xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/branch-fold-multiple.ll (revision 9d5adc7e49c12e5a9f8225d0460509b6be8ea344)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt %s -S -o - -passes=simplifycfg | FileCheck %s
3
4%struct.S = type { [4 x i32] }
5
6; Check the second, third, and fourth basic blocks are folded into
7; the first basic block since each has one bonus intruction, which
8; does not exceed the default bouns instruction threshold of 1.
9
10define i1 @test1(i32 %0, i32 %1, i32 %2, i32 %3) {
11; CHECK-LABEL: @test1(
12; CHECK-NEXT:  entry:
13; CHECK-NEXT:    [[MUL0:%.*]] = mul i32 [[TMP0:%.*]], [[TMP0]]
14; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[MUL0]], 0
15; CHECK-NEXT:    [[MUL1:%.*]] = mul i32 [[TMP1:%.*]], [[TMP1]]
16; CHECK-NEXT:    [[CMP2_1:%.*]] = icmp sgt i32 [[MUL1]], 0
17; CHECK-NEXT:    [[OR_COND:%.*]] = select i1 [[CMP2]], i1 true, i1 [[CMP2_1]]
18; CHECK-NEXT:    [[MUL2:%.*]] = mul i32 [[TMP2:%.*]], [[TMP2]]
19; CHECK-NEXT:    [[CMP2_2:%.*]] = icmp sgt i32 [[MUL2]], 0
20; CHECK-NEXT:    [[OR_COND1:%.*]] = select i1 [[OR_COND]], i1 true, i1 [[CMP2_2]]
21; CHECK-NEXT:    [[MUL3:%.*]] = mul i32 [[TMP3:%.*]], [[TMP3]]
22; CHECK-NEXT:    [[CMP2_3:%.*]] = icmp sgt i32 [[MUL3]], 0
23; CHECK-NEXT:    [[OR_COND2:%.*]] = select i1 [[OR_COND1]], i1 true, i1 [[CMP2_3]]
24; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[OR_COND2]], i1 false, i1 true
25; CHECK-NEXT:    ret i1 [[SPEC_SELECT]]
26;
27entry:
28  %mul0 = mul i32 %0, %0
29  %cmp2 = icmp sgt i32 %mul0, 0
30  br i1 %cmp2, label %cleanup, label %for.cond
31
32for.cond:
33  %mul1 = mul i32 %1, %1
34  %cmp2.1 = icmp sgt i32 %mul1, 0
35  br i1 %cmp2.1, label %cleanup, label %for.cond.1
36
37for.cond.1:
38  %mul2 = mul i32 %2, %2
39  %cmp2.2 = icmp sgt i32 %mul2, 0
40  br i1 %cmp2.2, label %cleanup, label %for.cond.2
41
42for.cond.2:
43  %mul3 = mul i32 %3, %3
44  %cmp2.3 = icmp sgt i32 %mul3, 0
45  br i1 %cmp2.3, label %cleanup, label %for.cond.3
46
47for.cond.3:
48  br label %cleanup
49
50cleanup:
51  %cmp = phi i1 [ false, %entry ], [ false, %for.cond ], [ false, %for.cond.1 ], [ false, %for.cond.2 ], [ true, %for.cond.3 ]
52  ret i1 %cmp
53}
54
55; Check the second, third, and forth basic blocks are folded into the first
56; basic block since each has no bonus instruction.
57
58define i1 @test2(i32 %0, i32 %1, i32 %2, i32 %3) {
59; CHECK-LABEL: @test2(
60; CHECK-NEXT:  entry:
61; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[TMP0:%.*]], 0
62; CHECK-NEXT:    [[CMP2_1:%.*]] = icmp sgt i32 [[TMP1:%.*]], 0
63; CHECK-NEXT:    [[OR_COND:%.*]] = select i1 [[CMP2]], i1 true, i1 [[CMP2_1]]
64; CHECK-NEXT:    [[CMP2_2:%.*]] = icmp sgt i32 [[TMP2:%.*]], 0
65; CHECK-NEXT:    [[OR_COND1:%.*]] = select i1 [[OR_COND]], i1 true, i1 [[CMP2_2]]
66; CHECK-NEXT:    [[CMP2_3:%.*]] = icmp sgt i32 [[TMP3:%.*]], 0
67; CHECK-NEXT:    [[OR_COND2:%.*]] = select i1 [[OR_COND1]], i1 true, i1 [[CMP2_3]]
68; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[OR_COND2]], i1 false, i1 true
69; CHECK-NEXT:    ret i1 [[SPEC_SELECT]]
70;
71entry:
72  %cmp2 = icmp sgt i32 %0, 0
73  br i1 %cmp2, label %cleanup, label %for.cond
74
75for.cond:
76  %cmp2.1 = icmp sgt i32 %1, 0
77  br i1 %cmp2.1, label %cleanup, label %for.cond.1
78
79for.cond.1:
80  %cmp2.2 = icmp sgt i32 %2, 0
81  br i1 %cmp2.2, label %cleanup, label %for.cond.2
82
83for.cond.2:
84  %cmp2.3 = icmp sgt i32 %3, 0
85  br i1 %cmp2.3, label %cleanup, label %for.cond.3
86
87for.cond.3:
88  br label %cleanup
89
90cleanup:
91  %cmp = phi i1 [ false, %entry ], [ false, %for.cond ], [ false, %for.cond.1 ], [ false, %for.cond.2 ], [ true, %for.cond.3 ]
92  ret i1 %cmp
93}
94
95; Check the second basic block is not folded into the first basic block
96; since it has three bonus instructions, which exceeds the default bonus
97; instruction threshold of 1. The third and fourth basic blocks are folded
98; into the second basic block since they do not have bonus instruction.
99
100define i1 @test3(i32 %0, i32 %1, i32 %2, i32 %3) {
101; CHECK-LABEL: @test3(
102; CHECK-NEXT:  entry:
103; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[TMP0:%.*]], 0
104; CHECK-NEXT:    br i1 [[CMP2]], label [[CLEANUP:%.*]], label [[FOR_COND:%.*]]
105; CHECK:       for.cond:
106; CHECK-NEXT:    [[MUL1:%.*]] = mul i32 [[TMP0]], [[TMP1:%.*]]
107; CHECK-NEXT:    [[MUL2:%.*]] = mul i32 [[MUL1]], [[TMP2:%.*]]
108; CHECK-NEXT:    [[MUL3:%.*]] = mul i32 [[MUL2]], [[TMP3:%.*]]
109; CHECK-NEXT:    [[MUL4:%.*]] = mul i32 [[MUL3]], [[TMP3]]
110; CHECK-NEXT:    [[MUL5:%.*]] = mul i32 [[MUL4]], [[TMP3]]
111; CHECK-NEXT:    [[MUL6:%.*]] = mul i32 [[MUL5]], [[TMP3]]
112; CHECK-NEXT:    [[CMP2_1:%.*]] = icmp sgt i32 [[MUL5]], 0
113; CHECK-NEXT:    [[CMP2_2:%.*]] = icmp sgt i32 [[TMP2]], 0
114; CHECK-NEXT:    [[OR_COND:%.*]] = select i1 [[CMP2_1]], i1 true, i1 [[CMP2_2]]
115; CHECK-NEXT:    [[CMP2_3:%.*]] = icmp sgt i32 [[TMP3]], 0
116; CHECK-NEXT:    [[OR_COND1:%.*]] = select i1 [[OR_COND]], i1 true, i1 [[CMP2_3]]
117; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[OR_COND1]], i1 false, i1 true
118; CHECK-NEXT:    br label [[CLEANUP]]
119; CHECK:       cleanup:
120; CHECK-NEXT:    [[CMP:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[FOR_COND]] ]
121; CHECK-NEXT:    ret i1 [[CMP]]
122;
123entry:
124  %cmp2 = icmp sgt i32 %0, 0
125  br i1 %cmp2, label %cleanup, label %for.cond
126
127for.cond:
128  %mul1 = mul i32 %0, %1
129  %mul2 = mul i32 %mul1, %2
130  %mul3 = mul i32 %mul2, %3
131  %mul4 = mul i32 %mul3, %3
132  %mul5 = mul i32 %mul4, %3
133  %mul6 = mul i32 %mul5, %3
134  %cmp2.1 = icmp sgt i32 %mul5, 0
135  br i1 %cmp2.1, label %cleanup, label %for.cond.1
136
137for.cond.1:
138  %cmp2.2 = icmp sgt i32 %2, 0
139  br i1 %cmp2.2, label %cleanup, label %for.cond.2
140
141for.cond.2:
142  %cmp2.3 = icmp sgt i32 %3, 0
143  br i1 %cmp2.3, label %cleanup, label %for.cond.3
144
145for.cond.3:
146  br label %cleanup
147
148cleanup:
149  %cmp = phi i1 [ false, %entry ], [ false, %for.cond ], [ false, %for.cond.1 ], [ false, %for.cond.2 ], [ true, %for.cond.3 ]
150  ret i1 %cmp
151}
152