llvm.org GIT mirror llvm / d5c86e9
Add an optional list of blocks to avoid when looking for a path in isPotentiallyReachable. The leads to some ambiguous overloads, so update three callers. Differential Revision: https://reviews.llvm.org/D60085 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357447 91177308-0d34-0410-b5e6-96231b3b80d8 Nick Lewycky 4 months ago
6 changed file(s) with 161 addition(s) and 51 deletion(s). Raw diff Collapse all Expand all
4646 bool isCriticalEdge(const Instruction *TI, unsigned SuccNum,
4747 bool AllowIdenticalEdges = false);
4848
49 /// Determine whether instruction 'To' is reachable from 'From',
50 /// returning true if uncertain.
49 /// Determine whether instruction 'To' is reachable from 'From', without passing
50 /// through any blocks in ExclusionSet, returning true if uncertain.
5151 ///
5252 /// Determine whether there is a path from From to To within a single function.
5353 /// Returns false only if we can prove that once 'From' has been executed then
6161 /// we find a block that dominates the block containing 'To'. DT is most useful
6262 /// on branchy code but not loops, and LI is most useful on code with loops but
6363 /// does not help on branchy code outside loops.
64 bool isPotentiallyReachable(const Instruction *From, const Instruction *To,
65 const DominatorTree *DT = nullptr,
66 const LoopInfo *LI = nullptr);
64 bool isPotentiallyReachable(
65 const Instruction *From, const Instruction *To,
66 const SmallPtrSetImpl *ExclusionSet = nullptr,
67 const DominatorTree *DT = nullptr, const LoopInfo *LI = nullptr);
6768
6869 /// Determine whether block 'To' is reachable from 'From', returning
6970 /// true if uncertain.
8687 BasicBlock *StopBB,
8788 const DominatorTree *DT = nullptr,
8889 const LoopInfo *LI = nullptr);
90
91 /// Determine whether there is at least one path from a block in
92 /// 'Worklist' to 'StopBB' without passing through any blocks in
93 /// 'ExclusionSet', returning true if uncertain.
94 ///
95 /// Determine whether there is a path from at least one block in Worklist to
96 /// StopBB within a single function without passing through any of the blocks
97 /// in 'ExclusionSet'. Returns false only if we can prove that once any block
98 /// in 'Worklist' has been reached then 'StopBB' can not be executed.
99 /// Conservatively returns true.
100 bool isPotentiallyReachableFromMany(
101 SmallVectorImpl &Worklist, BasicBlock *StopBB,
102 const SmallPtrSetImpl *ExclusionSet,
103 const DominatorTree *DT = nullptr, const LoopInfo *LI = nullptr);
89104
90105 /// Return true if the control flow in \p RPOTraversal is irreducible.
91106 ///
19051905 // the Values cannot come from different iterations of a potential cycle the
19061906 // phi nodes could be involved in.
19071907 for (auto *P : VisitedPhiBBs)
1908 if (isPotentiallyReachable(&P->front(), Inst, DT, LI))
1908 if (isPotentiallyReachable(&P->front(), Inst, nullptr, DT, LI))
19091909 return false;
19101910
19111911 return true;
1111 //===----------------------------------------------------------------------===//
1212
1313 #include "llvm/Analysis/CFG.h"
14 #include "llvm/ADT/SmallPtrSet.h"
1415 #include "llvm/ADT/SmallSet.h"
1516 #include "llvm/Analysis/LoopInfo.h"
1617 #include "llvm/IR/Dominators.h"
118119 return L;
119120 }
120121
121 // True if there is a loop which contains both BB1 and BB2.
122 static bool loopContainsBoth(const LoopInfo *LI,
123 const BasicBlock *BB1, const BasicBlock *BB2) {
124 const Loop *L1 = getOutermostLoop(LI, BB1);
125 const Loop *L2 = getOutermostLoop(LI, BB2);
126 return L1 != nullptr && L1 == L2;
127 }
128
129122 bool llvm::isPotentiallyReachableFromMany(
130123 SmallVectorImpl &Worklist, BasicBlock *StopBB,
131 const DominatorTree *DT, const LoopInfo *LI) {
124 const SmallPtrSetImpl *ExclusionSet, const DominatorTree *DT,
125 const LoopInfo *LI) {
132126 // When the stop block is unreachable, it's dominated from everywhere,
133127 // regardless of whether there's a path between the two blocks.
134128 if (DT && !DT->isReachableFromEntry(StopBB))
135129 DT = nullptr;
130
131 // We can't skip directly from a block that dominates the stop block if the
132 // exclusion block is potentially in between.
133 if (ExclusionSet && !ExclusionSet->empty())
134 DT = nullptr;
135
136 // Normally any block in a loop is reachable from any other block in a loop,
137 // however excluded blocks might partition the body of a loop to make that
138 // untrue.
139 SmallPtrSet LoopsWithHoles;
140 if (LI && ExclusionSet) {
141 for (auto BB : *ExclusionSet) {
142 if (const Loop *L = getOutermostLoop(LI, BB))
143 LoopsWithHoles.insert(L);
144 }
145 }
146
147 const Loop *StopLoop = LI ? getOutermostLoop(LI, StopBB) : nullptr;
136148
137149 // Limit the number of blocks we visit. The goal is to avoid run-away compile
138150 // times on large CFGs without hampering sensible code. Arbitrarily chosen.
144156 continue;
145157 if (BB == StopBB)
146158 return true;
159 if (ExclusionSet && ExclusionSet->count(BB))
160 continue;
147161 if (DT && DT->dominates(BB, StopBB))
148162 return true;
149 if (LI && loopContainsBoth(LI, BB, StopBB))
150 return true;
163
164 const Loop *Outer = nullptr;
165 if (LI) {
166 Outer = getOutermostLoop(LI, BB);
167 // If we're in a loop with a hole, not all blocks in the loop are
168 // reachable from all other blocks. That implies we can't simply jump to
169 // the loop's exit blocks, as that exit might need to pass through an
170 // excluded block. Clear Outer so we process BB's successors.
171 if (LoopsWithHoles.count(Outer))
172 Outer = nullptr;
173 if (StopLoop && Outer == StopLoop)
174 return true;
175 }
151176
152177 if (!--Limit) {
153178 // We haven't been able to prove it one way or the other. Conservatively
155180 return true;
156181 }
157182
158 if (const Loop *Outer = LI ? getOutermostLoop(LI, BB) : nullptr) {
183 if (Outer) {
159184 // All blocks in a single loop are reachable from all other blocks. From
160185 // any of these blocks, we can skip directly to the exits of the loop,
161186 // ignoring any other blocks inside the loop body.
179204 Worklist.push_back(const_cast(A));
180205
181206 return isPotentiallyReachableFromMany(Worklist, const_cast(B),
182 DT, LI);
183 }
184
185 bool llvm::isPotentiallyReachable(const Instruction *A, const Instruction *B,
186 const DominatorTree *DT, const LoopInfo *LI) {
207 nullptr, DT, LI);
208 }
209
210 bool llvm::isPotentiallyReachable(
211 const Instruction *A, const Instruction *B,
212 const SmallPtrSetImpl *ExclusionSet, const DominatorTree *DT,
213 const LoopInfo *LI) {
187214 assert(A->getParent()->getParent() == B->getParent()->getParent() &&
188215 "This analysis is function-local!");
189216
229256 if (DT->isReachableFromEntry(A->getParent()) !=
230257 DT->isReachableFromEntry(B->getParent()))
231258 return false;
232 if (A->getParent() == &A->getParent()->getParent()->getEntryBlock() &&
233 DT->isReachableFromEntry(B->getParent()))
234 return true;
235 if (B->getParent() == &A->getParent()->getParent()->getEntryBlock() &&
236 DT->isReachableFromEntry(A->getParent()))
237 return false;
259 if (!ExclusionSet || ExclusionSet->empty()) {
260 if (A->getParent() == &A->getParent()->getParent()->getEntryBlock() &&
261 DT->isReachableFromEntry(B->getParent()))
262 return true;
263 if (B->getParent() == &A->getParent()->getParent()->getEntryBlock() &&
264 DT->isReachableFromEntry(A->getParent()))
265 return false;
266 }
238267 }
239268
240269 return isPotentiallyReachableFromMany(
241 Worklist, const_cast(B->getParent()), DT, LI);
242 }
270 Worklist, const_cast(B->getParent()), ExclusionSet, DT, LI);
271 }
100100
101101 SmallVector Worklist;
102102 Worklist.append(succ_begin(BB), succ_end(BB));
103 return !isPotentiallyReachableFromMany(Worklist, BB, DT);
103 return !isPotentiallyReachableFromMany(Worklist, BB, nullptr, DT);
104104 }
105105
106106 // If the value is defined in the same basic block as use and BeforeHere,
107107 // there is no need to explore the use if BeforeHere dominates use.
108108 // Check whether there is a path from I to BeforeHere.
109109 if (BeforeHere != I && DT->dominates(BeforeHere, I) &&
110 !isPotentiallyReachable(I, BeforeHere, DT))
110 !isPotentiallyReachable(I, BeforeHere, nullptr, DT))
111111 return true;
112112
113113 return false;
144144 size_t ResumeIndex = 0;
145145 for (auto *RI : Resumes) {
146146 for (auto *LP : CleanupLPads) {
147 if (isPotentiallyReachable(LP, RI, DT)) {
147 if (isPotentiallyReachable(LP, RI, nullptr, DT)) {
148148 ResumeReachable.set(ResumeIndex);
149149 break;
150150 }
66 //===----------------------------------------------------------------------===//
77
88 #include "llvm/Analysis/CFG.h"
9 #include "llvm/ADT/SmallPtrSet.h"
910 #include "llvm/Analysis/LoopInfo.h"
1011 #include "llvm/AsmParser/Parser.h"
1112 #include "llvm/IR/Dominators.h"
5657 report_fatal_error("@test must have an instruction %A");
5758 if (B == nullptr)
5859 report_fatal_error("@test must have an instruction %B");
60
61 assert(ExclusionSet.empty());
62 for (auto I = F->begin(), E = F->end(); I != E; ++I) {
63 if (I->hasName() && I->getName().startswith("excluded"))
64 ExclusionSet.insert(&*I);
65 }
5966 }
6067
6168 void ExpectPath(bool ExpectedResult) {
6269 static char ID;
6370 class IsPotentiallyReachableTestPass : public FunctionPass {
6471 public:
65 IsPotentiallyReachableTestPass(bool ExpectedResult,
66 Instruction *A, Instruction *B)
67 : FunctionPass(ID), ExpectedResult(ExpectedResult), A(A), B(B) {}
68
69 static int initialize() {
70 PassInfo *PI = new PassInfo("isPotentiallyReachable testing pass",
71 "", &ID, nullptr, true, true);
72 PassRegistry::getPassRegistry()->registerPass(*PI, false);
73 initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry());
74 initializeDominatorTreeWrapperPassPass(
75 *PassRegistry::getPassRegistry());
76 return 0;
72 IsPotentiallyReachableTestPass(bool ExpectedResult, Instruction *A,
73 Instruction *B,
74 SmallPtrSet ExclusionSet)
75 : FunctionPass(ID), ExpectedResult(ExpectedResult), A(A), B(B),
76 ExclusionSet(ExclusionSet) {}
77
78 static int initialize() {
79 PassInfo *PI = new PassInfo("isPotentiallyReachable testing pass", "",
80 &ID, nullptr, true, true);
81 PassRegistry::getPassRegistry()->registerPass(*PI, false);
82 initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry());
83 initializeDominatorTreeWrapperPassPass(
84 *PassRegistry::getPassRegistry());
85 return 0;
7786 }
7887
7988 void getAnalysisUsage(AnalysisUsage &AU) const override {
8998 LoopInfo *LI = &getAnalysis().getLoopInfo();
9099 DominatorTree *DT =
91100 &getAnalysis().getDomTree();
92 EXPECT_EQ(isPotentiallyReachable(A, B, nullptr, nullptr),
101 EXPECT_EQ(isPotentiallyReachable(A, B, &ExclusionSet, nullptr, nullptr),
93102 ExpectedResult);
94 EXPECT_EQ(isPotentiallyReachable(A, B, DT, nullptr), ExpectedResult);
95 EXPECT_EQ(isPotentiallyReachable(A, B, nullptr, LI), ExpectedResult);
96 EXPECT_EQ(isPotentiallyReachable(A, B, DT, LI), ExpectedResult);
103 EXPECT_EQ(isPotentiallyReachable(A, B, &ExclusionSet, DT, nullptr),
104 ExpectedResult);
105 EXPECT_EQ(isPotentiallyReachable(A, B, &ExclusionSet, nullptr, LI),
106 ExpectedResult);
107 EXPECT_EQ(isPotentiallyReachable(A, B, &ExclusionSet, DT, LI),
108 ExpectedResult);
97109 return false;
98110 }
99111 bool ExpectedResult;
100112 Instruction *A, *B;
113 SmallPtrSet ExclusionSet;
101114 };
102115
103116 static int initialize = IsPotentiallyReachableTestPass::initialize();
104117 (void)initialize;
105118
106119 IsPotentiallyReachableTestPass *P =
107 new IsPotentiallyReachableTestPass(ExpectedResult, A, B);
120 new IsPotentiallyReachableTestPass(ExpectedResult, A, B, ExclusionSet);
108121 legacy::PassManager PM;
109122 PM.add(P);
110123 PM.run(*M);
113126 LLVMContext Context;
114127 std::unique_ptr M;
115128 Instruction *A, *B;
129 SmallPtrSet ExclusionSet;
116130 };
117131
118132 }
424438 "}");
425439 ExpectPath(false);
426440 }
441
442 TEST_F(IsPotentiallyReachableTest, SimpleExclusionTest) {
443 ParseAssembly("define void @test() {\n"
444 "entry:\n"
445 " %A = bitcast i8 undef to i8\n"
446 " br label %excluded\n"
447 "excluded:\n"
448 " br label %exit\n"
449 "exit:\n"
450 " %B = bitcast i8 undef to i8\n"
451 " ret void\n"
452 "}");
453 ExpectPath(false);
454 }
455
456 TEST_F(IsPotentiallyReachableTest, DiamondExcludedTest) {
457 ParseAssembly("declare i1 @switch()\n"
458 "\n"
459 "define void @test() {\n"
460 "entry:\n"
461 " %x = call i1 @switch()\n"
462 " %A = bitcast i8 undef to i8\n"
463 " br i1 %x, label %excluded.1, label %excluded.2\n"
464 "excluded.1:\n"
465 " br label %exit\n"
466 "excluded.2:\n"
467 " br label %exit\n"
468 "exit:\n"
469 " %B = bitcast i8 undef to i8\n"
470 " ret void\n"
471 "}");
472 ExpectPath(false);
473 }
474
475 TEST_F(IsPotentiallyReachableTest, DiamondOneSideExcludedTest) {
476 ParseAssembly("declare i1 @switch()\n"
477 "\n"
478 "define void @test() {\n"
479 "entry:\n"
480 " %x = call i1 @switch()\n"
481 " %A = bitcast i8 undef to i8\n"
482 " br i1 %x, label %excluded, label %diamond\n"
483 "excluded:\n"
484 " br label %exit\n"
485 "diamond:\n"
486 " br label %exit\n"
487 "exit:\n"
488 " %B = bitcast i8 undef to i8\n"
489 " ret void\n"
490 "}");
491 ExpectPath(true);
492 }