@@ -18,7 +18,7 @@ define i32 @test0() {
18
18
; CHECK: direct2:
19
19
; CHECK-NEXT: ret i32 0
20
20
; CHECK: indirect:
21
- ; CHECK-NEXT: [[OUT3:%.*]] = phi i32 [ [[OUT ]], [[ENTRY_INDIRECT_CRIT_EDGE:%.*]] ], [ [[OUT2 ]], [[DIRECT_INDIRECT_CRIT_EDGE:%.*]] ]
21
+ ; CHECK-NEXT: [[OUT3:%.*]] = phi i32 [ [[TMP0 ]], [[ENTRY_INDIRECT_CRIT_EDGE:%.*]] ], [ [[TMP1 ]], [[DIRECT_INDIRECT_CRIT_EDGE:%.*]] ]
22
22
; CHECK-NEXT: ret i32 [[OUT3]]
23
23
;
24
24
entry:
61
61
; Don't split edges unless they are critical, and callbr produces output, and
62
62
; that output is used.
63
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.
64
66
define i32 @dont_split1 () {
65
67
; CHECK-LABEL: @dont_split1(
66
68
; CHECK-NEXT: entry:
@@ -70,7 +72,7 @@ define i32 @dont_split1() {
70
72
; CHECK-NEXT: ret i32 42
71
73
; CHECK: y:
72
74
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])
73
- ; CHECK-NEXT: ret i32 [[TMP0 ]]
75
+ ; CHECK-NEXT: ret i32 [[TMP1 ]]
74
76
;
75
77
entry:
76
78
%0 = callbr i32 asm "" , "=r,!i" ()
@@ -146,7 +148,7 @@ define i32 @split_me0() {
146
148
; CHECK: x:
147
149
; CHECK-NEXT: br label [[Y]]
148
150
; CHECK: y:
149
- ; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP0 ]], [[ENTRY_Y_CRIT_EDGE:%.*]] ], [ 42, [[X]] ]
151
+ ; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP1 ]], [[ENTRY_Y_CRIT_EDGE:%.*]] ], [ 42, [[X]] ]
150
152
; CHECK-NEXT: ret i32 [[TMP2]]
151
153
;
152
154
entry:
@@ -177,7 +179,7 @@ define i32 @split_me1(i1 %z) {
177
179
; CHECK: x:
178
180
; CHECK-NEXT: ret i32 42
179
181
; CHECK: v:
180
- ; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP0 ]], [[W_V_CRIT_EDGE]] ], [ undef, [[ENTRY:%.*]] ]
182
+ ; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP1 ]], [[W_V_CRIT_EDGE]] ], [ undef, [[ENTRY:%.*]] ]
181
183
; CHECK-NEXT: ret i32 [[TMP2]]
182
184
;
183
185
entry:
@@ -210,7 +212,7 @@ define i32 @split_me2(i1 %z) {
210
212
; CHECK: x:
211
213
; CHECK-NEXT: ret i32 42
212
214
; CHECK: v:
213
- ; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP0 ]], [[W_V_CRIT_EDGE]] ], [ 42, [[ENTRY:%.*]] ]
215
+ ; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP1 ]], [[W_V_CRIT_EDGE]] ], [ 42, [[ENTRY:%.*]] ]
214
216
; CHECK-NEXT: ret i32 [[TMP2]]
215
217
;
216
218
entry:
227
229
%1 = phi i32 [ %0 , %w ], [ 42 , %entry ], [ %0 , %w ]
228
230
ret i32 %1
229
231
}
232
+
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]]
247
+ ;
248
+ entry:
249
+ %0 = callbr i32 asm "" , "=r,!i" ()
250
+ to label %x [label %y ]
251
+
252
+ x:
253
+ br label %out
254
+
255
+ y:
256
+ br label %out
257
+
258
+ out:
259
+ ret i32 %0
260
+ }
261
+
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]]
274
+ ;
275
+ entry:
276
+ %0 = callbr i32 asm "" , "=r,!i" ()
277
+ to label %out [label %y ]
278
+
279
+ y:
280
+ br label %out
281
+
282
+ out:
283
+ ret i32 %0
284
+ }
285
+
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]]
300
+ ;
301
+ entry:
302
+ %0 = callbr i32 asm "" , "=r,!i" ()
303
+ to label %y [label %out ]
304
+
305
+ y:
306
+ br label %out
307
+
308
+ out:
309
+ ret i32 %0
310
+ }
311
+
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
326
+ ;
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
334
+ }
335
+
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]]
348
+ ;
349
+ entry:
350
+ %0 = callbr i32 asm "" , "=r,!i" () to label %same [label %same ]
351
+ same:
352
+ ret i32 %0
353
+ }
354
+
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]]
367
+ ;
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
373
+ }
374
+
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]]
394
+ ;
395
+ entry:
396
+ %0 = callbr i64 asm "# $0 $1" , "={dx},!i" ()
397
+ to label %asm.fallthrough [label %foo ]
398
+
399
+ asm .fallthrough:
400
+ %1 = callbr i64 asm "# $0 $1" , "={bx},!i" ()
401
+ to label %foo [label %foo ]
402
+
403
+ foo:
404
+ %x.0 = phi i64 [ %0 , %entry ], [ %1 , %asm.fallthrough ], [ %1 , %asm.fallthrough ]
405
+ ret i64 %x.0
406
+ }
407
+
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]]
421
+ ;
422
+ entry:
423
+ %0 = callbr i32 asm "" , "=r,!i" ()
424
+ to label %x [label %y ]
425
+
426
+ x:
427
+ ret i32 42
428
+
429
+ y:
430
+ %1 = add nsw i32 %0 , %0
431
+ ret i32 %1
432
+ }
0 commit comments