Follow up to d0858bffa11, add missing REQUIRES x86
[llvm-project.git] / llvm / test / Transforms / Util / flattencfg.ll
blob4a4d4279f360d6aa2954a4cb78e2f28b21d3d30c
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2 ; RUN: opt -passes=flattencfg -S < %s | FileCheck %s
5 ; This test checks whether the pass completes without a crash.
6 ; The code is not transformed in any way
7 define void @test_not_crash(i32 %in_a) #0 {
8 ; CHECK-LABEL: define void @test_not_crash
9 ; CHECK-SAME: (i32 [[IN_A:%.*]]) {
10 ; CHECK-NEXT:  entry:
11 ; CHECK-NEXT:    [[CMP0:%.*]] = icmp eq i32 [[IN_A]], -1
12 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[IN_A]], 0
13 ; CHECK-NEXT:    [[COND0:%.*]] = and i1 [[CMP0]], [[CMP1]]
14 ; CHECK-NEXT:    br i1 [[COND0]], label [[B0:%.*]], label [[B1:%.*]]
15 ; CHECK:       b0:
16 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[IN_A]], 0
17 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp ne i32 [[IN_A]], 1
18 ; CHECK-NEXT:    [[COND1:%.*]] = or i1 [[CMP2]], [[CMP3]]
19 ; CHECK-NEXT:    br i1 [[COND1]], label [[EXIT:%.*]], label [[B1]]
20 ; CHECK:       b1:
21 ; CHECK-NEXT:    br label [[EXIT]]
22 ; CHECK:       exit:
23 ; CHECK-NEXT:    ret void
25 entry:
26   %cmp0 = icmp eq i32 %in_a, -1
27   %cmp1 = icmp ne i32 %in_a, 0
28   %cond0 = and i1 %cmp0, %cmp1
29   br i1 %cond0, label %b0, label %b1
31 b0:                                ; preds = %entry
32   %cmp2 = icmp eq i32 %in_a, 0
33   %cmp3 = icmp ne i32 %in_a, 1
34   %cond1 = or i1 %cmp2, %cmp3
35   br i1 %cond1, label %exit, label %b1
37 b1:                                       ; preds = %entry, %b0
38   br label %exit
40 exit:                               ; preds = %entry, %b0, %b1
41   ret void
44 define void @test_not_crash2(float %a, float %b) #0 {
45 ; CHECK-LABEL: define void @test_not_crash2
46 ; CHECK-SAME: (float [[A:%.*]], float [[B:%.*]]) {
47 ; CHECK-NEXT:  entry:
48 ; CHECK-NEXT:    [[TMP0:%.*]] = fcmp ult float [[A]], 1.000000e+00
49 ; CHECK-NEXT:    [[TMP1:%.*]] = fcmp ult float [[B]], 1.000000e+00
50 ; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP0]], [[TMP1]]
51 ; CHECK-NEXT:    br i1 [[TMP2]], label [[BB4:%.*]], label [[BB3:%.*]]
52 ; CHECK:       bb3:
53 ; CHECK-NEXT:    br label [[BB4]]
54 ; CHECK:       bb4:
55 ; CHECK-NEXT:    ret void
57 entry:
58   %0 = fcmp ult float %a, 1.000000e+00
59   br i1 %0, label %bb0, label %bb1
61 bb3:                                               ; preds = %bb0
62   br label %bb4
64 bb4:                                               ; preds = %bb0, %bb3
65   ret void
67 bb1:                                               ; preds = %entry
68   br label %bb0
70 bb0:                                               ; preds = %bb1, %entry
71   %1 = fcmp ult float %b, 1.000000e+00
72   br i1 %1, label %bb4, label %bb3
75 define void @test_not_crash3(i32 %a) #0 {
76 ; CHECK-LABEL: define void @test_not_crash3
77 ; CHECK-SAME: (i32 [[A:%.*]]) {
78 ; CHECK-NEXT:  entry:
79 ; CHECK-NEXT:    [[A_EQ_0:%.*]] = icmp eq i32 [[A]], 0
80 ; CHECK-NEXT:    [[A_EQ_1:%.*]] = icmp eq i32 [[A]], 1
81 ; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[A_EQ_0]], [[A_EQ_1]]
82 ; CHECK-NEXT:    br i1 [[TMP0]], label [[BB2:%.*]], label [[BB3:%.*]]
83 ; CHECK:       bb2:
84 ; CHECK-NEXT:    br label [[BB3]]
85 ; CHECK:       bb3:
86 ; CHECK-NEXT:    [[CHECK_BADREF:%.*]] = phi i32 [ 17, [[ENTRY:%.*]] ], [ 11, [[BB2]] ]
87 ; CHECK-NEXT:    ret void
89 entry:
90   %a_eq_0 = icmp eq i32 %a, 0
91   br i1 %a_eq_0, label %bb0, label %bb1
93 bb0:                                              ; preds = %entry
94   br label %bb1
96 bb1:                                              ; preds = %bb0, %entry
97   %a_eq_1 = icmp eq i32 %a, 1
98   br i1 %a_eq_1, label %bb2, label %bb3
100 bb2:                                              ; preds = %bb1
101   br label %bb3
103 bb3:                                              ; preds = %bb2, %bb1
104   %check_badref = phi i32 [ 17, %bb1 ], [ 11, %bb2 ]
105   ret void
109 @g = global i32 0, align 4
111 define void @test_then(i32 %x, i32 %y, i32 %z) {
112 ; CHECK-LABEL: define void @test_then
113 ; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
114 ; CHECK-NEXT:  entry.x:
115 ; CHECK-NEXT:    [[CMP_X:%.*]] = icmp ne i32 [[X]], 0
116 ; CHECK-NEXT:    [[CMP_Y:%.*]] = icmp ne i32 [[Y]], 0
117 ; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[CMP_X]], [[CMP_Y]]
118 ; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_THEN_Y:%.*]], label [[EXIT:%.*]]
119 ; CHECK:       if.then.y:
120 ; CHECK-NEXT:    store i32 [[Z]], ptr @g, align 4
121 ; CHECK-NEXT:    br label [[EXIT]]
122 ; CHECK:       exit:
123 ; CHECK-NEXT:    ret void
125 entry.x:
126   %cmp.x = icmp ne i32 %x, 0
127   br i1 %cmp.x, label %if.then.x, label %entry.y
129 if.then.x:
130   store i32 %z, ptr @g, align 4
131   br label %entry.y
133 entry.y:
134   %cmp.y = icmp ne i32 %y, 0
135   br i1 %cmp.y, label %if.then.y, label %exit
137 if.then.y:
138   store i32 %z, ptr @g, align 4
139   br label %exit
141 exit:
142   ret void
145 define void @test_else(i32 %x, i32 %y, i32 %z) {
146 ; CHECK-LABEL: define void @test_else
147 ; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
148 ; CHECK-NEXT:  entry.x:
149 ; CHECK-NEXT:    [[CMP_X:%.*]] = icmp eq i32 [[X]], 0
150 ; CHECK-NEXT:    [[CMP_Y:%.*]] = icmp eq i32 [[Y]], 0
151 ; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[CMP_X]], [[CMP_Y]]
152 ; CHECK-NEXT:    br i1 [[TMP0]], label [[EXIT:%.*]], label [[IF_ELSE_Y:%.*]]
153 ; CHECK:       if.else.y:
154 ; CHECK-NEXT:    store i32 [[Z]], ptr @g, align 4
155 ; CHECK-NEXT:    br label [[EXIT]]
156 ; CHECK:       exit:
157 ; CHECK-NEXT:    ret void
159 entry.x:
160   %cmp.x = icmp eq i32 %x, 0
161   br i1 %cmp.x, label %entry.y, label %if.else.x
163 if.else.x:
164   store i32 %z, ptr @g, align 4
165   br label %entry.y
167 entry.y:
168   %cmp.y = icmp eq i32 %y, 0
169   br i1 %cmp.y, label %exit, label %if.else.y
171 if.else.y:
172   store i32 %z, ptr @g, align 4
173   br label %exit
175 exit:
176   ret void
179 define void @test_combine_and(i32 %x, i32 %y, i32 %z) {
180 ; CHECK-LABEL: define void @test_combine_and
181 ; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
182 ; CHECK-NEXT:  entry.x:
183 ; CHECK-NEXT:    [[CMP_X:%.*]] = icmp eq i32 [[X]], 0
184 ; CHECK-NEXT:    [[CMP_Y:%.*]] = icmp eq i32 [[Y]], 0
185 ; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[CMP_X]], [[CMP_Y]]
186 ; CHECK-NEXT:    br i1 [[TMP0]], label [[EXIT:%.*]], label [[IF_THEN_Y:%.*]]
187 ; CHECK:       if.then.y:
188 ; CHECK-NEXT:    store i32 [[Z]], ptr @g, align 4
189 ; CHECK-NEXT:    br label [[EXIT]]
190 ; CHECK:       exit:
191 ; CHECK-NEXT:    ret void
193 entry.x:
194   %cmp.x = icmp eq i32 %x, 0
195   br i1 %cmp.x, label %entry.y, label %if.else.x
197 if.else.x:
198   store i32 %z, ptr @g, align 4
199   br label %entry.y
201 entry.y:
202   %cmp.y = icmp ne i32 %y, 0
203   br i1 %cmp.y, label %if.then.y, label %exit
205 if.then.y:
206   store i32 %z, ptr @g, align 4
207   br label %exit
209 exit:
210   ret void
213 define void @test_combine_or(i32 %x, i32 %y, i32 %z) {
214 ; CHECK-LABEL: define void @test_combine_or
215 ; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
216 ; CHECK-NEXT:  entry.x:
217 ; CHECK-NEXT:    [[CMP_X:%.*]] = icmp ne i32 [[X]], 0
218 ; CHECK-NEXT:    [[CMP_Y:%.*]] = icmp ne i32 [[Y]], 0
219 ; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[CMP_X]], [[CMP_Y]]
220 ; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_ELSE_Y:%.*]], label [[EXIT:%.*]]
221 ; CHECK:       if.else.y:
222 ; CHECK-NEXT:    store i32 [[Z]], ptr @g, align 4
223 ; CHECK-NEXT:    br label [[EXIT]]
224 ; CHECK:       exit:
225 ; CHECK-NEXT:    ret void
227 entry.x:
228   %cmp.x = icmp ne i32 %x, 0
229   br i1 %cmp.x, label %if.then.x, label %entry.y
231 if.then.x:
232   store i32 %z, ptr @g, align 4
233   br label %entry.y
235 entry.y:
236   %cmp.y = icmp eq i32 %y, 0
237   br i1 %cmp.y, label %exit, label %if.else.y
239 if.else.y:
240   store i32 %z, ptr @g, align 4
241   br label %exit
243 exit:
244   ret void
247 declare i1 @llvm.smax.i1(i1, i1) #0
249 define void @PR56875(i1 %val_i1_5) {
250 ; CHECK-LABEL: define void @PR56875
251 ; CHECK-SAME: (i1 [[VAL_I1_5:%.*]]) {
252 ; CHECK-NEXT:  entry_1:
253 ; CHECK-NEXT:    ret void
254 ; CHECK:       bb_2:
255 ; CHECK-NEXT:    br label [[BB_4:%.*]]
256 ; CHECK:       bb_4:
257 ; CHECK-NEXT:    [[VAL_I1_46:%.*]] = call i1 @llvm.smax.i1(i1 [[VAL_I1_5]], i1 [[VAL_I1_5]])
258 ; CHECK-NEXT:    br i1 [[VAL_I1_46]], label [[BB_4]], label [[BB_2:%.*]]
260 entry_1:
261   ret void
263 bb_2:                                             ; preds = %bb_4
264   br label %bb_4
266 bb_4:                                             ; preds = %bb_4, %bb_2
267   %val_i1_46 = call i1 @llvm.smax.i1(i1 %val_i1_5, i1 %val_i1_5)
268   br i1 %val_i1_46, label %bb_4, label %bb_2
271 ; cmp.y has 2 users, but should be inverted. So that a new one cmp is created instead.
272 ; Branch condition must be replaced with a new created combined condition
273 ; Proof of bug: https://alive2.llvm.org/ce/z/L4ps9v
274 ; Proof of fix: https://alive2.llvm.org/ce/z/QdrG5U
275 define i1 @test_cond_multi_use(i32 %x, i32 %y, i32 %z) {
276 ; CHECK-LABEL: define i1 @test_cond_multi_use
277 ; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
278 ; CHECK-NEXT:  entry.x:
279 ; CHECK-NEXT:    [[CMP_X:%.*]] = icmp ne i32 [[X]], 0
280 ; CHECK-NEXT:    [[CMP_Y:%.*]] = icmp eq i32 [[Y]], 0
281 ; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[CMP_Y]], true
282 ; CHECK-NEXT:    [[TMP1:%.*]] = or i1 [[CMP_X]], [[TMP0]]
283 ; CHECK-NEXT:    br i1 [[TMP1]], label [[IF_THEN_Y:%.*]], label [[EXIT:%.*]]
284 ; CHECK:       if.then.y:
285 ; CHECK-NEXT:    store i32 [[Z]], ptr @g, align 4
286 ; CHECK-NEXT:    br label [[EXIT]]
287 ; CHECK:       exit:
288 ; CHECK-NEXT:    ret i1 [[CMP_Y]]
290 entry.x:
291   %cmp.x = icmp ne i32 %x, 0
292   br i1 %cmp.x, label %if.then.x, label %entry.y
294 if.then.x:
295   store i32 %z, ptr @g, align 4
296   br label %entry.y
298 entry.y:
299   %cmp.y = icmp eq i32 %y, 0
300   br i1 %cmp.y, label %exit, label %if.then.y
302 if.then.y:
303   store i32 %z, ptr @g, align 4
304   br label %exit
306 exit:
307   ret i1 %cmp.y