diff options
Diffstat (limited to 'llvm/lib/Analysis/CFG.cpp')
| -rw-r--r-- | llvm/lib/Analysis/CFG.cpp | 74 |
1 files changed, 62 insertions, 12 deletions
diff --git a/llvm/lib/Analysis/CFG.cpp b/llvm/lib/Analysis/CFG.cpp index 8528aa9f77e0..841b83505238 100644 --- a/llvm/lib/Analysis/CFG.cpp +++ b/llvm/lib/Analysis/CFG.cpp @@ -130,14 +130,21 @@ static const Loop *getOutermostLoop(const LoopInfo *LI, const BasicBlock *BB) { return L ? L->getOutermostLoop() : nullptr; } -bool llvm::isPotentiallyReachableFromMany( - SmallVectorImpl<BasicBlock *> &Worklist, const BasicBlock *StopBB, - const SmallPtrSetImpl<BasicBlock *> *ExclusionSet, const DominatorTree *DT, - const LoopInfo *LI) { - // When the stop block is unreachable, it's dominated from everywhere, +template <class StopSetT> +static bool isReachableImpl(SmallVectorImpl<BasicBlock *> &Worklist, + const StopSetT &StopSet, + const SmallPtrSetImpl<BasicBlock *> *ExclusionSet, + const DominatorTree *DT, const LoopInfo *LI) { + // When a stop block is unreachable, it's dominated from everywhere, // regardless of whether there's a path between the two blocks. - if (DT && !DT->isReachableFromEntry(StopBB)) - DT = nullptr; + if (DT) { + for (auto *BB : StopSet) { + if (!DT->isReachableFromEntry(BB)) { + DT = nullptr; + break; + } + } + } // We can't skip directly from a block that dominates the stop block if the // exclusion block is potentially in between. @@ -155,7 +162,13 @@ bool llvm::isPotentiallyReachableFromMany( } } - const Loop *StopLoop = LI ? getOutermostLoop(LI, StopBB) : nullptr; + SmallPtrSet<const Loop *, 2> StopLoops; + if (LI) { + for (auto *StopSetBB : StopSet) { + if (const Loop *L = getOutermostLoop(LI, StopSetBB)) + StopLoops.insert(L); + } + } unsigned Limit = DefaultMaxBBsToExplore; SmallPtrSet<const BasicBlock*, 32> Visited; @@ -163,12 +176,16 @@ bool llvm::isPotentiallyReachableFromMany( BasicBlock *BB = Worklist.pop_back_val(); if (!Visited.insert(BB).second) continue; - if (BB == StopBB) + if (StopSet.contains(BB)) return true; if (ExclusionSet && ExclusionSet->count(BB)) continue; - if (DT && DT->dominates(BB, StopBB)) - return true; + if (DT) { + if (llvm::any_of(StopSet, [&](const BasicBlock *StopBB) { + return DT->dominates(BB, StopBB); + })) + return true; + } const Loop *Outer = nullptr; if (LI) { @@ -179,7 +196,7 @@ bool llvm::isPotentiallyReachableFromMany( // excluded block. Clear Outer so we process BB's successors. if (LoopsWithHoles.count(Outer)) Outer = nullptr; - if (StopLoop && Outer == StopLoop) + if (StopLoops.contains(Outer)) return true; } @@ -204,6 +221,39 @@ bool llvm::isPotentiallyReachableFromMany( return false; } +template <class T> class SingleEntrySet { +public: + using const_iterator = const T *; + + SingleEntrySet(T Elem) : Elem(Elem) {} + + bool contains(T Other) const { return Elem == Other; } + + const_iterator begin() const { return &Elem; } + const_iterator end() const { return &Elem + 1; } + +private: + T Elem; +}; + +bool llvm::isPotentiallyReachableFromMany( + SmallVectorImpl<BasicBlock *> &Worklist, const BasicBlock *StopBB, + const SmallPtrSetImpl<BasicBlock *> *ExclusionSet, const DominatorTree *DT, + const LoopInfo *LI) { + return isReachableImpl<SingleEntrySet<const BasicBlock *>>( + Worklist, SingleEntrySet<const BasicBlock *>(StopBB), ExclusionSet, DT, + LI); +} + +bool llvm::isManyPotentiallyReachableFromMany( + SmallVectorImpl<BasicBlock *> &Worklist, + const SmallPtrSetImpl<const BasicBlock *> &StopSet, + const SmallPtrSetImpl<BasicBlock *> *ExclusionSet, const DominatorTree *DT, + const LoopInfo *LI) { + return isReachableImpl<SmallPtrSetImpl<const BasicBlock *>>( + Worklist, StopSet, ExclusionSet, DT, LI); +} + bool llvm::isPotentiallyReachable( const BasicBlock *A, const BasicBlock *B, const SmallPtrSetImpl<BasicBlock *> *ExclusionSet, const DominatorTree *DT, |
