Skip to content

Commit 25c7029

Browse files
committed
clarify state of implementation
1 parent 1975e4b commit 25c7029

File tree

3 files changed

+198
-13
lines changed

3 files changed

+198
-13
lines changed

llvm/lib/Target/AMDGPU/AMDGPUUnifyDivergentExitNodes.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ bool AMDGPUUnifyDivergentExitNodesImpl::run(Function &F, DominatorTree *DT,
260260
if (HasDivergentExitBlock)
261261
UnreachableBlocks.push_back(BB);
262262
} else if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) {
263-
if (DummyReturnBB == nullptr)
263+
if (!DummyReturnBB)
264264
DummyReturnBB = createDummyReturnBlock(F, ReturningBlocks);
265265

266266
if (BI->isUnconditional()) {
@@ -275,7 +275,7 @@ bool AMDGPUUnifyDivergentExitNodesImpl::run(Function &F, DominatorTree *DT,
275275
}
276276
Changed = true;
277277
} else if (CallBrInst *CBI = dyn_cast<CallBrInst>(BB->getTerminator())) {
278-
if (DummyReturnBB == nullptr)
278+
if (!DummyReturnBB)
279279
DummyReturnBB = createDummyReturnBlock(F, ReturningBlocks);
280280

281281
handleNBranch(F, BB, CBI, DummyReturnBB, Updates);

llvm/lib/Transforms/Scalar/StructurizeCFG.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1396,7 +1396,12 @@ bool StructurizeCFG::makeUniformRegion(Region *R, UniformityInfo &UA) {
13961396
/// Run the transformation for each region found
13971397
bool StructurizeCFG::run(Region *R, DominatorTree *DT,
13981398
const TargetTransformInfo *TTI) {
1399-
// CallBr and its corresponding blocks must not be modified by this pass.
1399+
// CallBr and its corresponding direct target blocks are for now ignored by
1400+
// this pass. This is not a limitation for the currently intended uses cases
1401+
// of callbr in the AMDGPU backend (cf.
1402+
// https://discourse.llvm.org/t/rfc-add-callbr-intrinsic-support/86087).
1403+
// Parent and child regions are not affected by this (current) restriction.
1404+
// See `llvm/test/Transforms/StructurizeCFG/callbr.ll` for details.
14001405
if (R->isTopLevelRegion() || isa<CallBrInst>(R->getEntry()->getTerminator()))
14011406
return false;
14021407

llvm/test/Transforms/StructurizeCFG/callbr.ll

Lines changed: 190 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,208 @@
22
; RUN: opt -S -passes=structurizecfg %s -o - | FileCheck %s
33

44
; Structurize as usual, but don't tear callbr and its destination blocks apart.
5+
;
6+
; Note: currently, callbr blocks and their corresponding target blocks
7+
; themselves are not handled by the structurizer.* If the CFG turns out to be
8+
; unstructured at the end, the CFG lowering (si-annotate-control-flow) will
9+
; detect this. For the currently intended use cases of callbr in the context of
10+
; the AMDGPU backend, this is not a limitation (cf.
11+
; https://discourse.llvm.org/t/rfc-add-callbr-intrinsic-support/86087).
12+
;
13+
; Note 2: while callbr and its targets remain untouched, everything else is
14+
; handled as usual, even if it is nested in a callbr region.
15+
;
16+
; *FIXME: this will be fixed in the future. Callbr can be handled as follows:
17+
; Input IR:
18+
; ```
19+
; define void @foo_callbr() {
20+
; callbr void asm "", "!i"() to label %fallthrough [label %indirect, ...]
21+
; fallthrough:
22+
; br label %exit
23+
; indirect:
24+
; br label %exit
25+
; ...
26+
; exit:
27+
; ret void
28+
; }
29+
; ```
30+
;
31+
; Output IR:
32+
; ```
33+
; define void @foo_callbr() {
34+
; callbr void asm "", "!i"()
35+
; to label %fallthrough [label %fake.indirect, label %fake.indirect1, label %fake.indirect2, ...]
36+
; fake.indirect: ; preds = %0
37+
; br label %Flow
38+
; fake.indirect1: ; preds = %0
39+
; br label %Flow
40+
; fake.indirect2: ; preds = %0
41+
; br label %Flow
42+
; ...
43+
; Flow: ; preds = %fallthrough, %fake.indirect[0-N]
44+
; %1 = phi i1 [ false, %fallthrough ], [ true, %fake.indirect ], [ false, %fake.indirect[1-N] ]
45+
; br i1 %1, label %indirect, label %Flow1
46+
; Flow1: ; preds = %Flow, %indirect
47+
; %2 = phi i1 [ false, %Flow], [ true, %fake.indirect1 ], [ false, %indirect ]
48+
; br i1 %2, label %indirect1, label %Flow2
49+
; Flow2: ; preds = %Flow, %indirect1
50+
; %2 = phi i1 [ false, %Flow], [ true, %fake.indirect2 ], [ false, %indirect1 ]
51+
; br i1 %2, label %indirect2, label %Flow3
52+
; ...
53+
; fallthrough: ; preds = %0
54+
; br label %Flow
55+
; indirect: ; preds = %Flow
56+
; br label %Flow1
57+
; indirect1: ; preds = %Flow1
58+
; br label %Flow2
59+
; indirect2: : preds = %Flow2
60+
; br label %Flow3
61+
; ...
62+
; exit: ; preds = %indirectN, %FlowN
63+
; ret void
64+
; }
65+
; ```
66+
;
67+
; Output IR as ASCII-art:
68+
; %0
69+
; ---------------------
70+
; | | | |
71+
; v v v v
72+
; f f.i f.i1 f.i2
73+
; | | | |
74+
; v v v v
75+
; ---------------------
76+
; %Flow
77+
; | \
78+
; | %indirect
79+
; | /
80+
; %Flow1
81+
; | \
82+
; | %indirect1
83+
; | /
84+
; %Flow2
85+
; | \
86+
; | %indirect2
87+
; | /
88+
; %exit
89+
;
90+
91+
; Only callbr, nothing to do.
92+
define void @callbr_simple() {
93+
; CHECK-LABEL: define void @callbr_simple() {
94+
; CHECK-NEXT: [[CALLBR:.*:]]
95+
; CHECK-NEXT: callbr void asm "", "!i"()
96+
; CHECK-NEXT: to label %[[INDIRECT:.*]] [label %indirect]
97+
; CHECK: [[INDIRECT]]:
98+
; CHECK-NEXT: br label %[[EXIT:.*]]
99+
; CHECK: [[INDIRECT1:.*:]]
100+
; CHECK-NEXT: br label %[[EXIT]]
101+
; CHECK: [[EXIT]]:
102+
; CHECK-NEXT: ret void
103+
;
104+
callbr:
105+
callbr void asm "", "!i"() to label %fallthrough [label %indirect]
106+
fallthrough:
107+
br label %exit
108+
indirect:
109+
br label %exit
110+
exit:
111+
ret void
112+
}
113+
114+
; Callbr nested in non-callbr: non-callbr is transformed
115+
define void @callbr_in_non_callbr(i1 %c) {
116+
; CHECK-LABEL: define void @callbr_in_non_callbr(
117+
; CHECK-SAME: i1 [[C:%.*]]) {
118+
; CHECK-NEXT: [[C_INV:%.*]] = xor i1 [[C]], true
119+
; CHECK-NEXT: br i1 [[C_INV]], label %[[NOCALLBR:.*]], label %[[FLOW:.*]]
120+
; CHECK: [[FLOW]]:
121+
; CHECK-NEXT: [[TMP1:%.*]] = phi i1 [ false, %[[NOCALLBR]] ], [ true, [[TMP0:%.*]] ]
122+
; CHECK-NEXT: br i1 [[TMP1]], label %[[CALLBR:.*]], label %[[EXIT:.*]]
123+
; CHECK: [[CALLBR]]:
124+
; CHECK-NEXT: callbr void asm "", "!i"()
125+
; CHECK-NEXT: to label %[[INDIRECT:.*]] [label %indirect]
126+
; CHECK: [[INDIRECT]]:
127+
; CHECK-NEXT: br label %[[EXIT]]
128+
; CHECK: [[INDIRECT1:.*:]]
129+
; CHECK-NEXT: br label %[[EXIT]]
130+
; CHECK: [[NOCALLBR]]:
131+
; CHECK-NEXT: br label %[[FLOW]]
132+
; CHECK: [[EXIT]]:
133+
; CHECK-NEXT: ret void
134+
;
135+
br i1 %c, label %callbr, label %nocallbr
136+
callbr:
137+
callbr void asm "", "!i"() to label %fallthrough [label %indirect]
138+
fallthrough:
139+
br label %exit
140+
indirect:
141+
br label %exit
142+
nocallbr:
143+
br label %exit
144+
exit:
145+
ret void
146+
}
147+
148+
; Callbr parent of non-callbr: non-callbr is transformed
149+
define void @non_callbr_in_callbr(i1 %c) {
150+
; CHECK-LABEL: define void @non_callbr_in_callbr(
151+
; CHECK-SAME: i1 [[C:%.*]]) {
152+
; CHECK-NEXT: [[C_INV:%.*]] = xor i1 [[C]], true
153+
; CHECK-NEXT: callbr void asm "", "!i"()
154+
; CHECK-NEXT: to label %[[INDIRECT:.*]] [label %indirect]
155+
; CHECK: [[INDIRECT]]:
156+
; CHECK-NEXT: br i1 [[C_INV]], label %[[FALLTHROUGH2:.*]], label %[[FLOW:.*]]
157+
; CHECK: [[FLOW]]:
158+
; CHECK-NEXT: [[TMP1:%.*]] = phi i1 [ false, %[[FALLTHROUGH2]] ], [ true, %[[INDIRECT]] ]
159+
; CHECK-NEXT: br i1 [[TMP1]], label %[[FALLTHROUGH1:.*]], label %[[FLOW1:.*]]
160+
; CHECK: [[FALLTHROUGH1]]:
161+
; CHECK-NEXT: br label %[[FLOW1]]
162+
; CHECK: [[FALLTHROUGH2]]:
163+
; CHECK-NEXT: br label %[[FLOW]]
164+
; CHECK: [[INDIRECT1:.*:]]
165+
; CHECK-NEXT: br label %[[EXIT:.*]]
166+
; CHECK: [[FLOW1]]:
167+
; CHECK-NEXT: br label %[[EXIT]]
168+
; CHECK: [[EXIT]]:
169+
; CHECK-NEXT: ret void
170+
;
171+
callbr void asm "", "!i"() to label %fallthrough [label %indirect]
172+
fallthrough:
173+
br i1 %c, label %fallthrough1, label %fallthrough2
174+
fallthrough1:
175+
br label %exit
176+
fallthrough2:
177+
br label %exit
178+
indirect:
179+
br label %exit
180+
exit:
181+
ret void
182+
}
5183

6-
define void @callbr_inline_asm(i32 %c, i1 %d, i1 %e) {
7-
; CHECK-LABEL: define void @callbr_inline_asm(
8-
; CHECK-SAME: i32 [[C:%.*]], i1 [[D:%.*]], i1 [[E:%.*]]) {
9-
; CHECK-NEXT: [[D_INV:%.*]] = xor i1 [[D]], true
10-
; CHECK-NEXT: br i1 [[D_INV]], label %[[NOCALLBR:.*]], label %[[FLOW3:.*]]
184+
; Callbr surrounded by non-callbr: all three regular branches are handled
185+
; correctly
186+
define void @callbr_nested_in_non_callbr(i1 %c, i1 %d, i1 %e, i1 %f) {
187+
; CHECK-LABEL: define void @callbr_nested_in_non_callbr(
188+
; CHECK-SAME: i1 [[C:%.*]], i1 [[D:%.*]], i1 [[E:%.*]], i1 [[F:%.*]]) {
189+
; CHECK-NEXT: [[C_INV:%.*]] = xor i1 [[C]], true
190+
; CHECK-NEXT: br i1 [[C_INV]], label %[[NOCALLBR:.*]], label %[[FLOW3:.*]]
11191
; CHECK: [[FLOW3]]:
12192
; CHECK-NEXT: [[TMP1:%.*]] = phi i1 [ false, %[[FLOW:.*]] ], [ true, [[TMP0:%.*]] ]
13193
; CHECK-NEXT: br i1 [[TMP1]], label %[[CALLBR:.*]], label %[[RET:.*]]
14194
; CHECK: [[CALLBR]]:
15195
; CHECK-NEXT: callbr void asm "", "!i"()
16196
; CHECK-NEXT: to label %[[INDIRECT:.*]] [label %indirect]
17197
; CHECK: [[INDIRECT]]:
18-
; CHECK-NEXT: br i1 [[E]], label %[[FALLTHROUGH1:.*]], label %[[FLOW2:.*]]
198+
; CHECK-NEXT: br i1 [[D]], label %[[FALLTHROUGH1:.*]], label %[[FLOW2:.*]]
19199
; CHECK: [[FALLTHROUGH1]]:
20200
; CHECK-NEXT: br label %[[FLOW2]]
21201
; CHECK: [[INDIRECT2:.*:]]
22202
; CHECK-NEXT: br i1 [[E]], label %[[INDIRECT1:.*]], label %[[FLOW1:.*]]
23203
; CHECK: [[INDIRECT1]]:
24204
; CHECK-NEXT: br label %[[FLOW1]]
25205
; CHECK: [[NOCALLBR]]:
26-
; CHECK-NEXT: br i1 [[E]], label %[[NOCALLBR1:.*]], label %[[FLOW]]
206+
; CHECK-NEXT: br i1 [[F]], label %[[NOCALLBR1:.*]], label %[[FLOW]]
27207
; CHECK: [[NOCALLBR1]]:
28208
; CHECK-NEXT: br label %[[FLOW]]
29209
; CHECK: [[FLOW]]:
@@ -35,19 +215,19 @@ define void @callbr_inline_asm(i32 %c, i1 %d, i1 %e) {
35215
; CHECK: [[RET]]:
36216
; CHECK-NEXT: ret void
37217
;
38-
br i1 %d, label %callbr, label %nocallbr
218+
br i1 %c, label %callbr, label %nocallbr
39219
callbr:
40220
callbr void asm "", "!i"() to label %fallthrough [label %indirect]
41221
fallthrough:
42-
br i1 %e, label %fallthrough1, label %ret
222+
br i1 %d, label %fallthrough1, label %ret
43223
fallthrough1:
44224
br label %ret
45225
indirect:
46226
br i1 %e, label %indirect1, label %ret
47227
indirect1:
48228
br label %ret
49229
nocallbr:
50-
br i1 %e, label %nocallbr1, label %ret
230+
br i1 %f, label %nocallbr1, label %ret
51231
nocallbr1:
52232
br label %ret
53233
ret:

0 commit comments

Comments
 (0)