@@ -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