@@ -243,10 +243,11 @@ class PointerReplacer {
243243  void  replacePointer (Value *V);
244244
245245private: 
246+   bool  collectUsersRecursive (Instruction &I);
246247  void  replace (Instruction *I);
247-   Value *getReplacement (Value *V)  const  {  return  WorkMap. lookup (V); } 
248+   Value *getReplacement (Value *I); 
248249  bool  isAvailable (Instruction *I) const  {
249-     return  I == &Root || UsersToReplace .contains (I);
250+     return  I == &Root || Worklist .contains (I);
250251  }
251252
252253  bool  isEqualOrValidAddrSpaceCast (const  Instruction *I,
@@ -258,7 +259,8 @@ class PointerReplacer {
258259    return  (FromAS == ToAS) || IC.isValidAddrSpaceCast (FromAS, ToAS);
259260  }
260261
261-   SmallSetVector<Instruction *, 32 > UsersToReplace;
262+   SmallPtrSet<Instruction *, 32 > ValuesToRevisit;
263+   SmallSetVector<Instruction *, 4 > Worklist;
262264  MapVector<Value *, Value *> WorkMap;
263265  InstCombinerImpl &IC;
264266  Instruction &Root;
@@ -267,119 +269,80 @@ class PointerReplacer {
267269} //  end anonymous namespace
268270
269271bool  PointerReplacer::collectUsers () {
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-   };
272+   if  (!collectUsersRecursive (Root))
273+     return  false ;
279274
280-   PushUsersToWorklist (&Root);
281-   while  (!Worklist.empty ()) {
282-     Instruction *Inst = Worklist.pop_back_val ();
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+ }
280+ 
281+ bool  PointerReplacer::collectUsersRecursive (Instruction &I) {
282+   for  (auto  *U : I.users ()) {
283+     auto  *Inst = cast<Instruction>(&*U);
283284    if  (auto  *Load = dyn_cast<LoadInst>(Inst)) {
284285      if  (Load->isVolatile ())
285286        return  false ;
286-       UsersToReplace .insert (Load);
287+       Worklist .insert (Load);
287288    } else  if  (auto  *PHI = dyn_cast<PHINode>(Inst)) {
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));
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));
296299          })) {
297-         UsersToReplace.insert (PHI);
298-         PushUsersToWorklist (PHI);
300+         ValuesToRevisit.insert (Inst);
299301        continue ;
300302      }
301303
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))
304+       Worklist.insert (PHI);
305+       if  (!collectUsersRecursive (*PHI))
306306        return  false ;
307- 
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);
318-       }
319307    } 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)
308+       if  (!isa<Instruction>(SI->getTrueValue ()) ||
309+           !isa<Instruction>(SI->getFalseValue ()))
323310        return  false ;
324311
325-       UsersToReplace.insert (SI);
326-       PushUsersToWorklist (SI);
327-     } else  if  (auto  *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
328-       UsersToReplace.insert (GEP);
329-       PushUsersToWorklist (GEP);
312+       if  (!isAvailable (cast<Instruction>(SI->getTrueValue ())) ||
313+           !isAvailable (cast<Instruction>(SI->getFalseValue ()))) {
314+         ValuesToRevisit.insert (Inst);
315+         continue ;
316+       }
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))
323+         return  false ;
330324    } else  if  (auto  *MI = dyn_cast<MemTransferInst>(Inst)) {
331325      if  (MI->isVolatile ())
332326        return  false ;
333-       UsersToReplace .insert (Inst);
327+       Worklist .insert (Inst);
334328    } else  if  (isEqualOrValidAddrSpaceCast (Inst, FromAS)) {
335-       UsersToReplace.insert (Inst);
336-       PushUsersToWorklist (Inst);
329+       Worklist.insert (Inst);
330+       if  (!collectUsersRecursive (*Inst))
331+         return  false ;
337332    } else  if  (Inst->isLifetimeStartOrEnd ()) {
338333      continue ;
339334    } else  {
340335      //  TODO: For arbitrary uses with address space mismatches, should we check
341336      //  if we can introduce a valid addrspacecast?
342-       LLVM_DEBUG (dbgs () << " Cannot handle pointer user: "   << *Inst  << ' \n '  );
337+       LLVM_DEBUG (dbgs () << " Cannot handle pointer user: "   << *U  << ' \n '  );
343338      return  false ;
344339    }
345340  }
346341
347342  return  true ;
348343}
349344
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- }
345+ Value *PointerReplacer::getReplacement (Value *V) { return  WorkMap.lookup (V); }
383346
384347void  PointerReplacer::replace (Instruction *I) {
385348  if  (getReplacement (I))
@@ -401,15 +364,13 @@ void PointerReplacer::replace(Instruction *I) {
401364    //  replacement (new value).
402365    WorkMap[NewI] = NewI;
403366  } else  if  (auto  *PHI = dyn_cast<PHINode>(I)) {
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;
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;
413374  } else  if  (auto  *GEP = dyn_cast<GetElementPtrInst>(I)) {
414375    auto  *V = getReplacement (GEP->getPointerOperand ());
415376    assert (V && " Operand not replaced"  );
@@ -473,6 +434,18 @@ void PointerReplacer::replace(Instruction *I) {
473434  }
474435}
475436
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+ 
476449Instruction *InstCombinerImpl::visitAllocaInst (AllocaInst &AI) {
477450  if  (auto  *I = simplifyAllocaArraySize (*this , AI, DT))
478451    return  I;
0 commit comments