xref: /llvm-project/llvm/test/Transforms/Util/flatten-cfg.ll (revision f920b746ea818f1d21f317116cbb105e3e85979a)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt -passes=flatten-cfg -S < %s | FileCheck %s
3
4
5; This test checks whether the pass completes without a crash.
6; The code is not transformed in any way
7define 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
24;
25entry:
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
30
31b0:                                ; 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
36
37b1:                                       ; preds = %entry, %b0
38  br label %exit
39
40exit:                               ; preds = %entry, %b0, %b1
41  ret void
42}
43
44define 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
56;
57entry:
58  %0 = fcmp ult float %a, 1.000000e+00
59  br i1 %0, label %bb0, label %bb1
60
61bb3:                                               ; preds = %bb0
62  br label %bb4
63
64bb4:                                               ; preds = %bb0, %bb3
65  ret void
66
67bb1:                                               ; preds = %entry
68  br label %bb0
69
70bb0:                                               ; preds = %bb1, %entry
71  %1 = fcmp ult float %b, 1.000000e+00
72  br i1 %1, label %bb4, label %bb3
73}
74
75define 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:    br i1 [[A_EQ_0]], label [[BB0:%.*]], label [[BB1:%.*]]
81; CHECK:       bb0:
82; CHECK-NEXT:    br label [[BB1]]
83; CHECK:       bb1:
84; CHECK-NEXT:    [[A_EQ_1:%.*]] = icmp eq i32 [[A]], 1
85; CHECK-NEXT:    br i1 [[A_EQ_1]], label [[BB2:%.*]], label [[BB3:%.*]]
86; CHECK:       bb2:
87; CHECK-NEXT:    br label [[BB3]]
88; CHECK:       bb3:
89; CHECK-NEXT:    [[CHECK_BADREF:%.*]] = phi i32 [ 17, [[BB1]] ], [ 11, [[BB2]] ]
90; CHECK-NEXT:    ret void
91;
92entry:
93  %a_eq_0 = icmp eq i32 %a, 0
94  br i1 %a_eq_0, label %bb0, label %bb1
95
96bb0:                                              ; preds = %entry
97  br label %bb1
98
99bb1:                                              ; preds = %bb0, %entry
100  %a_eq_1 = icmp eq i32 %a, 1
101  br i1 %a_eq_1, label %bb2, label %bb3
102
103bb2:                                              ; preds = %bb1
104  br label %bb3
105
106bb3:                                              ; preds = %bb2, %bb1
107  %check_badref = phi i32 [ 17, %bb1 ], [ 11, %bb2 ]
108  ret void
109}
110
111
112@g = global i32 0, align 4
113
114define void @test_then(i32 %x, i32 %y, i32 %z) {
115; CHECK-LABEL: define void @test_then
116; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
117; CHECK-NEXT:  entry.x:
118; CHECK-NEXT:    [[CMP_X:%.*]] = icmp ne i32 [[X]], 0
119; CHECK-NEXT:    [[CMP_Y:%.*]] = icmp ne i32 [[Y]], 0
120; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[CMP_X]], [[CMP_Y]]
121; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_THEN_Y:%.*]], label [[EXIT:%.*]]
122; CHECK:       if.then.y:
123; CHECK-NEXT:    store i32 [[Z]], ptr @g, align 4
124; CHECK-NEXT:    br label [[EXIT]]
125; CHECK:       exit:
126; CHECK-NEXT:    ret void
127;
128entry.x:
129  %cmp.x = icmp ne i32 %x, 0
130  br i1 %cmp.x, label %if.then.x, label %entry.y
131
132if.then.x:
133  store i32 %z, ptr @g, align 4
134  br label %entry.y
135
136entry.y:
137  %cmp.y = icmp ne i32 %y, 0
138  br i1 %cmp.y, label %if.then.y, label %exit
139
140if.then.y:
141  store i32 %z, ptr @g, align 4
142  br label %exit
143
144exit:
145  ret void
146}
147
148define void @test_else(i32 %x, i32 %y, i32 %z) {
149; CHECK-LABEL: define void @test_else
150; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
151; CHECK-NEXT:  entry.x:
152; CHECK-NEXT:    [[CMP_X:%.*]] = icmp eq i32 [[X]], 0
153; CHECK-NEXT:    [[CMP_Y:%.*]] = icmp eq i32 [[Y]], 0
154; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[CMP_X]], [[CMP_Y]]
155; CHECK-NEXT:    br i1 [[TMP0]], label [[EXIT:%.*]], label [[IF_ELSE_Y:%.*]]
156; CHECK:       if.else.y:
157; CHECK-NEXT:    store i32 [[Z]], ptr @g, align 4
158; CHECK-NEXT:    br label [[EXIT]]
159; CHECK:       exit:
160; CHECK-NEXT:    ret void
161;
162entry.x:
163  %cmp.x = icmp eq i32 %x, 0
164  br i1 %cmp.x, label %entry.y, label %if.else.x
165
166if.else.x:
167  store i32 %z, ptr @g, align 4
168  br label %entry.y
169
170entry.y:
171  %cmp.y = icmp eq i32 %y, 0
172  br i1 %cmp.y, label %exit, label %if.else.y
173
174if.else.y:
175  store i32 %z, ptr @g, align 4
176  br label %exit
177
178exit:
179  ret void
180}
181
182define void @test_combine_and(i32 %x, i32 %y, i32 %z) {
183; CHECK-LABEL: define void @test_combine_and
184; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
185; CHECK-NEXT:  entry.x:
186; CHECK-NEXT:    [[CMP_X:%.*]] = icmp eq i32 [[X]], 0
187; CHECK-NEXT:    [[CMP_Y:%.*]] = icmp eq i32 [[Y]], 0
188; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[CMP_X]], [[CMP_Y]]
189; CHECK-NEXT:    br i1 [[TMP0]], label [[EXIT:%.*]], label [[IF_THEN_Y:%.*]]
190; CHECK:       if.then.y:
191; CHECK-NEXT:    store i32 [[Z]], ptr @g, align 4
192; CHECK-NEXT:    br label [[EXIT]]
193; CHECK:       exit:
194; CHECK-NEXT:    ret void
195;
196entry.x:
197  %cmp.x = icmp eq i32 %x, 0
198  br i1 %cmp.x, label %entry.y, label %if.else.x
199
200if.else.x:
201  store i32 %z, ptr @g, align 4
202  br label %entry.y
203
204entry.y:
205  %cmp.y = icmp ne i32 %y, 0
206  br i1 %cmp.y, label %if.then.y, label %exit
207
208if.then.y:
209  store i32 %z, ptr @g, align 4
210  br label %exit
211
212exit:
213  ret void
214}
215
216define void @test_combine_or(i32 %x, i32 %y, i32 %z) {
217; CHECK-LABEL: define void @test_combine_or
218; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
219; CHECK-NEXT:  entry.x:
220; CHECK-NEXT:    [[CMP_X:%.*]] = icmp ne i32 [[X]], 0
221; CHECK-NEXT:    [[CMP_Y:%.*]] = icmp ne i32 [[Y]], 0
222; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[CMP_X]], [[CMP_Y]]
223; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_ELSE_Y:%.*]], label [[EXIT:%.*]]
224; CHECK:       if.else.y:
225; CHECK-NEXT:    store i32 [[Z]], ptr @g, align 4
226; CHECK-NEXT:    br label [[EXIT]]
227; CHECK:       exit:
228; CHECK-NEXT:    ret void
229;
230entry.x:
231  %cmp.x = icmp ne i32 %x, 0
232  br i1 %cmp.x, label %if.then.x, label %entry.y
233
234if.then.x:
235  store i32 %z, ptr @g, align 4
236  br label %entry.y
237
238entry.y:
239  %cmp.y = icmp eq i32 %y, 0
240  br i1 %cmp.y, label %exit, label %if.else.y
241
242if.else.y:
243  store i32 %z, ptr @g, align 4
244  br label %exit
245
246exit:
247  ret void
248}
249
250declare i1 @llvm.smax.i1(i1, i1) #0
251
252define void @PR56875(i1 %val_i1_5) {
253; CHECK-LABEL: define void @PR56875
254; CHECK-SAME: (i1 [[VAL_I1_5:%.*]]) {
255; CHECK-NEXT:  entry_1:
256; CHECK-NEXT:    ret void
257; CHECK:       bb_2:
258; CHECK-NEXT:    br label [[BB_4:%.*]]
259; CHECK:       bb_4:
260; CHECK-NEXT:    [[VAL_I1_46:%.*]] = call i1 @llvm.smax.i1(i1 [[VAL_I1_5]], i1 [[VAL_I1_5]])
261; CHECK-NEXT:    br i1 [[VAL_I1_46]], label [[BB_4]], label [[BB_2:%.*]]
262;
263entry_1:
264  ret void
265
266bb_2:                                             ; preds = %bb_4
267  br label %bb_4
268
269bb_4:                                             ; preds = %bb_4, %bb_2
270  %val_i1_46 = call i1 @llvm.smax.i1(i1 %val_i1_5, i1 %val_i1_5)
271  br i1 %val_i1_46, label %bb_4, label %bb_2
272}
273
274; cmp.y has 2 users, but should be inverted. So that a new one cmp is created instead.
275; Branch condition must be replaced with a new created combined condition
276; Proof of bug: https://alive2.llvm.org/ce/z/L4ps9v
277; Proof of fix: https://alive2.llvm.org/ce/z/QdrG5U
278define i1 @test_cond_multi_use(i32 %x, i32 %y, i32 %z) {
279; CHECK-LABEL: define i1 @test_cond_multi_use
280; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
281; CHECK-NEXT:  entry.x:
282; CHECK-NEXT:    [[CMP_X:%.*]] = icmp ne i32 [[X]], 0
283; CHECK-NEXT:    [[CMP_Y:%.*]] = icmp eq i32 [[Y]], 0
284; CHECK-NEXT:    [[CMP_Y_NOT:%.*]] = xor i1 [[CMP_Y]], true
285; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[CMP_X]], [[CMP_Y_NOT]]
286; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_THEN_Y:%.*]], label [[EXIT:%.*]]
287; CHECK:       if.then.y:
288; CHECK-NEXT:    store i32 [[Z]], ptr @g, align 4
289; CHECK-NEXT:    br label [[EXIT]]
290; CHECK:       exit:
291; CHECK-NEXT:    ret i1 [[CMP_Y]]
292;
293entry.x:
294  %cmp.x = icmp ne i32 %x, 0
295  br i1 %cmp.x, label %if.then.x, label %entry.y
296
297if.then.x:
298  store i32 %z, ptr @g, align 4
299  br label %entry.y
300
301entry.y:
302  %cmp.y = icmp eq i32 %y, 0
303  br i1 %cmp.y, label %exit, label %if.then.y
304
305if.then.y:
306  store i32 %z, ptr @g, align 4
307  br label %exit
308
309exit:
310  ret i1 %cmp.y
311}
312