@@ -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  IsReplacable = true ;
292+       if  (all_of (PHI->incoming_values (), [&](Value *V) {
293+             if  (!isa<Instruction>(V))
294+               return  IsReplacable = 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  (!IsReplacable || !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))
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