Skip to content

Commit ed0fd56

Browse files
BreakCriticalEdges: do not split the critical edge from a CallBr indirect successor
Otherwise we'll fail the assertion in SplitBlockPredecessors() related to splitting the edges from CallBr's. Fixes: ClangBuiltLinux/linux#1161 Fixes: ClangBuiltLinux/linux#1252 Reviewed By: void, MaskRay, jyknight Differential Revision: https://reviews.llvm.org/D88438
1 parent 4a47da2 commit ed0fd56

File tree

3 files changed

+110
-8
lines changed

3 files changed

+110
-8
lines changed

llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,22 +158,21 @@ BasicBlock *llvm::SplitCriticalEdge(Instruction *TI, unsigned SuccNum,
158158
SmallVector<BasicBlock *, 4> LoopPreds;
159159
// Check if extra modifications will be required to preserve loop-simplify
160160
// form after splitting. If it would require splitting blocks with IndirectBr
161-
// terminators, bail out if preserving loop-simplify form is requested.
161+
// or CallBr terminators, bail out if preserving loop-simplify form is
162+
// requested.
162163
if (LI) {
163164
if (Loop *TIL = LI->getLoopFor(TIBB)) {
164165

165-
// The only that we can break LoopSimplify form by splitting a critical
166-
// edge is if after the split there exists some edge from TIL to DestBB
167-
// *and* the only edge into DestBB from outside of TIL is that of
166+
// The only way that we can break LoopSimplify form by splitting a
167+
// critical edge is if after the split there exists some edge from TIL to
168+
// DestBB *and* the only edge into DestBB from outside of TIL is that of
168169
// NewBB. If the first isn't true, then LoopSimplify still holds, NewBB
169170
// is the new exit block and it has no non-loop predecessors. If the
170171
// second isn't true, then DestBB was not in LoopSimplify form prior to
171172
// the split as it had a non-loop predecessor. In both of these cases,
172173
// the predecessor must be directly in TIL, not in a subloop, or again
173174
// LoopSimplify doesn't hold.
174-
for (pred_iterator I = pred_begin(DestBB), E = pred_end(DestBB); I != E;
175-
++I) {
176-
BasicBlock *P = *I;
175+
for (BasicBlock *P : predecessors(DestBB)) {
177176
if (P == TIBB)
178177
continue; // The new block is known.
179178
if (LI->getLoopFor(P) != TIL) {
@@ -186,7 +185,10 @@ BasicBlock *llvm::SplitCriticalEdge(Instruction *TI, unsigned SuccNum,
186185
// Loop-simplify form can be preserved, if we can split all in-loop
187186
// predecessors.
188187
if (any_of(LoopPreds, [](BasicBlock *Pred) {
189-
return isa<IndirectBrInst>(Pred->getTerminator());
188+
const Instruction *T = Pred->getTerminator();
189+
if (const auto *CBR = dyn_cast<CallBrInst>(T))
190+
return CBR->getDefaultDest() != Pred;
191+
return isa<IndirectBrInst>(T);
190192
})) {
191193
if (Options.PreserveLoopSimplify)
192194
return nullptr;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
; RUN: opt -loop-reduce %s -o - -S | FileCheck %s
2+
; RUN: opt -passes='loop(loop-reduce)' %s -o - -S | FileCheck %s
3+
4+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
5+
6+
define dso_local i32 @test1() local_unnamed_addr {
7+
entry:
8+
br label %for.cond
9+
10+
for.cond: ; preds = %for.inc, %entry
11+
; It's ok to modify this test in the future should be able to split critical
12+
; edges here, just noting that this is the critical edge that we care about.
13+
; CHECK: callbr void asm sideeffect "", "X,X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@test1, %cond.true.i), i8* blockaddress(@test1, %for.end))
14+
; CHECK-NEXT: to label %asm.fallthrough.i.i [label %cond.true.i, label %for.end]
15+
callbr void asm sideeffect "", "X,X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@test1, %cond.true.i), i8* blockaddress(@test1, %for.end))
16+
to label %asm.fallthrough.i.i [label %cond.true.i, label %for.end]
17+
18+
asm.fallthrough.i.i: ; preds = %for.cond
19+
unreachable
20+
21+
cond.true.i: ; preds = %for.cond
22+
br label %do.body.i.i.do.body.i.i_crit_edge
23+
24+
do.body.i.i.do.body.i.i_crit_edge: ; preds = %do.body.i.i.do.body.i.i_crit_edge, %cond.true.i
25+
%pgocount711 = phi i64 [ %0, %do.body.i.i.do.body.i.i_crit_edge ], [ 0, %cond.true.i ]
26+
%0 = add nuw nsw i64 %pgocount711, 1
27+
br i1 undef, label %do.body.i.i.rdrand_int.exit.i_crit_edge, label %do.body.i.i.do.body.i.i_crit_edge
28+
29+
do.body.i.i.rdrand_int.exit.i_crit_edge: ; preds = %do.body.i.i.do.body.i.i_crit_edge
30+
%1 = add i64 %0, undef
31+
br i1 undef, label %for.end, label %for.inc
32+
33+
for.inc: ; preds = %do.body.i.i.rdrand_int.exit.i_crit_edge
34+
br label %for.cond
35+
36+
for.end: ; preds = %do.body.i.i.rdrand_int.exit.i_crit_edge, %for.cond
37+
%pgocount.promoted24 = phi i64 [ undef, %for.cond ], [ %1, %do.body.i.i.rdrand_int.exit.i_crit_edge ]
38+
ret i32 undef
39+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
; RUN: opt -passes='loop(loop-reduce)' %s -o - -S | FileCheck %s
2+
3+
; Required metadata to trigger previously failing assertion.
4+
target datalayout = "e-m:e-i64:64-n32:64"
5+
6+
@f = external dso_local local_unnamed_addr global i32, align 4
7+
8+
declare i32 @a() local_unnamed_addr
9+
declare i32 @e(i32) local_unnamed_addr
10+
11+
define dso_local i32 @b() {
12+
entry:
13+
%call = tail call i32 @a()
14+
%tobool.not = icmp eq i32 %call, 0
15+
br i1 %tobool.not, label %cleanup.cont.critedge, label %if.then
16+
17+
if.then: ; preds = %entry
18+
; It's ok to modify this test in the future should be able to split critical
19+
; edges here, just noting that this is the critical edge that we care about.
20+
; CHECK: callbr void asm sideeffect "", "X"(i8* blockaddress(@b, %cleanup.cont.critedge))
21+
; CHECK-NEXT: to label %return [label %cleanup.cont.critedge]
22+
callbr void asm sideeffect "", "X"(i8* blockaddress(@b, %cleanup.cont.critedge))
23+
to label %return [label %cleanup.cont.critedge]
24+
25+
cleanup.cont.critedge: ; preds = %entry, %if.then
26+
br label %return
27+
28+
return: ; preds = %if.then, %cleanup.cont.critedge
29+
%retval.0 = phi i32 [ 4, %cleanup.cont.critedge ], [ 0, %if.then ]
30+
ret i32 %retval.0
31+
}
32+
33+
define dso_local i32 @do_pages_move_nr_pages() local_unnamed_addr {
34+
entry:
35+
br label %for.cond
36+
37+
for.cond: ; preds = %if.end3, %entry
38+
%g.0 = phi i32 [ undef, %entry ], [ %inc, %if.end3 ]
39+
%0 = load i32, i32* @f, align 4
40+
%tobool.not = icmp eq i32 %0, 0
41+
br i1 %tobool.not, label %if.end3, label %if.then
42+
43+
if.then: ; preds = %for.cond
44+
%call.i = tail call i32 @a()
45+
%tobool.not.i = icmp eq i32 %call.i, 0
46+
br i1 %tobool.not.i, label %if.then2, label %if.then.i
47+
48+
if.then.i: ; preds = %if.then
49+
callbr void asm sideeffect "", "X"(i8* blockaddress(@do_pages_move_nr_pages, %if.then2))
50+
to label %if.end3 [label %if.then2]
51+
52+
if.then2: ; preds = %if.then, %if.then.i
53+
%g.0.lcssa = phi i32 [ %g.0, %if.then ], [ %g.0, %if.then.i ]
54+
%call4 = tail call i32 @e(i32 %g.0.lcssa)
55+
ret i32 undef
56+
57+
if.end3: ; preds = %for.cond, %if.then.i
58+
%inc = add nsw i32 %g.0, 1
59+
br label %for.cond
60+
}
61+

0 commit comments

Comments
 (0)