@@ -243,11 +243,10 @@ class PointerReplacer {
243243 void replacePointer (Value *V);
244244
245245private:
246- bool collectUsersRecursive (Instruction &I);
247246 void replace (Instruction *I);
248- Value *getReplacement (Value *I);
247+ Value *getReplacement (Value *V) const { return WorkMap. lookup (V); }
249248 bool isAvailable (Instruction *I) const {
250- return I == &Root || Worklist .contains (I);
249+ return I == &Root || UsersToReplace .contains (I);
251250 }
252251
253252 bool isEqualOrValidAddrSpaceCast (const Instruction *I,
@@ -259,8 +258,7 @@ class PointerReplacer {
259258 return (FromAS == ToAS) || IC.isValidAddrSpaceCast (FromAS, ToAS);
260259 }
261260
262- SmallPtrSet<Instruction *, 32 > ValuesToRevisit;
263- SmallSetVector<Instruction *, 4 > Worklist;
261+ SmallSetVector<Instruction *, 32 > UsersToReplace;
264262 MapVector<Value *, Value *> WorkMap;
265263 InstCombinerImpl &IC;
266264 Instruction &Root;
@@ -269,80 +267,119 @@ class PointerReplacer {
269267} // end anonymous namespace
270268
271269bool PointerReplacer::collectUsers () {
272- if (!collectUsersRecursive (Root))
273- return false ;
274-
275- // Ensure that all outstanding (indirect) users of I
276- // are inserted into the Worklist. Return false
277- // otherwise.
278- return llvm::set_is_subset (ValuesToRevisit, Worklist);
279- }
270+ SmallVector<Instruction *> Worklist;
271+ SmallSetVector<Instruction *, 32 > ValuesToRevisit;
272+
273+ auto PushUsersToWorklist = [&](Instruction *Inst) {
274+ for (auto *U : Inst->users ())
275+ if (auto *I = dyn_cast<Instruction>(U))
276+ if (!isAvailable (I) && !ValuesToRevisit.contains (I))
277+ Worklist.emplace_back (I);
278+ };
280279
281- bool PointerReplacer::collectUsersRecursive (Instruction &I) {
282- for ( auto *U : I. users ()) {
283- auto *Inst = cast<Instruction>(&*U );
280+ PushUsersToWorklist (&Root);
281+ while (!Worklist. empty ()) {
282+ Instruction *Inst = Worklist. pop_back_val ( );
284283 if (auto *Load = dyn_cast<LoadInst>(Inst)) {
285284 if (Load->isVolatile ())
286285 return false ;
287- Worklist .insert (Load);
286+ UsersToReplace .insert (Load);
288287 } else if (auto *PHI = dyn_cast<PHINode>(Inst)) {
289- // All incoming values must be instructions for replacability
290- if (any_of (PHI->incoming_values (),
291- [](Value *V) { return !isa<Instruction>(V); }))
292- return false ;
293-
294- // If at least one incoming value of the PHI is not in Worklist,
295- // store the PHI for revisiting and skip this iteration of the
296- // loop.
297- if (any_of (PHI->incoming_values (), [this ](Value *V) {
298- return !isAvailable (cast<Instruction>(V));
288+ // / TODO: Handle poison and null pointers for PHI and select.
289+ // If all incoming values are available, mark this PHI as
290+ // replacable and push it's users into the worklist.
291+ bool IsReplaceable = true ;
292+ if (all_of (PHI->incoming_values (), [&](Value *V) {
293+ if (!isa<Instruction>(V))
294+ return IsReplaceable = false ;
295+ return isAvailable (cast<Instruction>(V));
299296 })) {
300- ValuesToRevisit.insert (Inst);
297+ UsersToReplace.insert (PHI);
298+ PushUsersToWorklist (PHI);
301299 continue ;
302300 }
303301
304- Worklist.insert (PHI);
305- if (!collectUsersRecursive (*PHI))
306- return false ;
307- } else if (auto *SI = dyn_cast<SelectInst>(Inst)) {
308- if (!isa<Instruction>(SI->getTrueValue ()) ||
309- !isa<Instruction>(SI->getFalseValue ()))
302+ // Either an incoming value is not an instruction or not all
303+ // incoming values are available. If this PHI was already
304+ // visited prior to this iteration, return false.
305+ if (!IsReplaceable || !ValuesToRevisit.insert (PHI))
310306 return false ;
311307
312- if (!isAvailable (cast<Instruction>(SI->getTrueValue ())) ||
313- !isAvailable (cast<Instruction>(SI->getFalseValue ()))) {
314- ValuesToRevisit.insert (Inst);
315- continue ;
308+ // Push PHI back into the stack, followed by unavailable
309+ // incoming values.
310+ Worklist.emplace_back (PHI);
311+ for (unsigned Idx = 0 ; Idx < PHI->getNumIncomingValues (); ++Idx) {
312+ auto *IncomingValue = cast<Instruction>(PHI->getIncomingValue (Idx));
313+ if (UsersToReplace.contains (IncomingValue))
314+ continue ;
315+ if (!ValuesToRevisit.insert (IncomingValue))
316+ return false ;
317+ Worklist.emplace_back (IncomingValue);
316318 }
317- Worklist.insert (SI);
318- if (!collectUsersRecursive (*SI))
319- return false ;
320- } else if (isa<GetElementPtrInst>(Inst)) {
321- Worklist.insert (Inst);
322- if (!collectUsersRecursive (*Inst))
319+ } else if (auto *SI = dyn_cast<SelectInst>(Inst)) {
320+ auto *TrueInst = dyn_cast<Instruction>(SI->getTrueValue ());
321+ auto *FalseInst = dyn_cast<Instruction>(SI->getFalseValue ());
322+ if (!TrueInst || !FalseInst)
323323 return false ;
324+
325+ UsersToReplace.insert (SI);
326+ PushUsersToWorklist (SI);
327+ } else if (auto *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
328+ UsersToReplace.insert (GEP);
329+ PushUsersToWorklist (GEP);
324330 } else if (auto *MI = dyn_cast<MemTransferInst>(Inst)) {
325331 if (MI->isVolatile ())
326332 return false ;
327- Worklist .insert (Inst);
333+ UsersToReplace .insert (Inst);
328334 } else if (isEqualOrValidAddrSpaceCast (Inst, FromAS)) {
329- Worklist.insert (Inst);
330- if (!collectUsersRecursive (*Inst))
331- return false ;
335+ UsersToReplace.insert (Inst);
336+ PushUsersToWorklist (Inst);
332337 } else if (Inst->isLifetimeStartOrEnd ()) {
333338 continue ;
334339 } else {
335340 // TODO: For arbitrary uses with address space mismatches, should we check
336341 // if we can introduce a valid addrspacecast?
337- LLVM_DEBUG (dbgs () << " Cannot handle pointer user: " << *U << ' \n ' );
342+ LLVM_DEBUG (dbgs () << " Cannot handle pointer user: " << *Inst << ' \n ' );
338343 return false ;
339344 }
340345 }
341346
342347 return true ;
343348}
344349
345- Value *PointerReplacer::getReplacement (Value *V) { return WorkMap.lookup (V); }
350+ void PointerReplacer::replacePointer (Value *V) {
351+ assert (cast<PointerType>(Root.getType ()) != cast<PointerType>(V->getType ()) &&
352+ " Invalid usage" );
353+ WorkMap[&Root] = V;
354+ SmallVector<Instruction *> Worklist;
355+ SetVector<Instruction *> PostOrderWorklist;
356+ SmallPtrSet<Instruction *, 32 > Visited;
357+
358+ // Perform a postorder traversal of the users of Root.
359+ Worklist.push_back (&Root);
360+ while (!Worklist.empty ()) {
361+ Instruction *I = Worklist.back ();
362+
363+ // If I has not been processed before, push each of its
364+ // replacable users into the worklist.
365+ if (Visited.insert (I).second ) {
366+ for (auto *U : I->users ()) {
367+ auto *UserInst = cast<Instruction>(U);
368+ if (UsersToReplace.contains (UserInst) && !Visited.contains (UserInst))
369+ Worklist.push_back (UserInst);
370+ }
371+ // Otherwise, users of I have already been pushed into
372+ // the PostOrderWorklist. Push I as well.
373+ } else {
374+ PostOrderWorklist.insert (I);
375+ Worklist.pop_back ();
376+ }
377+ }
378+
379+ // Replace pointers in reverse-postorder.
380+ for (Instruction *I : reverse (PostOrderWorklist))
381+ replace (I);
382+ }
346383
347384void PointerReplacer::replace (Instruction *I) {
348385 if (getReplacement (I))
@@ -364,13 +401,15 @@ void PointerReplacer::replace(Instruction *I) {
364401 // replacement (new value).
365402 WorkMap[NewI] = NewI;
366403 } else if (auto *PHI = dyn_cast<PHINode>(I)) {
367- Type *NewTy = getReplacement (PHI->getIncomingValue (0 ))->getType ();
368- auto *NewPHI = PHINode::Create (NewTy, PHI->getNumIncomingValues (),
369- PHI->getName (), PHI->getIterator ());
370- for (unsigned int I = 0 ; I < PHI->getNumIncomingValues (); ++I)
371- NewPHI->addIncoming (getReplacement (PHI->getIncomingValue (I)),
372- PHI->getIncomingBlock (I));
373- WorkMap[PHI] = NewPHI;
404+ // Create a new PHI by replacing any incoming value that is a user of the
405+ // root pointer and has a replacement.
406+ Value *V = WorkMap.lookup (PHI->getIncomingValue (0 ));
407+ PHI->mutateType (V ? V->getType () : PHI->getIncomingValue (0 )->getType ());
408+ for (unsigned int I = 0 ; I < PHI->getNumIncomingValues (); ++I) {
409+ Value *V = WorkMap.lookup (PHI->getIncomingValue (I));
410+ PHI->setIncomingValue (I, V ? V : PHI->getIncomingValue (I));
411+ }
412+ WorkMap[PHI] = PHI;
374413 } else if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
375414 auto *V = getReplacement (GEP->getPointerOperand ());
376415 assert (V && " Operand not replaced" );
@@ -434,18 +473,6 @@ void PointerReplacer::replace(Instruction *I) {
434473 }
435474}
436475
437- void PointerReplacer::replacePointer (Value *V) {
438- #ifndef NDEBUG
439- auto *PT = cast<PointerType>(Root.getType ());
440- auto *NT = cast<PointerType>(V->getType ());
441- assert (PT != NT && " Invalid usage" );
442- #endif
443- WorkMap[&Root] = V;
444-
445- for (Instruction *Workitem : Worklist)
446- replace (Workitem);
447- }
448-
449476Instruction *InstCombinerImpl::visitAllocaInst (AllocaInst &AI) {
450477 if (auto *I = simplifyAllocaArraySize (*this , AI, DT))
451478 return I;
0 commit comments