diff --git a/llvm/include/llvm/Analysis/MemorySSAUpdater.h b/llvm/include/llvm/Analysis/MemorySSAUpdater.h index 96bf99922d848..8c03f241e8609 100644 --- a/llvm/include/llvm/Analysis/MemorySSAUpdater.h +++ b/llvm/include/llvm/Analysis/MemorySSAUpdater.h @@ -257,7 +257,6 @@ class MemorySSAUpdater { MemoryAccess * getPreviousDefRecursive(BasicBlock *, DenseMap> &); - MemoryAccess *recursePhi(MemoryAccess *Phi); MemoryAccess *tryRemoveTrivialPhi(MemoryPhi *Phi); template MemoryAccess *tryRemoveTrivialPhi(MemoryPhi *Phi, RangeType &Operands); diff --git a/llvm/lib/Analysis/MemorySSAUpdater.cpp b/llvm/lib/Analysis/MemorySSAUpdater.cpp index ecfecb03c3757..68e035e82439d 100644 --- a/llvm/lib/Analysis/MemorySSAUpdater.cpp +++ b/llvm/lib/Analysis/MemorySSAUpdater.cpp @@ -18,12 +18,17 @@ #include "llvm/Analysis/MemorySSA.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Dominators.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include #define DEBUG_TYPE "memoryssa" using namespace llvm; +static cl::opt TrivialPhiProcessingLimit( + "mssaupdater-processing-limit", cl::Hidden, cl::init(20), + cl::desc("The worklist limit for trivial phi removal (default = 20)")); + // This is the marker algorithm from "Simple and Efficient Construction of // Static Single Assignment Form" // The simple, non-marker algorithm places phi nodes at any join @@ -181,18 +186,6 @@ MemoryAccess *MemorySSAUpdater::getPreviousDefFromEnd( return getPreviousDefRecursive(BB, CachedPreviousDef); } -// Recurse over a set of phi uses to eliminate the trivial ones -MemoryAccess *MemorySSAUpdater::recursePhi(MemoryAccess *Phi) { - if (!Phi) - return nullptr; - TrackingVH Res(Phi); - SmallVector, 8> Uses; - std::copy(Phi->user_begin(), Phi->user_end(), std::back_inserter(Uses)); - for (auto &U : Uses) - if (MemoryPhi *UsePhi = dyn_cast(&*U)) - tryRemoveTrivialPhi(UsePhi); - return Res; -} // Eliminate trivial phis // Phis are trivial if they are defined either by themselves, or all the same @@ -230,9 +223,65 @@ MemoryAccess *MemorySSAUpdater::tryRemoveTrivialPhi(MemoryPhi *Phi, removeMemoryAccess(Phi); } - // We should only end up recursing in case we replaced something, in which - // case, we may have made other Phis trivial. - return recursePhi(Same); + // Continue traversal in a DFS worklist approach, in case we might find + // other trivial Phis. + if (!Same) + return nullptr; + + // Worklist approach to recursively removing trivial Phis. + SmallVector Worklist; + SmallSetVector Visited; + + for (auto U : Same->users()) { + if (dyn_cast(&*U)) + Worklist.push_back(&*U); + } + + while (!Worklist.empty() && Worklist.size() < TrivialPhiProcessingLimit) { + MemoryPhi *RecPhi = dyn_cast(&*(Worklist[Worklist.size() - 1])); + Worklist.pop_back(); + + if (!RecPhi || Visited.contains(RecPhi)) + continue; + auto RecOperands = RecPhi->operands(); + + // Repeat above algorithm. + if (NonOptPhis.count(RecPhi)) + continue; + + bool nextone = false; + MemoryAccess *RecSame = nullptr; + for (auto &Op : RecOperands) { + if (Op == RecPhi || Op == RecSame) + continue; + if (RecSame) { + nextone = true; + break; + } + RecSame = cast(&*Op); + } + + // Move on to the next Phi in the worklist. + if (nextone || RecSame == nullptr) + continue; + + if (RecPhi) { + if (RecPhi == Same) { + // Update the returned value + Same = RecSame; + } + Visited.insert(RecPhi); + RecPhi->replaceAllUsesWith(RecSame); + removeMemoryAccess(RecPhi); + } + + for (auto U : RecSame->users()) { + if (dyn_cast(&*U)) + Worklist.push_back(&*U); + } + } + + return Same; } void MemorySSAUpdater::insertUse(MemoryUse *MU, bool RenameUses) {