[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / test / CodeGen / AArch64 / callbr-prepare.ll
blob08b48d65c89a0cf9557e7becd3302304c524d778
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt %s -callbrprepare -S -o - | FileCheck %s
4 define i32 @test0() {
5 ; CHECK-LABEL: @test0(
6 ; CHECK-NEXT:  entry:
7 ; CHECK-NEXT:    [[OUT:%.*]] = callbr i32 asm "# $0", "=r,!i"()
8 ; CHECK-NEXT:    to label [[DIRECT:%.*]] [label %entry.indirect_crit_edge]
9 ; CHECK:       entry.indirect_crit_edge:
10 ; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[OUT]])
11 ; CHECK-NEXT:    br label [[INDIRECT:%.*]]
12 ; CHECK:       direct:
13 ; CHECK-NEXT:    [[OUT2:%.*]] = callbr i32 asm "# $0", "=r,!i"()
14 ; CHECK-NEXT:    to label [[DIRECT2:%.*]] [label %direct.indirect_crit_edge]
15 ; CHECK:       direct.indirect_crit_edge:
16 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[OUT2]])
17 ; CHECK-NEXT:    br label [[INDIRECT]]
18 ; CHECK:       direct2:
19 ; CHECK-NEXT:    ret i32 0
20 ; CHECK:       indirect:
21 ; CHECK-NEXT:    [[OUT3:%.*]] = phi i32 [ [[TMP0]], [[ENTRY_INDIRECT_CRIT_EDGE:%.*]] ], [ [[TMP1]], [[DIRECT_INDIRECT_CRIT_EDGE:%.*]] ]
22 ; CHECK-NEXT:    ret i32 [[OUT3]]
24 entry:
25   %out = callbr i32 asm "# $0", "=r,!i"()
26   to label %direct [label %indirect]
27 direct:
28   %out2 = callbr i32 asm "# $0", "=r,!i"()
29   to label %direct2 [label %indirect]
30 direct2:
31   ret i32 0
32 indirect:
33   %out3 = phi i32 [%out, %entry], [%out2, %direct]
34   ret i32 %out3
37 ; Don't split edges unless they are critical, and callbr produces output, and
38 ; that output is used.
39 ; Here we have none of the above.
40 define i32 @dont_split0() {
41 ; CHECK-LABEL: @dont_split0(
42 ; CHECK-NEXT:  entry:
43 ; CHECK-NEXT:    callbr void asm "", "!i"()
44 ; CHECK-NEXT:    to label [[X:%.*]] [label %y]
45 ; CHECK:       x:
46 ; CHECK-NEXT:    ret i32 42
47 ; CHECK:       y:
48 ; CHECK-NEXT:    ret i32 0
50 entry:
51   callbr void asm "", "!i"()
52   to label %x [label %y]
55   ret i32 42
58   ret i32 0
61 ; Don't split edges unless they are critical, and callbr produces output, and
62 ; that output is used.
63 ; Here we have output, but no critical edge.
64 ; That said, we ought to insert a callbr landing pad intrinsic call and update
65 ; to use the correct SSA value.
66 define i32 @dont_split1() {
67 ; CHECK-LABEL: @dont_split1(
68 ; CHECK-NEXT:  entry:
69 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
70 ; CHECK-NEXT:    to label [[X:%.*]] [label %y]
71 ; CHECK:       x:
72 ; CHECK-NEXT:    ret i32 42
73 ; CHECK:       y:
74 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
75 ; CHECK-NEXT:    ret i32 [[TMP1]]
77 entry:
78   %0 = callbr i32 asm "", "=r,!i"()
79   to label %x [label %y]
82   ret i32 42
85   ret i32 %0
88 ; Don't split edges unless they are critical, and callbr produces output, and
89 ; that output is used.
90 ; Here we have a critical edge along an indirect branch, but no output.
91 define i32 @dont_split2() {
92 ; CHECK-LABEL: @dont_split2(
93 ; CHECK-NEXT:  entry:
94 ; CHECK-NEXT:    callbr void asm "", "!i"()
95 ; CHECK-NEXT:    to label [[X:%.*]] [label %y]
96 ; CHECK:       x:
97 ; CHECK-NEXT:    br label [[Y:%.*]]
98 ; CHECK:       y:
99 ; CHECK-NEXT:    [[TMP0:%.*]] = phi i32 [ 0, [[X]] ], [ 42, [[ENTRY:%.*]] ]
100 ; CHECK-NEXT:    ret i32 [[TMP0]]
102 entry:
103   callbr void asm "", "!i"()
104   to label %x [label %y]
107   br label %y
110   %0 = phi i32 [ 0, %x ], [ 42, %entry ]
111   ret i32 %0
114 ; Don't split edges unless they are critical, and callbr produces output, and
115 ; that output is used.
116 ; Here we're missing a use.
117 define i32 @dont_split3() {
118 ; CHECK-LABEL: @dont_split3(
119 ; CHECK-NEXT:  entry:
120 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
121 ; CHECK-NEXT:    to label [[X:%.*]] [label %v]
122 ; CHECK:       x:
123 ; CHECK-NEXT:    br label [[V:%.*]]
124 ; CHECK:       v:
125 ; CHECK-NEXT:    ret i32 42
127 entry:
128   %0 = callbr i32 asm "", "=r,!i"() to label %x [label %v]
131   br label %v
134   ret i32 42
137 ; Don't split edges unless they are critical, and callbr produces output, and
138 ; that output is used.
139 ; Here we have output and a critical edge along an indirect branch.
140 define i32 @split_me0() {
141 ; CHECK-LABEL: @split_me0(
142 ; CHECK-NEXT:  entry:
143 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
144 ; CHECK-NEXT:    to label [[X:%.*]] [label %entry.y_crit_edge]
145 ; CHECK:       entry.y_crit_edge:
146 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
147 ; CHECK-NEXT:    br label [[Y:%.*]]
148 ; CHECK:       x:
149 ; CHECK-NEXT:    br label [[Y]]
150 ; CHECK:       y:
151 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[ENTRY_Y_CRIT_EDGE:%.*]] ], [ 42, [[X]] ]
152 ; CHECK-NEXT:    ret i32 [[TMP2]]
154 entry:
155   %0 = callbr i32 asm "", "=r,!i"()
156   to label %x [label %y]
159   br label %y
162   %1 = phi i32 [ %0, %entry ], [ 42, %x ]
163   ret i32 %1
166 ; Here we have output and a critical edge along an indirect branch.
167 ; Ensure that if we repeat the indirect destination, that we only split it
168 ; once.
169 define i32 @split_me1(i1 %z) {
170 ; CHECK-LABEL: @split_me1(
171 ; CHECK-NEXT:  entry:
172 ; CHECK-NEXT:    br i1 [[Z:%.*]], label [[W:%.*]], label [[V:%.*]]
173 ; CHECK:       w:
174 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i,!i"()
175 ; CHECK-NEXT:    to label [[X:%.*]] [label [[W_V_CRIT_EDGE:%.*]], label %w.v_crit_edge]
176 ; CHECK:       w.v_crit_edge:
177 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
178 ; CHECK-NEXT:    br label [[V]]
179 ; CHECK:       x:
180 ; CHECK-NEXT:    ret i32 42
181 ; CHECK:       v:
182 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[W_V_CRIT_EDGE]] ], [ undef, [[ENTRY:%.*]] ]
183 ; CHECK-NEXT:    ret i32 [[TMP2]]
185 entry:
186   br i1 %z, label %w, label %v
189   %0 = callbr i32 asm "", "=r,!i,!i"()
190   to label %x [label %v, label %v]
193   ret i32 42
196   %1 = phi i32 [%0, %w], [%0, %w], [undef, %entry]
197   ret i32 %1
200 ; A more interessting case of @split_me1. Check that we still only split the
201 ; critical edge from w to v once.
202 define i32 @split_me2(i1 %z) {
203 ; CHECK-LABEL: @split_me2(
204 ; CHECK-NEXT:  entry:
205 ; CHECK-NEXT:    br i1 [[Z:%.*]], label [[W:%.*]], label [[V:%.*]]
206 ; CHECK:       w:
207 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i,!i"()
208 ; CHECK-NEXT:    to label [[X:%.*]] [label [[W_V_CRIT_EDGE:%.*]], label %w.v_crit_edge]
209 ; CHECK:       w.v_crit_edge:
210 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
211 ; CHECK-NEXT:    br label [[V]]
212 ; CHECK:       x:
213 ; CHECK-NEXT:    ret i32 42
214 ; CHECK:       v:
215 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[W_V_CRIT_EDGE]] ], [ 42, [[ENTRY:%.*]] ]
216 ; CHECK-NEXT:    ret i32 [[TMP2]]
218 entry:
219   br i1 %z, label %w, label %v
222   %0 = callbr i32 asm "", "=r,!i,!i"()
223   to label %x [label %v, label %v]
226   ret i32 42
229   %1 = phi i32 [ %0, %w ], [ 42, %entry ], [ %0, %w ]
230   ret i32 %1
233 ; Here we have a diamond with no phi.
234 define i32 @dont_split4() {
235 ; CHECK-LABEL: @dont_split4(
236 ; CHECK-NEXT:  entry:
237 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
238 ; CHECK-NEXT:    to label [[X:%.*]] [label %y]
239 ; CHECK:       x:
240 ; CHECK-NEXT:    br label [[OUT:%.*]]
241 ; CHECK:       y:
242 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
243 ; CHECK-NEXT:    br label [[OUT]]
244 ; CHECK:       out:
245 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[Y:%.*]] ], [ [[TMP0]], [[X]] ]
246 ; CHECK-NEXT:    ret i32 [[TMP2]]
248 entry:
249   %0 = callbr i32 asm "", "=r,!i"()
250   to label %x [label %y]
253   br label %out
256   br label %out
258 out:
259   ret i32 %0
262 ; Triangle with no phi.
263 define i32 @dont_split5() {
264 ; CHECK-LABEL: @dont_split5(
265 ; CHECK-NEXT:  entry:
266 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
267 ; CHECK-NEXT:    to label [[OUT:%.*]] [label %y]
268 ; CHECK:       y:
269 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
270 ; CHECK-NEXT:    br label [[OUT]]
271 ; CHECK:       out:
272 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[Y:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
273 ; CHECK-NEXT:    ret i32 [[TMP2]]
275 entry:
276   %0 = callbr i32 asm "", "=r,!i"()
277   to label %out [label %y]
280   br label %out
282 out:
283   ret i32 %0
286 ; Triangle the other way with no phi.
287 define i32 @split_me3() {
288 ; CHECK-LABEL: @split_me3(
289 ; CHECK-NEXT:  entry:
290 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
291 ; CHECK-NEXT:    to label [[Y:%.*]] [label %entry.out_crit_edge]
292 ; CHECK:       entry.out_crit_edge:
293 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
294 ; CHECK-NEXT:    br label [[OUT:%.*]]
295 ; CHECK:       y:
296 ; CHECK-NEXT:    br label [[OUT]]
297 ; CHECK:       out:
298 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[ENTRY_OUT_CRIT_EDGE:%.*]] ], [ [[TMP0]], [[Y]] ]
299 ; CHECK-NEXT:    ret i32 [[TMP2]]
301 entry:
302   %0 = callbr i32 asm "", "=r,!i"()
303   to label %y [label %out]
306   br label %out
308 out:
309   ret i32 %0
312 ; Test callbr looping back on itself.
313 define i32 @dont_split6(i32 %0) {
314 ; CHECK-LABEL: @dont_split6(
315 ; CHECK-NEXT:  entry:
316 ; CHECK-NEXT:    br label [[LOOP:%.*]]
317 ; CHECK:       loop:
318 ; CHECK-NEXT:    [[TMP1:%.*]] = phi i32 [ [[TMP0:%.*]], [[ENTRY:%.*]] ], [ [[TMP3:%.*]], [[LOOP_LOOP_CRIT_EDGE:%.*]] ]
319 ; CHECK-NEXT:    [[TMP2:%.*]] = callbr i32 asm "", "=r,0,!i"(i32 [[TMP1]])
320 ; CHECK-NEXT:    to label [[EXIT:%.*]] [label %loop.loop_crit_edge]
321 ; CHECK:       loop.loop_crit_edge:
322 ; CHECK-NEXT:    [[TMP3]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP2]])
323 ; CHECK-NEXT:    br label [[LOOP]]
324 ; CHECK:       exit:
325 ; CHECK-NEXT:    ret i32 0
327 entry:
328   br label %loop
329 loop:
330   %1 = phi i32 [%0, %entry], [%2, %loop]
331   %2 = callbr i32 asm "", "=r,0,!i"(i32 %1) to label %exit [label %loop]
332 exit:
333   ret i32 0
336 ; Test same direct+indirect dest no phi.
337 define i32 @split_me4() {
338 ; CHECK-LABEL: @split_me4(
339 ; CHECK-NEXT:  entry:
340 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
341 ; CHECK-NEXT:    to label [[SAME:%.*]] [label %entry.same_crit_edge]
342 ; CHECK:       entry.same_crit_edge:
343 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
344 ; CHECK-NEXT:    br label [[SAME]]
345 ; CHECK:       same:
346 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[ENTRY_SAME_CRIT_EDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
347 ; CHECK-NEXT:    ret i32 [[TMP2]]
349 entry:
350   %0 = callbr i32 asm "", "=r,!i"() to label %same [label %same]
351 same:
352   ret i32 %0
355 ; Test same direct+indirect dest w/ phi.
356 define i32 @split_me5() {
357 ; CHECK-LABEL: @split_me5(
358 ; CHECK-NEXT:  entry:
359 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
360 ; CHECK-NEXT:    to label [[SAME:%.*]] [label %entry.same_crit_edge]
361 ; CHECK:       entry.same_crit_edge:
362 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
363 ; CHECK-NEXT:    br label [[SAME]]
364 ; CHECK:       same:
365 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[ENTRY_SAME_CRIT_EDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
366 ; CHECK-NEXT:    ret i32 [[TMP2]]
368 entry:
369   %0 = callbr i32 asm "", "=r,!i"() to label %same [label %same]
370 same:
371   %1 = phi i32 [%0, %entry], [%0, %entry]
372   ret i32 %1
375 ; "The Devil's cross" (i.e. two asm goto with conflicting physreg constraints
376 ; going to the same destination).
377 define i64 @split_me6() {
378 ; CHECK-LABEL: @split_me6(
379 ; CHECK-NEXT:  entry:
380 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i64 asm "# $0 $1", "={dx},!i"()
381 ; CHECK-NEXT:    to label [[ASM_FALLTHROUGH:%.*]] [label %entry.foo_crit_edge]
382 ; CHECK:       entry.foo_crit_edge:
383 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.callbr.landingpad.i64(i64 [[TMP0]])
384 ; CHECK-NEXT:    br label [[FOO:%.*]]
385 ; CHECK:       asm.fallthrough:
386 ; CHECK-NEXT:    [[TMP2:%.*]] = callbr i64 asm "# $0 $1", "={bx},!i"()
387 ; CHECK-NEXT:    to label [[FOO]] [label %asm.fallthrough.foo_crit_edge]
388 ; CHECK:       asm.fallthrough.foo_crit_edge:
389 ; CHECK-NEXT:    [[TMP3:%.*]] = call i64 @llvm.callbr.landingpad.i64(i64 [[TMP2]])
390 ; CHECK-NEXT:    br label [[FOO]]
391 ; CHECK:       foo:
392 ; CHECK-NEXT:    [[X_0:%.*]] = phi i64 [ [[TMP1]], [[ENTRY_FOO_CRIT_EDGE:%.*]] ], [ [[TMP3]], [[ASM_FALLTHROUGH_FOO_CRIT_EDGE:%.*]] ], [ [[TMP2]], [[ASM_FALLTHROUGH]] ]
393 ; CHECK-NEXT:    ret i64 [[X_0]]
395 entry:
396   %0 = callbr i64 asm "# $0 $1", "={dx},!i"()
397   to label %asm.fallthrough [label %foo]
399 asm.fallthrough:
400   %1 = callbr i64 asm "# $0 $1", "={bx},!i"()
401   to label %foo [label %foo]
403 foo:
404   %x.0 = phi i64 [ %0, %entry ], [ %1, %asm.fallthrough ], [ %1, %asm.fallthrough ]
405   ret i64 %x.0
408 ; Test the result of the callbr having multiple uses to avoid iterator
409 ; invalidation bugs in CallBrPrepare::UpdateSSA.
410 define i32 @multiple_split() {
411 ; CHECK-LABEL: @multiple_split(
412 ; CHECK-NEXT:  entry:
413 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
414 ; CHECK-NEXT:    to label [[X:%.*]] [label %y]
415 ; CHECK:       x:
416 ; CHECK-NEXT:    ret i32 42
417 ; CHECK:       y:
418 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
419 ; CHECK-NEXT:    [[TMP2:%.*]] = add nsw i32 [[TMP1]], [[TMP1]]
420 ; CHECK-NEXT:    ret i32 [[TMP2]]
422 entry:
423   %0 = callbr i32 asm "", "=r,!i"()
424   to label %x [label %y]
427   ret i32 42
430   %1 = add nsw i32 %0, %0
431   ret i32 %1