xref: /llvm-project/llvm/test/Transforms/InstCombine/unreachable-code.ll (revision 6cdf596c52f028ea7d150e0696f967fbff443ccf)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt -S -passes=instcombine < %s | FileCheck %s --check-prefixes=CHECK,DEFAULT_ITER
3; RUN: opt -S -passes='instcombine<max-iterations=1>' < %s | FileCheck %s --check-prefixes=CHECK,MAX1
4
5declare void @dummy()
6declare void @llvm.assume(i1)
7
8define i32 @br_true(i1 %x) {
9; CHECK-LABEL: define i32 @br_true
10; CHECK-SAME: (i1 [[X:%.*]]) {
11; CHECK-NEXT:    br i1 true, label [[IF:%.*]], label [[ELSE:%.*]]
12; CHECK:       if:
13; CHECK-NEXT:    call void @dummy()
14; CHECK-NEXT:    br label [[JOIN:%.*]]
15; CHECK:       else:
16; CHECK-NEXT:    br label [[JOIN]]
17; CHECK:       join:
18; CHECK-NEXT:    ret i32 1
19;
20  %c = or i1 %x, true
21  br i1 %c, label %if, label %else
22
23if:
24  call void @dummy()
25  br label %join
26
27else:
28  call void @dummy()
29  br label %join
30
31join:
32  %phi = phi i32 [ 1, %if ], [ 2, %else ]
33  ret i32 %phi
34}
35
36define i32 @br_false(i1 %x) {
37; CHECK-LABEL: define i32 @br_false
38; CHECK-SAME: (i1 [[X:%.*]]) {
39; CHECK-NEXT:    br i1 false, label [[IF:%.*]], label [[ELSE:%.*]]
40; CHECK:       if:
41; CHECK-NEXT:    br label [[JOIN:%.*]]
42; CHECK:       else:
43; CHECK-NEXT:    call void @dummy()
44; CHECK-NEXT:    br label [[JOIN]]
45; CHECK:       join:
46; CHECK-NEXT:    ret i32 2
47;
48  %c = and i1 %x, false
49  br i1 %c, label %if, label %else
50
51if:
52  call void @dummy()
53  br label %join
54
55else:
56  call void @dummy()
57  br label %join
58
59join:
60  %phi = phi i32 [ 1, %if ], [ 2, %else ]
61  ret i32 %phi
62}
63
64define i32 @br_undef(i1 %x) {
65; CHECK-LABEL: define i32 @br_undef
66; CHECK-SAME: (i1 [[X:%.*]]) {
67; CHECK-NEXT:    br i1 undef, label [[IF:%.*]], label [[ELSE:%.*]]
68; CHECK:       if:
69; CHECK-NEXT:    br label [[JOIN:%.*]]
70; CHECK:       else:
71; CHECK-NEXT:    br label [[JOIN]]
72; CHECK:       join:
73; CHECK-NEXT:    ret i32 poison
74;
75  %c = xor i1 %x, undef
76  br i1 %c, label %if, label %else
77
78if:
79  call void @dummy()
80  br label %join
81
82else:
83  call void @dummy()
84  br label %join
85
86join:
87  %phi = phi i32 [ 1, %if ], [ 2, %else ]
88  ret i32 %phi
89}
90
91define i32 @br_true_phi_with_repeated_preds(i1 %x) {
92; CHECK-LABEL: define i32 @br_true_phi_with_repeated_preds
93; CHECK-SAME: (i1 [[X:%.*]]) {
94; CHECK-NEXT:    br i1 true, label [[IF:%.*]], label [[ELSE:%.*]]
95; CHECK:       if:
96; CHECK-NEXT:    call void @dummy()
97; CHECK-NEXT:    br label [[JOIN:%.*]]
98; CHECK:       else:
99; CHECK-NEXT:    br i1 false, label [[JOIN]], label [[JOIN]]
100; CHECK:       join:
101; CHECK-NEXT:    ret i32 1
102;
103  %c = or i1 %x, true
104  br i1 %c, label %if, label %else
105
106if:
107  call void @dummy()
108  br label %join
109
110else:
111  br i1 false, label %join, label %join
112
113join:
114  %phi = phi i32 [ 1, %if ], [ 2, %else ], [ 2, %else ]
115  ret i32 %phi
116}
117
118define i32 @br_true_const_phi_direct_edge(i1 %x) {
119; CHECK-LABEL: define i32 @br_true_const_phi_direct_edge
120; CHECK-SAME: (i1 [[X:%.*]]) {
121; CHECK-NEXT:  entry:
122; CHECK-NEXT:    br i1 true, label [[IF:%.*]], label [[JOIN:%.*]]
123; CHECK:       if:
124; CHECK-NEXT:    call void @dummy()
125; CHECK-NEXT:    br label [[JOIN]]
126; CHECK:       join:
127; CHECK-NEXT:    ret i32 2
128;
129entry:
130  br i1 true, label %if, label %join
131
132if:
133  call void @dummy()
134  br label %join
135
136join:
137  %phi = phi i32 [ 1, %entry ], [ 2, %if ]
138  ret i32 %phi
139}
140
141define i32 @br_true_var_phi_direct_edge(i1 %x) {
142; CHECK-LABEL: define i32 @br_true_var_phi_direct_edge
143; CHECK-SAME: (i1 [[X:%.*]]) {
144; CHECK-NEXT:  entry:
145; CHECK-NEXT:    br i1 true, label [[IF:%.*]], label [[JOIN:%.*]]
146; CHECK:       if:
147; CHECK-NEXT:    call void @dummy()
148; CHECK-NEXT:    br label [[JOIN]]
149; CHECK:       join:
150; CHECK-NEXT:    ret i32 2
151;
152entry:
153  %c = or i1 %x, true
154  br i1 %c, label %if, label %join
155
156if:
157  call void @dummy()
158  br label %join
159
160join:
161  %phi = phi i32 [ 1, %entry ], [ 2, %if ]
162  ret i32 %phi
163}
164
165define void @switch_case(i32 %x) {
166; CHECK-LABEL: define void @switch_case
167; CHECK-SAME: (i32 [[X:%.*]]) {
168; CHECK-NEXT:    switch i32 0, label [[DEFAULT:%.*]] [
169; CHECK-NEXT:    i32 0, label [[CASE0:%.*]]
170; CHECK-NEXT:    ]
171; CHECK:       case0:
172; CHECK-NEXT:    call void @dummy()
173; CHECK-NEXT:    ret void
174; CHECK:       default:
175; CHECK-NEXT:    ret void
176;
177  %v = and i32 %x, 0
178  switch i32 %v, label %default [
179  i32 0, label %case0
180  ]
181
182case0:
183  call void @dummy()
184  ret void
185
186default:
187  call void @dummy()
188  ret void
189}
190
191define void @switch_default(i32 %x) {
192; CHECK-LABEL: define void @switch_default
193; CHECK-SAME: (i32 [[X:%.*]]) {
194; CHECK-NEXT:    switch i32 -1, label [[DEFAULT:%.*]] [
195; CHECK-NEXT:    i32 0, label [[CASE0:%.*]]
196; CHECK-NEXT:    ]
197; CHECK:       case0:
198; CHECK-NEXT:    ret void
199; CHECK:       default:
200; CHECK-NEXT:    call void @dummy()
201; CHECK-NEXT:    ret void
202;
203  %v = or i32 %x, -1
204  switch i32 %v, label %default [
205  i32 0, label %case0
206  ]
207
208case0:
209  call void @dummy()
210  ret void
211
212default:
213  call void @dummy()
214  ret void
215}
216
217define void @switch_undef(i32 %x) {
218; CHECK-LABEL: define void @switch_undef
219; CHECK-SAME: (i32 [[X:%.*]]) {
220; CHECK-NEXT:    switch i32 undef, label [[DEFAULT:%.*]] [
221; CHECK-NEXT:    i32 0, label [[CASE0:%.*]]
222; CHECK-NEXT:    ]
223; CHECK:       case0:
224; CHECK-NEXT:    ret void
225; CHECK:       default:
226; CHECK-NEXT:    ret void
227;
228  %v = xor i32 %x, undef
229  switch i32 %v, label %default [
230  i32 0, label %case0
231  ]
232
233case0:
234  call void @dummy()
235  ret void
236
237default:
238  call void @dummy()
239  ret void
240}
241
242define void @non_term_unreachable() {
243; CHECK-LABEL: define void @non_term_unreachable() {
244; CHECK-NEXT:    call void @dummy()
245; CHECK-NEXT:    store i1 true, ptr poison, align 1
246; CHECK-NEXT:    ret void
247;
248  call void @dummy()
249  call void @dummy() nounwind willreturn
250  store i1 true, ptr poison
251  call void @dummy()
252  ret void
253}
254
255define i32 @non_term_unreachable_phi(i1 %c) {
256; CHECK-LABEL: define i32 @non_term_unreachable_phi
257; CHECK-SAME: (i1 [[C:%.*]]) {
258; CHECK-NEXT:  entry:
259; CHECK-NEXT:    br i1 [[C]], label [[IF:%.*]], label [[JOIN:%.*]]
260; CHECK:       if:
261; CHECK-NEXT:    store i1 true, ptr poison, align 1
262; CHECK-NEXT:    br label [[JOIN]]
263; CHECK:       join:
264; CHECK-NEXT:    ret i32 2
265;
266entry:
267  br i1 %c, label %if, label %join
268
269if:
270  store i1 true, ptr poison
271  call void @dummy()
272  br label %join
273
274join:
275  %phi = phi i32 [ 1, %if], [ 2, %entry ]
276  ret i32 %phi
277}
278
279define void @non_term_unreachable_following_blocks() {
280; CHECK-LABEL: define void @non_term_unreachable_following_blocks() {
281; CHECK-NEXT:    call void @dummy()
282; CHECK-NEXT:    store i1 true, ptr poison, align 1
283; CHECK-NEXT:    br label [[SPLIT:%.*]]
284; CHECK:       split:
285; CHECK-NEXT:    br label [[LOOP:%.*]]
286; CHECK:       loop:
287; CHECK-NEXT:    br label [[LOOP]]
288;
289  call void @dummy()
290  store i1 true, ptr poison
291  call void @dummy()
292  br label %split
293
294split:
295  call void @dummy()
296  br label %loop
297
298loop:
299  call void @dummy()
300  br label %loop
301}
302
303define void @br_not_into_loop(i1 %x) {
304; CHECK-LABEL: define void @br_not_into_loop
305; CHECK-SAME: (i1 [[X:%.*]]) {
306; CHECK-NEXT:    br i1 true, label [[EXIT:%.*]], label [[LOOP:%.*]]
307; CHECK:       loop:
308; CHECK-NEXT:    br label [[LOOP]]
309; CHECK:       exit:
310; CHECK-NEXT:    call void @dummy()
311; CHECK-NEXT:    ret void
312;
313  %c = or i1 %x, true
314  br i1 %c, label %exit, label %loop
315
316loop:
317  call void @dummy()
318  br label %loop
319
320exit:
321  call void @dummy()
322  ret void
323}
324
325define void @br_into_loop(i1 %x) {
326; CHECK-LABEL: define void @br_into_loop
327; CHECK-SAME: (i1 [[X:%.*]]) {
328; CHECK-NEXT:    br i1 true, label [[LOOP:%.*]], label [[EXIT:%.*]]
329; CHECK:       loop:
330; CHECK-NEXT:    call void @dummy()
331; CHECK-NEXT:    br label [[LOOP]]
332; CHECK:       exit:
333; CHECK-NEXT:    ret void
334;
335  %c = or i1 %x, true
336  br i1 %c, label %loop, label %exit
337
338loop:
339  call void @dummy()
340  br label %loop
341
342exit:
343  call void @dummy()
344  ret void
345}
346
347define void @two_br_not_into_loop(i1 %x) {
348; CHECK-LABEL: define void @two_br_not_into_loop
349; CHECK-SAME: (i1 [[X:%.*]]) {
350; CHECK-NEXT:    br i1 true, label [[BB2:%.*]], label [[LOOP:%.*]]
351; CHECK:       bb2:
352; CHECK-NEXT:    br i1 true, label [[EXIT:%.*]], label [[LOOP]]
353; CHECK:       loop:
354; CHECK-NEXT:    br label [[LOOP]]
355; CHECK:       exit:
356; CHECK-NEXT:    call void @dummy()
357; CHECK-NEXT:    ret void
358;
359  %c = or i1 %x, true
360  br i1 %c, label %bb2, label %loop
361
362bb2:
363  %c2 = or i1 %x, true
364  br i1 %c2, label %exit, label %loop
365
366loop:
367  call void @dummy()
368  br label %loop
369
370exit:
371  call void @dummy()
372  ret void
373}
374
375define void @one_br_into_loop_one_not(i1 %x, i1 %c2) {
376; CHECK-LABEL: define void @one_br_into_loop_one_not
377; CHECK-SAME: (i1 [[X:%.*]], i1 [[C2:%.*]]) {
378; CHECK-NEXT:    br i1 true, label [[BB2:%.*]], label [[LOOP:%.*]]
379; CHECK:       bb2:
380; CHECK-NEXT:    br i1 [[C2]], label [[EXIT:%.*]], label [[LOOP]]
381; CHECK:       loop:
382; CHECK-NEXT:    call void @dummy()
383; CHECK-NEXT:    br label [[LOOP]]
384; CHECK:       exit:
385; CHECK-NEXT:    call void @dummy()
386; CHECK-NEXT:    ret void
387;
388  %c = or i1 %x, true
389  br i1 %c, label %bb2, label %loop
390
391bb2:
392  br i1 %c2, label %exit, label %loop
393
394loop:
395  call void @dummy()
396  br label %loop
397
398exit:
399  call void @dummy()
400  ret void
401}
402
403define void @two_br_not_into_loop_with_split(i1 %x) {
404; CHECK-LABEL: define void @two_br_not_into_loop_with_split
405; CHECK-SAME: (i1 [[X:%.*]]) {
406; CHECK-NEXT:    br i1 true, label [[BB2:%.*]], label [[SPLIT1:%.*]]
407; CHECK:       bb2:
408; CHECK-NEXT:    br i1 true, label [[EXIT:%.*]], label [[SPLIT2:%.*]]
409; CHECK:       split1:
410; CHECK-NEXT:    br label [[LOOP:%.*]]
411; CHECK:       split2:
412; CHECK-NEXT:    br label [[LOOP]]
413; CHECK:       loop:
414; CHECK-NEXT:    br label [[LOOP]]
415; CHECK:       exit:
416; CHECK-NEXT:    call void @dummy()
417; CHECK-NEXT:    ret void
418;
419  %c = or i1 %x, true
420  br i1 %c, label %bb2, label %split1
421
422bb2:
423  %c2 = or i1 %x, true
424  br i1 %c2, label %exit, label %split2
425
426split1:
427  call void @dummy()
428  br label %loop
429
430split2:
431  call void @dummy()
432  br label %loop
433
434loop:
435  call void @dummy()
436  br label %loop
437
438exit:
439  call void @dummy()
440  ret void
441}
442
443define void @irreducible() {
444; CHECK-LABEL: define void @irreducible() {
445; CHECK-NEXT:  entry:
446; CHECK-NEXT:    br i1 false, label [[LOOP2:%.*]], label [[LOOP1:%.*]]
447; CHECK:       loop1:
448; CHECK-NEXT:    call void @dummy()
449; CHECK-NEXT:    br label [[LOOP2]]
450; CHECK:       loop2:
451; CHECK-NEXT:    call void @dummy()
452; CHECK-NEXT:    br i1 true, label [[EXIT:%.*]], label [[LOOP1]]
453; CHECK:       exit:
454; CHECK-NEXT:    call void @dummy()
455; CHECK-NEXT:    ret void
456;
457entry:
458  br i1 false, label %loop2, label %loop1
459
460loop1:
461  call void @dummy()
462  br label %loop2
463
464loop2:
465  call void @dummy()
466  br i1 true, label %exit, label %loop1
467
468exit:
469  call void @dummy()
470  ret void
471}
472
473define void @really_unreachable() {
474; CHECK-LABEL: define void @really_unreachable() {
475; CHECK-NEXT:  entry:
476; CHECK-NEXT:    ret void
477; CHECK:       unreachable:
478; CHECK-NEXT:    ret void
479;
480entry:
481  ret void
482
483unreachable:
484  call void @dummy()
485  ret void
486}
487
488define void @really_unreachable_predecessor() {
489; CHECK-LABEL: define void @really_unreachable_predecessor() {
490; CHECK-NEXT:  entry:
491; CHECK-NEXT:    br i1 false, label [[BB:%.*]], label [[EXIT:%.*]]
492; CHECK:       unreachable:
493; CHECK-NEXT:    br label [[BB]]
494; CHECK:       bb:
495; CHECK-NEXT:    ret void
496; CHECK:       exit:
497; CHECK-NEXT:    call void @dummy()
498; CHECK-NEXT:    ret void
499;
500entry:
501  br i1 false, label %bb, label %exit
502
503unreachable:
504  call void @dummy()
505  br label %bb
506
507bb:
508  call void @dummy()
509  ret void
510
511exit:
512  call void @dummy()
513  ret void
514}
515
516define i32 @pr64235() {
517; CHECK-LABEL: define i32 @pr64235() {
518; CHECK-NEXT:  entry:
519; CHECK-NEXT:    br i1 false, label [[BB:%.*]], label [[BB3:%.*]]
520; CHECK:       bb3:
521; CHECK-NEXT:    store i1 true, ptr poison, align 1
522; CHECK-NEXT:    br label [[BB2:%.*]]
523; CHECK:       bb:
524; CHECK-NEXT:    br label [[BB2]]
525; CHECK:       bb2:
526; CHECK-NEXT:    br label [[BB]]
527;
528entry:
529  br i1 false, label %bb, label %bb3
530
531bb3:
532  call void @llvm.assume(i1 false)
533  br label %bb2
534
535bb:
536  br label %bb2
537
538bb2:
539  call void @llvm.assume(i1 false)
540  br label %bb
541}
542
543declare void @invoke(ptr)
544declare i32 @__gxx_personality_v0(...)
545define void @test(i1 %x) personality ptr @__gxx_personality_v0  {
546; CHECK-LABEL: define void @test
547; CHECK-SAME: (i1 [[X:%.*]]) personality ptr @__gxx_personality_v0 {
548; CHECK-NEXT:  entry:
549; CHECK-NEXT:    br i1 [[X]], label [[IF_ELSE:%.*]], label [[CLEAN1:%.*]]
550; CHECK:       if.else:
551; CHECK-NEXT:    store i32 1, ptr undef, align 4
552; CHECK-NEXT:    invoke void @invoke(ptr poison)
553; CHECK-NEXT:            to label [[CONT:%.*]] unwind label [[LPAD5:%.*]]
554; CHECK:       cont:
555; CHECK-NEXT:    invoke void @invoke(ptr poison)
556; CHECK-NEXT:            to label [[CLEAN1]] unwind label [[LPAD6:%.*]]
557; CHECK:       lpad5:
558; CHECK-NEXT:    [[TMP0:%.*]] = landingpad { ptr, i32 }
559; CHECK-NEXT:            cleanup
560; CHECK-NEXT:    br label [[CLEAN1]]
561; CHECK:       lpad6:
562; CHECK-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
563; CHECK-NEXT:            cleanup
564; CHECK-NEXT:    br label [[CLEAN2:%.*]]
565; CHECK:       clean1:
566; CHECK-NEXT:    ret void
567; CHECK:       clean2:
568; CHECK-NEXT:    ret void
569;
570entry:
571  %ref = alloca ptr
572  br i1 %x, label %if.else, label %clean1
573
574if.else:
575  store i32 1, ptr undef
576  invoke void @invoke(ptr %ref)
577  to label %cont unwind label %lpad5
578
579cont:
580  invoke void @invoke(ptr %ref)
581  to label %clean1 unwind label %lpad6
582
583lpad5:
584  %13 = landingpad { ptr, i32 }
585  cleanup
586  br label %clean1
587
588lpad6:
589  %14 = landingpad { ptr, i32 }
590  cleanup
591  br label %clean2
592
593clean1:
594  ret void
595
596clean2:
597  ret void
598}
599
600;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
601; DEFAULT_ITER: {{.*}}
602; MAX1: {{.*}}
603