Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / SimplifyCFG / indirectbr.ll
blob87d8b399494ce2514c870e43d1b2b03b321aa101
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
4 ; SimplifyCFG should eliminate redundant indirectbr edges.
6 declare void @foo()
7 declare void @A()
8 declare void @B(i32)
9 declare void @C()
11 define void @indbrtest0(ptr %P, ptr %Q) {
12 ; CHECK-LABEL: @indbrtest0(
13 ; CHECK-NEXT:  entry:
14 ; CHECK-NEXT:    store ptr blockaddress(@indbrtest0, [[BB0:%.*]]), ptr [[P:%.*]], align 8
15 ; CHECK-NEXT:    store ptr blockaddress(@indbrtest0, [[BB1:%.*]]), ptr [[P]], align 8
16 ; CHECK-NEXT:    store ptr blockaddress(@indbrtest0, [[BB2:%.*]]), ptr [[P]], align 8
17 ; CHECK-NEXT:    call void @foo()
18 ; CHECK-NEXT:    [[T:%.*]] = load ptr, ptr [[Q:%.*]], align 8
19 ; CHECK-NEXT:    indirectbr ptr [[T]], [label [[BB0]], label [[BB1]], label %BB2]
20 ; CHECK:       BB0:
21 ; CHECK-NEXT:    call void @A()
22 ; CHECK-NEXT:    br label [[BB1]]
23 ; CHECK:       common.ret:
24 ; CHECK-NEXT:    ret void
25 ; CHECK:       BB1:
26 ; CHECK-NEXT:    [[X:%.*]] = phi i32 [ 0, [[BB0]] ], [ 1, [[ENTRY:%.*]] ]
27 ; CHECK-NEXT:    call void @B(i32 [[X]])
28 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
29 ; CHECK:       BB2:
30 ; CHECK-NEXT:    call void @C()
31 ; CHECK-NEXT:    br label [[COMMON_RET]]
33 entry:
34   store ptr blockaddress(@indbrtest0, %BB0), ptr %P
35   store ptr blockaddress(@indbrtest0, %BB1), ptr %P
36   store ptr blockaddress(@indbrtest0, %BB2), ptr %P
37   call void @foo()
38   %t = load ptr, ptr %Q
39   indirectbr ptr %t, [label %BB0, label %BB1, label %BB2, label %BB0, label %BB1, label %BB2]
40 BB0:
41   call void @A()
42   br label %BB1
43 BB1:
44   %x = phi i32 [ 0, %BB0 ], [ 1, %entry ], [ 1, %entry ]
45   call void @B(i32 %x)
46   ret void
47 BB2:
48   call void @C()
49   ret void
52 ; SimplifyCFG should convert the indirectbr into a directbr. It would be even
53 ; better if it removed the branch altogether, but simplifycfdg currently misses
54 ; that because the predecessor is the entry block.
57 define void @indbrtest1(ptr %P, ptr %Q) {
58 ; CHECK-LABEL: @indbrtest1(
59 ; CHECK-NEXT:  entry:
60 ; CHECK-NEXT:    store ptr blockaddress(@indbrtest1, [[BB0:%.*]]), ptr [[P:%.*]], align 8
61 ; CHECK-NEXT:    call void @foo()
62 ; CHECK-NEXT:    br label [[BB0]]
63 ; CHECK:       BB0:
64 ; CHECK-NEXT:    call void @A()
65 ; CHECK-NEXT:    ret void
67 entry:
68   store ptr blockaddress(@indbrtest1, %BB0), ptr %P
69   call void @foo()
70   %t = load ptr, ptr %Q
71   indirectbr ptr %t, [label %BB0, label %BB0]
72 BB0:
73   call void @A()
74   ret void
77 ; SimplifyCFG should notice that BB0 does not have its address taken and
78 ; remove it from entry's successor list.
81 define void @indbrtest2(ptr %t) {
82 ; CHECK-LABEL: @indbrtest2(
83 ; CHECK-NEXT:  entry:
84 ; CHECK-NEXT:    unreachable
86 entry:
87   indirectbr ptr %t, [label %BB0, label %BB0]
88 BB0:
89   ret void
93 ; Make sure the blocks in the next few tests aren't trivially removable as
94 ; successors by taking their addresses.
96 @anchor = constant [13 x ptr] [
97   ptr blockaddress(@indbrtest3, %L1), ptr blockaddress(@indbrtest3, %L2), ptr blockaddress(@indbrtest3, %L3),
98   ptr blockaddress(@indbrtest4, %L1), ptr blockaddress(@indbrtest4, %L2), ptr blockaddress(@indbrtest4, %L3),
99   ptr blockaddress(@indbrtest5, %L1), ptr blockaddress(@indbrtest5, %L2), ptr blockaddress(@indbrtest5, %L3), ptr blockaddress(@indbrtest5, %L4),
100   ptr blockaddress(@indbrtest6, %L1), ptr blockaddress(@indbrtest6, %L2), ptr blockaddress(@indbrtest6, %L3)
103 ; SimplifyCFG should turn the indirectbr into a conditional branch on the
104 ; condition of the select.
106 define void @indbrtest3(i1 %cond, ptr %address) nounwind {
107 ; CHECK-LABEL: @indbrtest3(
108 ; CHECK-NEXT:  entry:
109 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[L1:%.*]], label [[L2:%.*]]
110 ; CHECK:       common.ret:
111 ; CHECK-NEXT:    ret void
112 ; CHECK:       L1:
113 ; CHECK-NEXT:    call void @A()
114 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
115 ; CHECK:       L2:
116 ; CHECK-NEXT:    call void @C()
117 ; CHECK-NEXT:    br label [[COMMON_RET]]
119 entry:
120   %indirect.goto.dest = select i1 %cond, ptr blockaddress(@indbrtest3, %L1), ptr blockaddress(@indbrtest3, %L2)
121   indirectbr ptr %indirect.goto.dest, [label %L1, label %L2, label %L3]
124   call void @A()
125   ret void
127   call void @C()
128   ret void
130   call void @foo()
131   ret void
134 ; SimplifyCFG should turn the indirectbr into an unconditional branch to the
135 ; only possible destination.
136 ; As in @indbrtest1, it should really remove the branch entirely, but it doesn't
137 ; because it's in the entry block.
139 define void @indbrtest4(i1 %cond) nounwind {
140 ; CHECK-LABEL: @indbrtest4(
141 ; CHECK-NEXT:  entry:
142 ; CHECK-NEXT:    br label [[L1:%.*]]
143 ; CHECK:       L1:
144 ; CHECK-NEXT:    call void @A()
145 ; CHECK-NEXT:    ret void
147 entry:
148   %indirect.goto.dest = select i1 %cond, ptr blockaddress(@indbrtest4, %L1), ptr blockaddress(@indbrtest4, %L1)
149   indirectbr ptr %indirect.goto.dest, [label %L1, label %L2, label %L3]
152   call void @A()
153   ret void
155   call void @C()
156   ret void
158   call void @foo()
159   ret void
162 ; SimplifyCFG should turn the indirectbr into an unreachable because neither
163 ; destination is listed as a successor.
165 define void @indbrtest5(i1 %cond, ptr %anchor) nounwind {
166 ; CHECK-LABEL: @indbrtest5(
167 ; CHECK-NEXT:  entry:
168 ; CHECK-NEXT:    unreachable
170 entry:
171   %indirect.goto.dest = select i1 %cond, ptr blockaddress(@indbrtest5, %L1), ptr blockaddress(@indbrtest5, %L2)
172 ; This needs to have more than one successor for this test, otherwise it gets
173 ; replaced with an unconditional branch to the single successor.
174   indirectbr ptr %indirect.goto.dest, [label %L3, label %L4]
177   call void @A()
178   ret void
180   call void @C()
181   ret void
183   call void @foo()
184   ret void
186   call void @foo()
188 ; This keeps blockaddresses not otherwise listed as successors from being zapped
189 ; before SimplifyCFG even looks at the indirectbr.
190   indirectbr ptr %anchor, [label %L1, label %L2]
193 ; The same as above, except the selected addresses are equal.
195 define void @indbrtest6(i1 %cond, ptr %anchor) nounwind {
196 ; CHECK-LABEL: @indbrtest6(
197 ; CHECK-NEXT:  entry:
198 ; CHECK-NEXT:    unreachable
200 entry:
201   %indirect.goto.dest = select i1 %cond, ptr blockaddress(@indbrtest6, %L1), ptr blockaddress(@indbrtest6, %L1)
202 ; This needs to have more than one successor for this test, otherwise it gets
203 ; replaced with an unconditional branch to the single successor.
204   indirectbr ptr %indirect.goto.dest, [label %L2, label %L3]
207   call void @A()
208   ret void
210   call void @C()
211   ret void
213   call void @foo()
215 ; This keeps blockaddresses not otherwise listed as successors from being zapped
216 ; before SimplifyCFG even looks at the indirectbr.
217   indirectbr ptr %anchor, [label %L1, label %L2]
220 ; PR10072
222 @xblkx.bbs = internal unnamed_addr constant [9 x ptr] [ptr blockaddress(@indbrtest7, %xblkx.begin), ptr blockaddress(@indbrtest7, %xblkx.begin3), ptr blockaddress(@indbrtest7, %xblkx.begin4), ptr blockaddress(@indbrtest7, %xblkx.begin5), ptr blockaddress(@indbrtest7, %xblkx.begin6), ptr blockaddress(@indbrtest7, %xblkx.begin7), ptr blockaddress(@indbrtest7, %xblkx.begin8), ptr blockaddress(@indbrtest7, %xblkx.begin9), ptr blockaddress(@indbrtest7, %xblkx.end)]
224 define void @indbrtest7() {
225 ; CHECK-LABEL: @indbrtest7(
226 ; CHECK-NEXT:  escape-string.top:
227 ; CHECK-NEXT:    [[XVAL202X:%.*]] = call i32 @xfunc5x()
228 ; CHECK-NEXT:    br label [[XLAB5X:%.*]]
229 ; CHECK:       xlab8x:
230 ; CHECK-NEXT:    [[XVALUEX:%.*]] = call i32 @xselectorx()
231 ; CHECK-NEXT:    [[XBLKX_X:%.*]] = getelementptr [9 x ptr], ptr @xblkx.bbs, i32 0, i32 [[XVALUEX]]
232 ; CHECK-NEXT:    [[XBLKX_LOAD:%.*]] = load ptr, ptr [[XBLKX_X]], align 8
233 ; CHECK-NEXT:    indirectbr ptr [[XBLKX_LOAD]], [label [[XLAB4X:%.*]], label %v2j]
234 ; CHECK:       v2j:
235 ; CHECK-NEXT:    [[XUNUSEDX:%.*]] = call i32 @xactionx()
236 ; CHECK-NEXT:    br label [[XLAB4X]]
237 ; CHECK:       xlab4x:
238 ; CHECK-NEXT:    [[INCR19:%.*]] = add i32 [[XVAL704X_0:%.*]], 1
239 ; CHECK-NEXT:    br label [[XLAB5X]]
240 ; CHECK:       xlab5x:
241 ; CHECK-NEXT:    [[XVAL704X_0]] = phi i32 [ 0, [[ESCAPE_STRING_TOP:%.*]] ], [ [[INCR19]], [[XLAB4X]] ]
242 ; CHECK-NEXT:    [[XVAL10X:%.*]] = icmp ult i32 [[XVAL704X_0]], [[XVAL202X]]
243 ; CHECK-NEXT:    br i1 [[XVAL10X]], label [[XLAB8X:%.*]], label [[XLAB9X:%.*]]
244 ; CHECK:       xlab9x:
245 ; CHECK-NEXT:    ret void
247 escape-string.top:
248   %xval202x = call i32 @xfunc5x()
249   br label %xlab5x
251 xlab8x:                                           ; preds = %xlab5x
252   %xvaluex = call i32 @xselectorx()
253   %xblkx.x = getelementptr [9 x ptr], ptr @xblkx.bbs, i32 0, i32 %xvaluex
254   %xblkx.load = load ptr, ptr %xblkx.x
255   indirectbr ptr %xblkx.load, [label %xblkx.begin, label %xblkx.begin3, label %xblkx.begin4, label %xblkx.begin5, label %xblkx.begin6, label %xblkx.begin7, label %xblkx.begin8, label %xblkx.begin9, label %xblkx.end]
257 xblkx.begin:
258   br label %xblkx.end
260 xblkx.begin3:
261   br label %xblkx.end
263 xblkx.begin4:
264   br label %xblkx.end
266 xblkx.begin5:
267   br label %xblkx.end
269 xblkx.begin6:
270   br label %xblkx.end
272 xblkx.begin7:
273   br label %xblkx.end
275 xblkx.begin8:
276   br label %xblkx.end
278 xblkx.begin9:
279   br label %xblkx.end
281 xblkx.end:
282   %yes.0 = phi i1 [ false, %xblkx.begin ], [ true, %xlab8x ], [ false, %xblkx.begin9 ], [ false, %xblkx.begin8 ], [ false, %xblkx.begin7 ], [ false, %xblkx.begin6 ], [ false, %xblkx.begin5 ], [ true, %xblkx.begin4 ], [ false, %xblkx.begin3 ]
283   br i1 %yes.0, label %v2j, label %xlab17x
285 v2j:
286   %xunusedx = call i32 @xactionx()
287   br label %xlab4x
289 xlab17x:
290   br label %xlab4x
292 xlab4x:
293   %incr19 = add i32 %xval704x.0, 1
294   br label %xlab5x
296 xlab5x:
297   %xval704x.0 = phi i32 [ 0, %escape-string.top ], [ %incr19, %xlab4x ]
298   %xval10x = icmp ult i32 %xval704x.0, %xval202x
299   br i1 %xval10x, label %xlab8x, label %xlab9x
301 xlab9x:
302   ret void
305 define void @indbrtest8() {
306 ; CHECK-LABEL: @indbrtest8(
307 ; CHECK-NEXT:  entry:
308 ; CHECK-NEXT:    call void @B(i32 undef)
309 ; CHECK-NEXT:    ret void
311 entry:
312   indirectbr ptr blockaddress(@indbrtest8, %BB1), [label %BB0, label %BB1]
313 BB0:
314   call void @A()
315   ret void
316 BB1:
317   call void @B(i32 undef)
318   ret void
321 define void @indbrtest9() {
322 ; CHECK-LABEL: @indbrtest9(
323 ; CHECK-NEXT:  entry:
324 ; CHECK-NEXT:    unreachable
326 entry:
327   indirectbr ptr blockaddress(@indbrtest9, %BB1), [label %BB0]
328 BB0:
329   call void @A()
330   ret void
331 BB1:
332   call void @B(i32 undef)
333   ret void
336 define void @indbrtest10() {
337 ; CHECK-LABEL: @indbrtest10(
338 ; CHECK-NEXT:  entry:
339 ; CHECK-NEXT:    call void @B(i32 undef)
340 ; CHECK-NEXT:    ret void
342 entry:
343   indirectbr ptr blockaddress(@indbrtest10, %BB1), [label %BB1]
344 BB0:
345   call void @A()
346   ret void
347 BB1:
348   call void @B(i32 undef)
349   ret void
352 define void @indbrtest11() {
353 ; CHECK-LABEL: @indbrtest11(
354 ; CHECK-NEXT:  entry:
355 ; CHECK-NEXT:    call void @A()
356 ; CHECK-NEXT:    ret void
358 entry:
359   indirectbr ptr blockaddress(@indbrtest11, %BB0), [label %BB0, label %BB1, label %BB1]
360 BB0:
361   call void @A()
362   ret void
363 BB1:
364   call void @B(i32 undef)
365   ret void
368 define void @indbrtest12() {
369 ; CHECK-LABEL: @indbrtest12(
370 ; CHECK-NEXT:  entry:
371 ; CHECK-NEXT:    call void @B(i32 undef)
372 ; CHECK-NEXT:    ret void
374 entry:
375   indirectbr ptr blockaddress(@indbrtest12, %BB1), [label %BB0, label %BB1, label %BB1]
376 BB0:
377   call void @A()
378   ret void
379 BB1:
380   call void @B(i32 undef)
381   ret void
384 declare i32 @xfunc5x()
385 declare i8 @xfunc7x()
386 declare i32 @xselectorx()
387 declare i32 @xactionx()