1313#include " InstCombineInternal.h"
1414#include " llvm/ADT/MapVector.h"
1515#include " llvm/ADT/SetOperations.h"
16+ #include " llvm/ADT/SetVector.h"
1617#include " llvm/ADT/SmallString.h"
1718#include " llvm/ADT/Statistic.h"
1819#include " llvm/Analysis/AliasAnalysis.h"
2425#include " llvm/IR/PatternMatch.h"
2526#include " llvm/Transforms/InstCombine/InstCombiner.h"
2627#include " llvm/Transforms/Utils/Local.h"
28+ #include < stack>
2729using namespace llvm ;
2830using namespace PatternMatch ;
2931
@@ -244,11 +246,10 @@ class PointerReplacer {
244246 void replacePointer (Value *V);
245247
246248private:
247- bool collectUsersRecursive (Instruction &I);
248249 void replace (Instruction *I);
249250 Value *getReplacement (Value *I);
250251 bool isAvailable (Instruction *I) const {
251- return I == &Root || Worklist .contains (I);
252+ return I == &Root || UsersToReplace .contains (I);
252253 }
253254
254255 bool isEqualOrValidAddrSpaceCast (const Instruction *I,
@@ -260,8 +261,7 @@ class PointerReplacer {
260261 return (FromAS == ToAS) || IC.isValidAddrSpaceCast (FromAS, ToAS);
261262 }
262263
263- SmallPtrSet<Instruction *, 32 > ValuesToRevisit;
264- SmallSetVector<Instruction *, 4 > Worklist;
264+ SmallSetVector<Instruction *, 4 > UsersToReplace;
265265 MapVector<Value *, Value *> WorkMap;
266266 InstCombinerImpl &IC;
267267 Instruction &Root;
@@ -270,77 +270,87 @@ class PointerReplacer {
270270} // end anonymous namespace
271271
272272bool PointerReplacer::collectUsers () {
273- if (! collectUsersRecursive (Root))
274- return false ;
273+ std::stack<User *> Worklist;
274+ SmallSetVector<Instruction *, 4 > ValuesToRevisit ;
275275
276- // Ensure that all outstanding (indirect) users of I
277- // are inserted into the Worklist. Return false
278- // otherwise.
279- return llvm::set_is_subset (ValuesToRevisit, Worklist);
280- }
276+ auto PushUsersToWorklist = [&](Instruction *Inst) {
277+ for ( auto *U : Inst-> users ())
278+ if (isa<Instruction>(U) && ! isAvailable (cast<Instruction>(U)))
279+ Worklist. push (U );
280+ };
281281
282- bool PointerReplacer::collectUsersRecursive (Instruction &I) {
283- for (auto *U : I.users ()) {
284- auto *Inst = cast<Instruction>(&*U);
282+ PushUsersToWorklist (&Root);
283+ while (!Worklist.empty ()) {
284+ auto *Inst = dyn_cast<Instruction>(Worklist.top ());
285+ Worklist.pop ();
286+ if (!Inst)
287+ return false ;
288+ if (isAvailable (Inst))
289+ continue ;
285290 if (auto *Load = dyn_cast<LoadInst>(Inst)) {
286291 if (Load->isVolatile ())
287292 return false ;
288- Worklist .insert (Load);
293+ UsersToReplace .insert (Load);
289294 } else if (auto *PHI = dyn_cast<PHINode>(Inst)) {
290295 // All incoming values must be instructions for replacability
291296 if (any_of (PHI->incoming_values (),
292297 [](Value *V) { return !isa<Instruction>(V); }))
293298 return false ;
294299
295- // If at least one incoming value of the PHI is not in Worklist,
296- // store the PHI for revisiting and skip this iteration of the
297- // loop.
298- if (any_of (PHI->incoming_values (), [this ](Value *V) {
299- return !isAvailable (cast<Instruction>(V));
300- })) {
301- ValuesToRevisit.insert (Inst);
300+ // If all incoming values are available, mark this PHI as
301+ // replacable and push it's users into the worklist.
302+ if (all_of (PHI->incoming_values (),
303+ [&](Value *V) { return isAvailable (cast<Instruction>(V)); })) {
304+ UsersToReplace.insert (PHI);
305+ PushUsersToWorklist (PHI);
302306 continue ;
303307 }
304308
305- Worklist.insert (PHI);
306- if (!collectUsersRecursive (*PHI))
307- return false ;
308- } else if (auto *SI = dyn_cast<SelectInst>(Inst)) {
309- if (!isa<Instruction>(SI->getTrueValue ()) ||
310- !isa<Instruction>(SI->getFalseValue ()))
309+ // Not all incoming values are available. If this PHI was already
310+ // visited prior to this iteration, return false.
311+ if (ValuesToRevisit.contains (PHI))
311312 return false ;
312313
313- if (!isAvailable (cast<Instruction>(SI->getTrueValue ())) ||
314- !isAvailable (cast<Instruction>(SI->getFalseValue ()))) {
315- ValuesToRevisit.insert (Inst);
316- continue ;
314+ // Revisit PHI, after all it's incoming values have been visited.
315+ Worklist.push (PHI);
316+ ValuesToRevisit.insert (PHI);
317+ for (unsigned Idx = 0 ; Idx < PHI->getNumIncomingValues (); ++Idx) {
318+ auto *IncomingValue = cast<Instruction>(PHI->getIncomingValue (Idx));
319+ if (UsersToReplace.contains (IncomingValue))
320+ continue ;
321+ if (ValuesToRevisit.contains (IncomingValue))
322+ return false ;
323+ ValuesToRevisit.insert (IncomingValue);
324+ Worklist.push (IncomingValue);
317325 }
318- Worklist.insert (SI);
319- if (!collectUsersRecursive (*SI))
320- return false ;
321- } else if (isa<GetElementPtrInst>(Inst)) {
322- Worklist.insert (Inst);
323- if (!collectUsersRecursive (*Inst))
326+ } else if (auto *SI = dyn_cast<SelectInst>(Inst)) {
327+ auto *TrueInst = dyn_cast<Instruction>(SI->getTrueValue ());
328+ auto *FalseInst = dyn_cast<Instruction>(SI->getFalseValue ());
329+ if (!TrueInst || !FalseInst)
324330 return false ;
331+
332+ UsersToReplace.insert (SI);
333+ PushUsersToWorklist (SI);
334+ } else if (auto *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
335+ UsersToReplace.insert (GEP);
336+ PushUsersToWorklist (GEP);
325337 } else if (auto *MI = dyn_cast<MemTransferInst>(Inst)) {
326338 if (MI->isVolatile ())
327339 return false ;
328- Worklist .insert (Inst);
340+ UsersToReplace .insert (Inst);
329341 } else if (isEqualOrValidAddrSpaceCast (Inst, FromAS)) {
330- Worklist.insert (Inst);
331- if (!collectUsersRecursive (*Inst))
332- return false ;
342+ UsersToReplace.insert (Inst);
343+ PushUsersToWorklist (Inst);
333344 } else if (Inst->isLifetimeStartOrEnd ()) {
334345 continue ;
335346 } else {
336347 // TODO: For arbitrary uses with address space mismatches, should we check
337348 // if we can introduce a valid addrspacecast?
338- LLVM_DEBUG (dbgs () << " Cannot handle pointer user: " << *U << ' \n ' );
349+ LLVM_DEBUG (dbgs () << " Cannot handle pointer user: " << *Inst << ' \n ' );
339350 return false ;
340351 }
341352 }
342-
343- return true ;
353+ return llvm::set_is_subset (ValuesToRevisit, UsersToReplace);
344354}
345355
346356Value *PointerReplacer::getReplacement (Value *V) { return WorkMap.lookup (V); }
@@ -443,7 +453,7 @@ void PointerReplacer::replacePointer(Value *V) {
443453#endif
444454 WorkMap[&Root] = V;
445455
446- for (Instruction *Workitem : Worklist )
456+ for (Instruction *Workitem : UsersToReplace )
447457 replace (Workitem);
448458}
449459
0 commit comments