Skip to content

Commit 4ef096b

Browse files
committed
Handle non-unique edges in edge-dominance
This removes a quadratic behavior in assert-enabled builds. GVN propagates the equivalence from a condition into the blocks guarded by the condition. E.g. for 'if (a == 7) { ... }', 'a' will be replaced in the block with 7. It does this by replacing all the uses of 'a' that are dominated by the true edge. For a switch with N cases and U uses of the value, this will mean N * U calls to 'dominates'. Asserting isSingleEdge in 'dominates' make this N^2 * U because this function checks for the uniqueness of the edge. I.e. traverses each edge between the SwitchInst's block and the cases. The change removes the assert and makes 'dominates' works correctly in the presence of non-unique edges. This brings build time down by an order of magnitude for an input that has ~10k cases in a switch statement. Differential Revision: https://reviews.llvm.org/D33584 llvm-svn: 304721
1 parent ad12580 commit 4ef096b

File tree

3 files changed

+65
-13
lines changed

3 files changed

+65
-13
lines changed

llvm/include/llvm/IR/Dominators.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class BasicBlockEdge {
6666
return End;
6767
}
6868

69+
/// Check if this is the only edge between Start and End.
6970
bool isSingleEdge() const;
7071
};
7172

@@ -143,6 +144,11 @@ class DominatorTree : public DominatorTreeBase<BasicBlock> {
143144
bool dominates(const Instruction *Def, const Use &U) const;
144145
bool dominates(const Instruction *Def, const Instruction *User) const;
145146
bool dominates(const Instruction *Def, const BasicBlock *BB) const;
147+
148+
/// Return true if an edge dominates a use.
149+
///
150+
/// If BBE is not a unique edge between start and end of the edge, it can
151+
/// never dominate the use.
146152
bool dominates(const BasicBlockEdge &BBE, const Use &U) const;
147153
bool dominates(const BasicBlockEdge &BBE, const BasicBlock *BB) const;
148154

llvm/lib/IR/Dominators.cpp

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,6 @@ bool DominatorTree::dominates(const Instruction *Def,
150150

151151
bool DominatorTree::dominates(const BasicBlockEdge &BBE,
152152
const BasicBlock *UseBB) const {
153-
// Assert that we have a single edge. We could handle them by simply
154-
// returning false, but since isSingleEdge is linear on the number of
155-
// edges, the callers can normally handle them more efficiently.
156-
assert(BBE.isSingleEdge() &&
157-
"This function is not efficient in handling multiple edges");
158-
159153
// If the BB the edge ends in doesn't dominate the use BB, then the
160154
// edge also doesn't.
161155
const BasicBlock *Start = BBE.getStart();
@@ -188,11 +182,17 @@ bool DominatorTree::dominates(const BasicBlockEdge &BBE,
188182
// trivially dominates itself, so we only have to find if it dominates the
189183
// other predecessors. Since the only way out of X is via NormalDest, X can
190184
// only properly dominate a node if NormalDest dominates that node too.
185+
int IsDuplicateEdge = 0;
191186
for (const_pred_iterator PI = pred_begin(End), E = pred_end(End);
192187
PI != E; ++PI) {
193188
const BasicBlock *BB = *PI;
194-
if (BB == Start)
189+
if (BB == Start) {
190+
// If there are multiple edges between Start and End, by definition they
191+
// can't dominate anything.
192+
if (IsDuplicateEdge++)
193+
return false;
195194
continue;
195+
}
196196

197197
if (!dominates(End, BB))
198198
return false;
@@ -201,12 +201,6 @@ bool DominatorTree::dominates(const BasicBlockEdge &BBE,
201201
}
202202

203203
bool DominatorTree::dominates(const BasicBlockEdge &BBE, const Use &U) const {
204-
// Assert that we have a single edge. We could handle them by simply
205-
// returning false, but since isSingleEdge is linear on the number of
206-
// edges, the callers can normally handle them more efficiently.
207-
assert(BBE.isSingleEdge() &&
208-
"This function is not efficient in handling multiple edges");
209-
210204
Instruction *UserInst = cast<Instruction>(U.getUser());
211205
// A PHI in the end of the edge is dominated by it.
212206
PHINode *PN = dyn_cast<PHINode>(UserInst);

llvm/unittests/IR/DominatorTreeTest.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,55 @@ TEST(DominatorTree, Unreachable) {
257257
DT->verifyDomTree();
258258
});
259259
}
260+
261+
TEST(DominatorTree, NonUniqueEdges) {
262+
StringRef ModuleString =
263+
"define i32 @f(i32 %i, i32 *%p) {\n"
264+
"bb0:\n"
265+
" store i32 %i, i32 *%p\n"
266+
" switch i32 %i, label %bb2 [\n"
267+
" i32 0, label %bb1\n"
268+
" i32 1, label %bb1\n"
269+
" ]\n"
270+
" bb1:\n"
271+
" ret i32 1\n"
272+
" bb2:\n"
273+
" ret i32 4\n"
274+
"}\n";
275+
276+
// Parse the module.
277+
LLVMContext Context;
278+
std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
279+
280+
runWithDomTree(
281+
*M, "f",
282+
[&](Function &F, DominatorTree *DT, DominatorTreeBase<BasicBlock> *PDT) {
283+
Function::iterator FI = F.begin();
284+
285+
BasicBlock *BB0 = &*FI++;
286+
BasicBlock *BB1 = &*FI++;
287+
BasicBlock *BB2 = &*FI++;
288+
289+
const TerminatorInst *TI = BB0->getTerminator();
290+
assert(TI->getNumSuccessors() == 3 && "Switch has three successors");
291+
292+
BasicBlockEdge Edge_BB0_BB2(BB0, TI->getSuccessor(0));
293+
assert(Edge_BB0_BB2.getEnd() == BB2 &&
294+
"Default label is the 1st successor");
295+
296+
BasicBlockEdge Edge_BB0_BB1_a(BB0, TI->getSuccessor(1));
297+
assert(Edge_BB0_BB1_a.getEnd() == BB1 && "BB1 is the 2nd successor");
298+
299+
BasicBlockEdge Edge_BB0_BB1_b(BB0, TI->getSuccessor(2));
300+
assert(Edge_BB0_BB1_b.getEnd() == BB1 && "BB1 is the 3rd successor");
301+
302+
EXPECT_TRUE(DT->dominates(Edge_BB0_BB2, BB2));
303+
EXPECT_FALSE(DT->dominates(Edge_BB0_BB2, BB1));
304+
305+
EXPECT_FALSE(DT->dominates(Edge_BB0_BB1_a, BB1));
306+
EXPECT_FALSE(DT->dominates(Edge_BB0_BB1_b, BB1));
307+
308+
EXPECT_FALSE(DT->dominates(Edge_BB0_BB1_a, BB2));
309+
EXPECT_FALSE(DT->dominates(Edge_BB0_BB1_b, BB2));
310+
});
311+
}

0 commit comments

Comments
 (0)