1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S < %s -passes=instcombine | FileCheck %s
4 define i1 @test_direct_implication(i1 %cond) {
5 ; CHECK-LABEL: @test_direct_implication(
7 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
9 ; CHECK-NEXT: br label [[MERGE:%.*]]
11 ; CHECK-NEXT: br label [[MERGE]]
13 ; CHECK-NEXT: ret i1 [[COND]]
16 br i1 %cond, label %if.true, label %if.false
25 %ret = phi i1 [true, %if.true], [false, %if.false]
29 define i1 @test_inverted_implication(i1 %cond) {
30 ; CHECK-LABEL: @test_inverted_implication(
32 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
34 ; CHECK-NEXT: br label [[MERGE:%.*]]
36 ; CHECK-NEXT: br label [[MERGE]]
38 ; CHECK-NEXT: [[RET:%.*]] = xor i1 [[COND]], true
39 ; CHECK-NEXT: ret i1 [[RET]]
42 br i1 %cond, label %if.true, label %if.false
51 %ret = phi i1 [false, %if.true], [true, %if.false]
55 define i1 @test_edge_dominance(i1 %cmp) {
56 ; CHECK-LABEL: @test_edge_dominance(
58 ; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
60 ; CHECK-NEXT: br label [[IF_END]]
62 ; CHECK-NEXT: ret i1 [[CMP]]
65 br i1 %cmp, label %if.end, label %if.then
71 %phi = phi i1 [ true, %entry ], [ false, %if.then ]
75 define i1 @test_direct_implication_complex_cfg(i1 %cond, i32 %cnt1) {
76 ; CHECK-LABEL: @test_direct_implication_complex_cfg(
78 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
80 ; CHECK-NEXT: br label [[LOOP1:%.*]]
82 ; CHECK-NEXT: [[IV1:%.*]] = phi i32 [ 0, [[IF_TRUE]] ], [ [[IV1_NEXT:%.*]], [[LOOP1]] ]
83 ; CHECK-NEXT: [[IV1_NEXT]] = add i32 [[IV1]], 1
84 ; CHECK-NEXT: [[LOOP_COND_1:%.*]] = icmp slt i32 [[IV1_NEXT]], [[CNT1:%.*]]
85 ; CHECK-NEXT: br i1 [[LOOP_COND_1]], label [[LOOP1]], label [[IF_TRUE_END:%.*]]
87 ; CHECK-NEXT: br label [[MERGE:%.*]]
89 ; CHECK-NEXT: br label [[MERGE]]
91 ; CHECK-NEXT: ret i1 [[COND]]
94 br i1 %cond, label %if.true, label %if.false
100 %iv1 = phi i32 [0, %if.true], [%iv1.next, %loop1]
101 %iv1.next = add i32 %iv1, 1
102 %loop.cond.1 = icmp slt i32 %iv1.next, %cnt1
103 br i1 %loop.cond.1, label %loop1, label %if.true.end
112 %ret = phi i1 [true, %if.true.end], [false, %if.false]
116 define i1 @test_inverted_implication_complex_cfg(i1 %cond, i32 %cnt1) {
117 ; CHECK-LABEL: @test_inverted_implication_complex_cfg(
119 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
121 ; CHECK-NEXT: br label [[LOOP1:%.*]]
123 ; CHECK-NEXT: [[IV1:%.*]] = phi i32 [ 0, [[IF_TRUE]] ], [ [[IV1_NEXT:%.*]], [[LOOP1]] ]
124 ; CHECK-NEXT: [[IV1_NEXT]] = add i32 [[IV1]], 1
125 ; CHECK-NEXT: [[LOOP_COND_1:%.*]] = icmp slt i32 [[IV1_NEXT]], [[CNT1:%.*]]
126 ; CHECK-NEXT: br i1 [[LOOP_COND_1]], label [[LOOP1]], label [[IF_TRUE_END:%.*]]
127 ; CHECK: if.true.end:
128 ; CHECK-NEXT: br label [[MERGE:%.*]]
130 ; CHECK-NEXT: br label [[MERGE]]
132 ; CHECK-NEXT: [[RET:%.*]] = xor i1 [[COND]], true
133 ; CHECK-NEXT: ret i1 [[RET]]
136 br i1 %cond, label %if.true, label %if.false
142 %iv1 = phi i32 [0, %if.true], [%iv1.next, %loop1]
143 %iv1.next = add i32 %iv1, 1
144 %loop.cond.1 = icmp slt i32 %iv1.next, %cnt1
145 br i1 %loop.cond.1, label %loop1, label %if.true.end
154 %ret = phi i1 [false, %if.true.end], [true, %if.false]
158 define i1 @test_multiple_predecessors(i1 %cond, i1 %cond2) {
159 ; CHECK-LABEL: @test_multiple_predecessors(
161 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
163 ; CHECK-NEXT: br label [[MERGE:%.*]]
165 ; CHECK-NEXT: br i1 [[COND2:%.*]], label [[IF2_TRUE:%.*]], label [[IF2_FALSE:%.*]]
167 ; CHECK-NEXT: br label [[MERGE]]
169 ; CHECK-NEXT: br label [[MERGE]]
171 ; CHECK-NEXT: ret i1 [[COND]]
174 br i1 %cond, label %if.true, label %if.false
180 br i1 %cond2, label %if2.true, label %if2.false
189 %ret = phi i1 [ true, %if.true ], [ false, %if2.true ], [ false, %if2.false ]
193 define i1 @test_multiple_predecessors_wrong_value(i1 %cond, i1 %cond2) {
194 ; CHECK-LABEL: @test_multiple_predecessors_wrong_value(
196 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
198 ; CHECK-NEXT: br label [[MERGE:%.*]]
200 ; CHECK-NEXT: br i1 [[COND2:%.*]], label [[IF2_TRUE:%.*]], label [[IF2_FALSE:%.*]]
202 ; CHECK-NEXT: br label [[MERGE]]
204 ; CHECK-NEXT: br label [[MERGE]]
206 ; CHECK-NEXT: [[RET:%.*]] = phi i1 [ true, [[IF_TRUE]] ], [ true, [[IF2_TRUE]] ], [ false, [[IF2_FALSE]] ]
207 ; CHECK-NEXT: ret i1 [[RET]]
210 br i1 %cond, label %if.true, label %if.false
216 br i1 %cond2, label %if2.true, label %if2.false
225 %ret = phi i1 [ true, %if.true ], [ true, %if2.true ], [ false, %if2.false ]
229 define i1 @test_multiple_predecessors_no_edge_domination(i1 %cond, i1 %cond2) {
230 ; CHECK-LABEL: @test_multiple_predecessors_no_edge_domination(
232 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
234 ; CHECK-NEXT: br i1 [[COND2:%.*]], label [[MERGE:%.*]], label [[IF_FALSE]]
236 ; CHECK-NEXT: br i1 [[COND2]], label [[IF2_TRUE:%.*]], label [[IF2_FALSE:%.*]]
238 ; CHECK-NEXT: br label [[MERGE]]
240 ; CHECK-NEXT: br label [[MERGE]]
242 ; CHECK-NEXT: [[RET:%.*]] = phi i1 [ true, [[IF_TRUE]] ], [ false, [[IF2_TRUE]] ], [ false, [[IF2_FALSE]] ]
243 ; CHECK-NEXT: ret i1 [[RET]]
246 br i1 %cond, label %if.true, label %if.false
249 br i1 %cond2, label %merge, label %if.false
252 br i1 %cond2, label %if2.true, label %if2.false
261 %ret = phi i1 [ true, %if.true ], [ false, %if2.true ], [ false, %if2.false ]
265 define i8 @test_switch(i8 %cond) {
266 ; CHECK-LABEL: @test_switch(
268 ; CHECK-NEXT: switch i8 [[COND:%.*]], label [[DEFAULT:%.*]] [
269 ; CHECK-NEXT: i8 1, label [[SW_1:%.*]]
270 ; CHECK-NEXT: i8 7, label [[SW_7:%.*]]
271 ; CHECK-NEXT: i8 19, label [[SW_19:%.*]]
274 ; CHECK-NEXT: br label [[MERGE:%.*]]
276 ; CHECK-NEXT: br label [[MERGE]]
278 ; CHECK-NEXT: br label [[MERGE]]
280 ; CHECK-NEXT: ret i8 42
282 ; CHECK-NEXT: ret i8 [[COND]]
285 switch i8 %cond, label %default [
304 %ret = phi i8 [ 1, %sw.1 ], [ 7, %sw.7 ], [ 19, %sw.19 ]
308 define i8 @test_switch_direct_edge(i8 %cond) {
309 ; CHECK-LABEL: @test_switch_direct_edge(
311 ; CHECK-NEXT: switch i8 [[COND:%.*]], label [[DEFAULT:%.*]] [
312 ; CHECK-NEXT: i8 1, label [[SW_1:%.*]]
313 ; CHECK-NEXT: i8 7, label [[SW_7:%.*]]
314 ; CHECK-NEXT: i8 19, label [[MERGE:%.*]]
317 ; CHECK-NEXT: br label [[MERGE]]
319 ; CHECK-NEXT: br label [[MERGE]]
321 ; CHECK-NEXT: ret i8 42
323 ; CHECK-NEXT: ret i8 [[COND]]
326 switch i8 %cond, label %default [
342 %ret = phi i8 [ 1, %sw.1 ], [ 7, %sw.7 ], [ 19, %entry ]
346 define i8 @test_switch_duplicate_direct_edge(i8 %cond) {
347 ; CHECK-LABEL: @test_switch_duplicate_direct_edge(
349 ; CHECK-NEXT: switch i8 [[COND:%.*]], label [[DEFAULT:%.*]] [
350 ; CHECK-NEXT: i8 1, label [[SW_1:%.*]]
351 ; CHECK-NEXT: i8 7, label [[MERGE:%.*]]
352 ; CHECK-NEXT: i8 19, label [[MERGE]]
355 ; CHECK-NEXT: br label [[MERGE]]
357 ; CHECK-NEXT: ret i8 42
359 ; CHECK-NEXT: [[RET:%.*]] = phi i8 [ 1, [[SW_1]] ], [ 7, [[ENTRY:%.*]] ], [ 7, [[ENTRY]] ]
360 ; CHECK-NEXT: ret i8 [[RET]]
363 switch i8 %cond, label %default [
376 %ret = phi i8 [ 1, %sw.1 ], [ 7, %entry ], [ 7, %entry ]
380 define i8 @test_switch_subset(i8 %cond) {
381 ; CHECK-LABEL: @test_switch_subset(
383 ; CHECK-NEXT: switch i8 [[COND:%.*]], label [[DEFAULT:%.*]] [
384 ; CHECK-NEXT: i8 1, label [[SW_1:%.*]]
385 ; CHECK-NEXT: i8 7, label [[SW_7:%.*]]
386 ; CHECK-NEXT: i8 19, label [[SW_19:%.*]]
389 ; CHECK-NEXT: br label [[MERGE:%.*]]
391 ; CHECK-NEXT: br label [[MERGE]]
393 ; CHECK-NEXT: ret i8 24
395 ; CHECK-NEXT: ret i8 42
397 ; CHECK-NEXT: ret i8 [[COND]]
400 switch i8 %cond, label %default [
419 %ret = phi i8 [ 1, %sw.1 ], [ 7, %sw.7 ]
423 define i8 @test_switch_wrong_value(i8 %cond) {
424 ; CHECK-LABEL: @test_switch_wrong_value(
426 ; CHECK-NEXT: switch i8 [[COND:%.*]], label [[DEFAULT:%.*]] [
427 ; CHECK-NEXT: i8 1, label [[SW_1:%.*]]
428 ; CHECK-NEXT: i8 7, label [[SW_7:%.*]]
429 ; CHECK-NEXT: i8 19, label [[SW_19:%.*]]
432 ; CHECK-NEXT: br label [[MERGE:%.*]]
434 ; CHECK-NEXT: br label [[MERGE]]
436 ; CHECK-NEXT: br label [[MERGE]]
438 ; CHECK-NEXT: ret i8 42
440 ; CHECK-NEXT: [[RET:%.*]] = phi i8 [ 1, [[SW_1]] ], [ 7, [[SW_7]] ], [ 10, [[SW_19]] ]
441 ; CHECK-NEXT: ret i8 [[RET]]
444 switch i8 %cond, label %default [
463 %ret = phi i8 [ 1, %sw.1 ], [ 7, %sw.7 ], [ 10, %sw.19 ]
467 define i8 @test_switch_inverted(i8 %cond) {
468 ; CHECK-LABEL: @test_switch_inverted(
470 ; CHECK-NEXT: switch i8 [[COND:%.*]], label [[DEFAULT:%.*]] [
471 ; CHECK-NEXT: i8 0, label [[SW_0:%.*]]
472 ; CHECK-NEXT: i8 1, label [[SW_1:%.*]]
473 ; CHECK-NEXT: i8 2, label [[SW_2:%.*]]
476 ; CHECK-NEXT: br label [[MERGE:%.*]]
478 ; CHECK-NEXT: br label [[MERGE]]
480 ; CHECK-NEXT: br label [[MERGE]]
482 ; CHECK-NEXT: ret i8 42
484 ; CHECK-NEXT: [[RET:%.*]] = xor i8 [[COND]], -1
485 ; CHECK-NEXT: ret i8 [[RET]]
488 switch i8 %cond, label %default [
507 %ret = phi i8 [ -1, %sw.0 ], [ -2, %sw.1 ], [ -3, %sw.2 ]
511 define i8 @test_switch_duplicate_edge(i8 %cond) {
512 ; CHECK-LABEL: @test_switch_duplicate_edge(
514 ; CHECK-NEXT: switch i8 [[COND:%.*]], label [[DEFAULT:%.*]] [
515 ; CHECK-NEXT: i8 1, label [[SW_1:%.*]]
516 ; CHECK-NEXT: i8 7, label [[SW_7:%.*]]
517 ; CHECK-NEXT: i8 19, label [[SW_7]]
520 ; CHECK-NEXT: br label [[MERGE:%.*]]
522 ; CHECK-NEXT: br label [[MERGE]]
524 ; CHECK-NEXT: ret i8 42
526 ; CHECK-NEXT: [[RET:%.*]] = phi i8 [ 1, [[SW_1]] ], [ 7, [[SW_7]] ]
527 ; CHECK-NEXT: ret i8 [[RET]]
530 switch i8 %cond, label %default [
546 %ret = phi i8 [ 1, %sw.1 ], [ 7, %sw.7 ]
550 define i8 @test_switch_default_edge(i8 %cond) {
551 ; CHECK-LABEL: @test_switch_default_edge(
553 ; CHECK-NEXT: switch i8 [[COND:%.*]], label [[MERGE:%.*]] [
554 ; CHECK-NEXT: i8 1, label [[SW_1:%.*]]
555 ; CHECK-NEXT: i8 7, label [[SW_7:%.*]]
556 ; CHECK-NEXT: i8 19, label [[SW_19:%.*]]
559 ; CHECK-NEXT: br label [[MERGE]]
561 ; CHECK-NEXT: br label [[MERGE]]
563 ; CHECK-NEXT: br label [[MERGE]]
565 ; CHECK-NEXT: [[RET:%.*]] = phi i8 [ 1, [[SW_1]] ], [ 7, [[SW_7]] ], [ 19, [[SW_19]] ], [ 42, [[ENTRY:%.*]] ]
566 ; CHECK-NEXT: ret i8 [[RET]]
569 switch i8 %cond, label %merge [
585 %ret = phi i8 [ 1, %sw.1 ], [ 7, %sw.7 ], [ 19, %sw.19 ], [ 42, %entry ]
589 define i8 @test_switch_default_edge_direct(i8 %cond) {
590 ; CHECK-LABEL: @test_switch_default_edge_direct(
592 ; CHECK-NEXT: switch i8 [[COND:%.*]], label [[MERGE:%.*]] [
593 ; CHECK-NEXT: i8 1, label [[SW_1:%.*]]
594 ; CHECK-NEXT: i8 7, label [[SW_7:%.*]]
595 ; CHECK-NEXT: i8 19, label [[MERGE]]
598 ; CHECK-NEXT: br label [[MERGE]]
600 ; CHECK-NEXT: br label [[MERGE]]
602 ; CHECK-NEXT: [[RET:%.*]] = phi i8 [ 1, [[SW_1]] ], [ 7, [[SW_7]] ], [ 19, [[ENTRY:%.*]] ], [ 19, [[ENTRY]] ]
603 ; CHECK-NEXT: ret i8 [[RET]]
606 switch i8 %cond, label %merge [
616 %ret = phi i8 [ 1, %sw.1 ], [ 7, %sw.7 ], [ 19, %entry ], [ 19, %entry ]
620 define i8 @test_switch_default_edge_duplicate(i8 %cond) {
621 ; CHECK-LABEL: @test_switch_default_edge_duplicate(
623 ; CHECK-NEXT: switch i8 [[COND:%.*]], label [[SW_19:%.*]] [
624 ; CHECK-NEXT: i8 1, label [[SW_1:%.*]]
625 ; CHECK-NEXT: i8 7, label [[SW_7:%.*]]
626 ; CHECK-NEXT: i8 19, label [[SW_19]]
629 ; CHECK-NEXT: br label [[MERGE:%.*]]
631 ; CHECK-NEXT: br label [[MERGE]]
633 ; CHECK-NEXT: br label [[MERGE]]
635 ; CHECK-NEXT: [[RET:%.*]] = phi i8 [ 1, [[SW_1]] ], [ 7, [[SW_7]] ], [ 19, [[SW_19]] ]
636 ; CHECK-NEXT: ret i8 [[RET]]
639 switch i8 %cond, label %sw.19 [
651 %ret = phi i8 [ 1, %sw.1 ], [ 7, %sw.7 ], [ 19, %sw.19 ]