Revert " [LoongArch][ISel] Check the number of sign bits in `PatGprGpr_32` (#107432)"
[llvm-project.git] / llvm / test / CodeGen / AArch64 / callbr-prepare.ll
blobafe18ca8b7c50f9a666bce8d5f024c69439b384d
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt %s -callbrprepare -S -o - | FileCheck %s
3 ; RUN: opt %s -passes=callbr-prepare -S -o - | FileCheck %s
5 define i32 @test0() {
6 ; CHECK-LABEL: @test0(
7 ; CHECK-NEXT:  entry:
8 ; CHECK-NEXT:    [[OUT:%.*]] = callbr i32 asm "# $0", "=r,!i"()
9 ; CHECK-NEXT:    to label [[DIRECT:%.*]] [label %entry.indirect_crit_edge]
10 ; CHECK:       entry.indirect_crit_edge:
11 ; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[OUT]])
12 ; CHECK-NEXT:    br label [[INDIRECT:%.*]]
13 ; CHECK:       direct:
14 ; CHECK-NEXT:    [[OUT2:%.*]] = callbr i32 asm "# $0", "=r,!i"()
15 ; CHECK-NEXT:    to label [[DIRECT2:%.*]] [label %direct.indirect_crit_edge]
16 ; CHECK:       direct.indirect_crit_edge:
17 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[OUT2]])
18 ; CHECK-NEXT:    br label [[INDIRECT]]
19 ; CHECK:       direct2:
20 ; CHECK-NEXT:    ret i32 0
21 ; CHECK:       indirect:
22 ; CHECK-NEXT:    [[OUT3:%.*]] = phi i32 [ [[TMP0]], [[ENTRY_INDIRECT_CRIT_EDGE:%.*]] ], [ [[TMP1]], [[DIRECT_INDIRECT_CRIT_EDGE:%.*]] ]
23 ; CHECK-NEXT:    ret i32 [[OUT3]]
25 entry:
26   %out = callbr i32 asm "# $0", "=r,!i"()
27   to label %direct [label %indirect]
28 direct:
29   %out2 = callbr i32 asm "# $0", "=r,!i"()
30   to label %direct2 [label %indirect]
31 direct2:
32   ret i32 0
33 indirect:
34   %out3 = phi i32 [%out, %entry], [%out2, %direct]
35   ret i32 %out3
38 ; Don't split edges unless they are critical, and callbr produces output, and
39 ; that output is used.
40 ; Here we have none of the above.
41 define i32 @dont_split0() {
42 ; CHECK-LABEL: @dont_split0(
43 ; CHECK-NEXT:  entry:
44 ; CHECK-NEXT:    callbr void asm "", "!i"()
45 ; CHECK-NEXT:    to label [[X:%.*]] [label %y]
46 ; CHECK:       x:
47 ; CHECK-NEXT:    ret i32 42
48 ; CHECK:       y:
49 ; CHECK-NEXT:    ret i32 0
51 entry:
52   callbr void asm "", "!i"()
53   to label %x [label %y]
56   ret i32 42
59   ret i32 0
62 ; Don't split edges unless they are critical, and callbr produces output, and
63 ; that output is used.
64 ; Here we have output, but no critical edge.
65 ; That said, we ought to insert a callbr landing pad intrinsic call and update
66 ; to use the correct SSA value.
67 define i32 @dont_split1() {
68 ; CHECK-LABEL: @dont_split1(
69 ; CHECK-NEXT:  entry:
70 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
71 ; CHECK-NEXT:    to label [[X:%.*]] [label %y]
72 ; CHECK:       x:
73 ; CHECK-NEXT:    ret i32 42
74 ; CHECK:       y:
75 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
76 ; CHECK-NEXT:    ret i32 [[TMP1]]
78 entry:
79   %0 = callbr i32 asm "", "=r,!i"()
80   to label %x [label %y]
83   ret i32 42
86   ret i32 %0
89 ; Don't split edges unless they are critical, and callbr produces output, and
90 ; that output is used.
91 ; Here we have a critical edge along an indirect branch, but no output.
92 define i32 @dont_split2() {
93 ; CHECK-LABEL: @dont_split2(
94 ; CHECK-NEXT:  entry:
95 ; CHECK-NEXT:    callbr void asm "", "!i"()
96 ; CHECK-NEXT:    to label [[X:%.*]] [label %y]
97 ; CHECK:       x:
98 ; CHECK-NEXT:    br label [[Y:%.*]]
99 ; CHECK:       y:
100 ; CHECK-NEXT:    [[TMP0:%.*]] = phi i32 [ 0, [[X]] ], [ 42, [[ENTRY:%.*]] ]
101 ; CHECK-NEXT:    ret i32 [[TMP0]]
103 entry:
104   callbr void asm "", "!i"()
105   to label %x [label %y]
108   br label %y
111   %0 = phi i32 [ 0, %x ], [ 42, %entry ]
112   ret i32 %0
115 ; Don't split edges unless they are critical, and callbr produces output, and
116 ; that output is used.
117 ; Here we're missing a use.
118 define i32 @dont_split3() {
119 ; CHECK-LABEL: @dont_split3(
120 ; CHECK-NEXT:  entry:
121 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
122 ; CHECK-NEXT:    to label [[X:%.*]] [label %v]
123 ; CHECK:       x:
124 ; CHECK-NEXT:    br label [[V:%.*]]
125 ; CHECK:       v:
126 ; CHECK-NEXT:    ret i32 42
128 entry:
129   %0 = callbr i32 asm "", "=r,!i"() to label %x [label %v]
132   br label %v
135   ret i32 42
138 ; Don't split edges unless they are critical, and callbr produces output, and
139 ; that output is used.
140 ; Here we have output and a critical edge along an indirect branch.
141 define i32 @split_me0() {
142 ; CHECK-LABEL: @split_me0(
143 ; CHECK-NEXT:  entry:
144 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
145 ; CHECK-NEXT:    to label [[X:%.*]] [label %entry.y_crit_edge]
146 ; CHECK:       entry.y_crit_edge:
147 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
148 ; CHECK-NEXT:    br label [[Y:%.*]]
149 ; CHECK:       x:
150 ; CHECK-NEXT:    br label [[Y]]
151 ; CHECK:       y:
152 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[ENTRY_Y_CRIT_EDGE:%.*]] ], [ 42, [[X]] ]
153 ; CHECK-NEXT:    ret i32 [[TMP2]]
155 entry:
156   %0 = callbr i32 asm "", "=r,!i"()
157   to label %x [label %y]
160   br label %y
163   %1 = phi i32 [ %0, %entry ], [ 42, %x ]
164   ret i32 %1
167 ; Here we have output and a critical edge along an indirect branch.
168 ; Ensure that if we repeat the indirect destination, that we only split it
169 ; once.
170 define i32 @split_me1(i1 %z) {
171 ; CHECK-LABEL: @split_me1(
172 ; CHECK-NEXT:  entry:
173 ; CHECK-NEXT:    br i1 [[Z:%.*]], label [[W:%.*]], label [[V:%.*]]
174 ; CHECK:       w:
175 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i,!i"()
176 ; CHECK-NEXT:    to label [[X:%.*]] [label [[W_V_CRIT_EDGE:%.*]], label %w.v_crit_edge]
177 ; CHECK:       w.v_crit_edge:
178 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
179 ; CHECK-NEXT:    br label [[V]]
180 ; CHECK:       x:
181 ; CHECK-NEXT:    ret i32 42
182 ; CHECK:       v:
183 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[W_V_CRIT_EDGE]] ], [ undef, [[ENTRY:%.*]] ]
184 ; CHECK-NEXT:    ret i32 [[TMP2]]
186 entry:
187   br i1 %z, label %w, label %v
190   %0 = callbr i32 asm "", "=r,!i,!i"()
191   to label %x [label %v, label %v]
194   ret i32 42
197   %1 = phi i32 [%0, %w], [%0, %w], [undef, %entry]
198   ret i32 %1
201 ; A more interessting case of @split_me1. Check that we still only split the
202 ; critical edge from w to v once.
203 define i32 @split_me2(i1 %z) {
204 ; CHECK-LABEL: @split_me2(
205 ; CHECK-NEXT:  entry:
206 ; CHECK-NEXT:    br i1 [[Z:%.*]], label [[W:%.*]], label [[V:%.*]]
207 ; CHECK:       w:
208 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i,!i"()
209 ; CHECK-NEXT:    to label [[X:%.*]] [label [[W_V_CRIT_EDGE:%.*]], label %w.v_crit_edge]
210 ; CHECK:       w.v_crit_edge:
211 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
212 ; CHECK-NEXT:    br label [[V]]
213 ; CHECK:       x:
214 ; CHECK-NEXT:    ret i32 42
215 ; CHECK:       v:
216 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[W_V_CRIT_EDGE]] ], [ 42, [[ENTRY:%.*]] ]
217 ; CHECK-NEXT:    ret i32 [[TMP2]]
219 entry:
220   br i1 %z, label %w, label %v
223   %0 = callbr i32 asm "", "=r,!i,!i"()
224   to label %x [label %v, label %v]
227   ret i32 42
230   %1 = phi i32 [ %0, %w ], [ 42, %entry ], [ %0, %w ]
231   ret i32 %1
234 ; Here we have a diamond with no phi.
235 define i32 @dont_split4() {
236 ; CHECK-LABEL: @dont_split4(
237 ; CHECK-NEXT:  entry:
238 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
239 ; CHECK-NEXT:    to label [[X:%.*]] [label %y]
240 ; CHECK:       x:
241 ; CHECK-NEXT:    br label [[OUT:%.*]]
242 ; CHECK:       y:
243 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
244 ; CHECK-NEXT:    br label [[OUT]]
245 ; CHECK:       out:
246 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[Y:%.*]] ], [ [[TMP0]], [[X]] ]
247 ; CHECK-NEXT:    ret i32 [[TMP2]]
249 entry:
250   %0 = callbr i32 asm "", "=r,!i"()
251   to label %x [label %y]
254   br label %out
257   br label %out
259 out:
260   ret i32 %0
263 ; Triangle with no phi.
264 define i32 @dont_split5() {
265 ; CHECK-LABEL: @dont_split5(
266 ; CHECK-NEXT:  entry:
267 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
268 ; CHECK-NEXT:    to label [[OUT:%.*]] [label %y]
269 ; CHECK:       y:
270 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
271 ; CHECK-NEXT:    br label [[OUT]]
272 ; CHECK:       out:
273 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[Y:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
274 ; CHECK-NEXT:    ret i32 [[TMP2]]
276 entry:
277   %0 = callbr i32 asm "", "=r,!i"()
278   to label %out [label %y]
281   br label %out
283 out:
284   ret i32 %0
287 ; Triangle the other way with no phi.
288 define i32 @split_me3() {
289 ; CHECK-LABEL: @split_me3(
290 ; CHECK-NEXT:  entry:
291 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
292 ; CHECK-NEXT:    to label [[Y:%.*]] [label %entry.out_crit_edge]
293 ; CHECK:       entry.out_crit_edge:
294 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
295 ; CHECK-NEXT:    br label [[OUT:%.*]]
296 ; CHECK:       y:
297 ; CHECK-NEXT:    br label [[OUT]]
298 ; CHECK:       out:
299 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[ENTRY_OUT_CRIT_EDGE:%.*]] ], [ [[TMP0]], [[Y]] ]
300 ; CHECK-NEXT:    ret i32 [[TMP2]]
302 entry:
303   %0 = callbr i32 asm "", "=r,!i"()
304   to label %y [label %out]
307   br label %out
309 out:
310   ret i32 %0
313 ; Test callbr looping back on itself.
314 define i32 @dont_split6(i32 %0) {
315 ; CHECK-LABEL: @dont_split6(
316 ; CHECK-NEXT:  entry:
317 ; CHECK-NEXT:    br label [[LOOP:%.*]]
318 ; CHECK:       loop:
319 ; CHECK-NEXT:    [[TMP1:%.*]] = phi i32 [ [[TMP0:%.*]], [[ENTRY:%.*]] ], [ [[TMP3:%.*]], [[LOOP_LOOP_CRIT_EDGE:%.*]] ]
320 ; CHECK-NEXT:    [[TMP2:%.*]] = callbr i32 asm "", "=r,0,!i"(i32 [[TMP1]])
321 ; CHECK-NEXT:    to label [[EXIT:%.*]] [label %loop.loop_crit_edge]
322 ; CHECK:       loop.loop_crit_edge:
323 ; CHECK-NEXT:    [[TMP3]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP2]])
324 ; CHECK-NEXT:    br label [[LOOP]]
325 ; CHECK:       exit:
326 ; CHECK-NEXT:    ret i32 0
328 entry:
329   br label %loop
330 loop:
331   %1 = phi i32 [%0, %entry], [%2, %loop]
332   %2 = callbr i32 asm "", "=r,0,!i"(i32 %1) to label %exit [label %loop]
333 exit:
334   ret i32 0
337 ; Test same direct+indirect dest no phi.
338 define i32 @split_me4() {
339 ; CHECK-LABEL: @split_me4(
340 ; CHECK-NEXT:  entry:
341 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
342 ; CHECK-NEXT:    to label [[SAME:%.*]] [label %entry.same_crit_edge]
343 ; CHECK:       entry.same_crit_edge:
344 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
345 ; CHECK-NEXT:    br label [[SAME]]
346 ; CHECK:       same:
347 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[ENTRY_SAME_CRIT_EDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
348 ; CHECK-NEXT:    ret i32 [[TMP2]]
350 entry:
351   %0 = callbr i32 asm "", "=r,!i"() to label %same [label %same]
352 same:
353   ret i32 %0
356 ; Test same direct+indirect dest w/ phi.
357 define i32 @split_me5() {
358 ; CHECK-LABEL: @split_me5(
359 ; CHECK-NEXT:  entry:
360 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
361 ; CHECK-NEXT:    to label [[SAME:%.*]] [label %entry.same_crit_edge]
362 ; CHECK:       entry.same_crit_edge:
363 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
364 ; CHECK-NEXT:    br label [[SAME]]
365 ; CHECK:       same:
366 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[ENTRY_SAME_CRIT_EDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
367 ; CHECK-NEXT:    ret i32 [[TMP2]]
369 entry:
370   %0 = callbr i32 asm "", "=r,!i"() to label %same [label %same]
371 same:
372   %1 = phi i32 [%0, %entry], [%0, %entry]
373   ret i32 %1
376 ; "The Devil's cross" (i.e. two asm goto with conflicting physreg constraints
377 ; going to the same destination).
378 define i64 @split_me6() {
379 ; CHECK-LABEL: @split_me6(
380 ; CHECK-NEXT:  entry:
381 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i64 asm "# $0 $1", "={dx},!i"()
382 ; CHECK-NEXT:    to label [[ASM_FALLTHROUGH:%.*]] [label %entry.foo_crit_edge]
383 ; CHECK:       entry.foo_crit_edge:
384 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.callbr.landingpad.i64(i64 [[TMP0]])
385 ; CHECK-NEXT:    br label [[FOO:%.*]]
386 ; CHECK:       asm.fallthrough:
387 ; CHECK-NEXT:    [[TMP2:%.*]] = callbr i64 asm "# $0 $1", "={bx},!i"()
388 ; CHECK-NEXT:    to label [[FOO]] [label %asm.fallthrough.foo_crit_edge]
389 ; CHECK:       asm.fallthrough.foo_crit_edge:
390 ; CHECK-NEXT:    [[TMP3:%.*]] = call i64 @llvm.callbr.landingpad.i64(i64 [[TMP2]])
391 ; CHECK-NEXT:    br label [[FOO]]
392 ; CHECK:       foo:
393 ; CHECK-NEXT:    [[X_0:%.*]] = phi i64 [ [[TMP1]], [[ENTRY_FOO_CRIT_EDGE:%.*]] ], [ [[TMP3]], [[ASM_FALLTHROUGH_FOO_CRIT_EDGE:%.*]] ], [ [[TMP2]], [[ASM_FALLTHROUGH]] ]
394 ; CHECK-NEXT:    ret i64 [[X_0]]
396 entry:
397   %0 = callbr i64 asm "# $0 $1", "={dx},!i"()
398   to label %asm.fallthrough [label %foo]
400 asm.fallthrough:
401   %1 = callbr i64 asm "# $0 $1", "={bx},!i"()
402   to label %foo [label %foo]
404 foo:
405   %x.0 = phi i64 [ %0, %entry ], [ %1, %asm.fallthrough ], [ %1, %asm.fallthrough ]
406   ret i64 %x.0
409 ; Test the result of the callbr having multiple uses to avoid iterator
410 ; invalidation bugs in CallBrPrepare::UpdateSSA.
411 define i32 @multiple_split() {
412 ; CHECK-LABEL: @multiple_split(
413 ; CHECK-NEXT:  entry:
414 ; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()
415 ; CHECK-NEXT:    to label [[X:%.*]] [label %y]
416 ; CHECK:       x:
417 ; CHECK-NEXT:    ret i32 42
418 ; CHECK:       y:
419 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
420 ; CHECK-NEXT:    [[TMP2:%.*]] = add nsw i32 [[TMP1]], [[TMP1]]
421 ; CHECK-NEXT:    ret i32 [[TMP2]]
423 entry:
424   %0 = callbr i32 asm "", "=r,!i"()
425   to label %x [label %y]
428   ret i32 42
431   %1 = add nsw i32 %0, %0
432   ret i32 %1