1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=simplifycfg,instcombine -simplifycfg-require-and-preserve-domtree=1 < %s -simplifycfg-merge-cond-stores=true -simplifycfg-merge-cond-stores-aggressively=false -phi-node-folding-threshold=2 -S | FileCheck %s
4 ; This test should succeed and end up if-converted.
5 define void @test_simple(ptr %p, i32 %a, i32 %b) {
6 ; CHECK-LABEL: @test_simple(
8 ; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[A:%.*]], [[B:%.*]]
9 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP0]], 0
10 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[TMP2:%.*]], label [[TMP1:%.*]]
12 ; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0
13 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32
14 ; CHECK-NEXT: store i32 [[SPEC_SELECT]], ptr [[P:%.*]], align 4
15 ; CHECK-NEXT: br label [[TMP2]]
17 ; CHECK-NEXT: ret void
20 %x1 = icmp eq i32 %a, 0
21 br i1 %x1, label %fallthrough, label %yes1
28 %x2 = icmp eq i32 %b, 0
29 br i1 %x2, label %end, label %yes2
39 ; This is the same as test_simple, but the branch target order has been swapped
40 define void @test_simple_commuted(ptr %p, i32 %a, i32 %b) {
41 ; CHECK-LABEL: @test_simple_commuted(
43 ; CHECK-NEXT: [[X1_NOT:%.*]] = icmp eq i32 [[A:%.*]], 0
44 ; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B:%.*]], 0
45 ; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[X1_NOT]], [[X2]]
46 ; CHECK-NEXT: br i1 [[TMP0]], label [[TMP1:%.*]], label [[TMP2:%.*]]
48 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32
49 ; CHECK-NEXT: store i32 [[SPEC_SELECT]], ptr [[P:%.*]], align 4
50 ; CHECK-NEXT: br label [[TMP2]]
52 ; CHECK-NEXT: ret void
55 %x1 = icmp eq i32 %a, 0
56 br i1 %x1, label %yes1, label %fallthrough
63 %x2 = icmp eq i32 %b, 0
64 br i1 %x2, label %yes2, label %end
74 ; This test should entirely fold away, leaving one large basic block.
75 define void @test_recursive(ptr %p, i32 %a, i32 %b, i32 %c, i32 %d) {
76 ; CHECK-LABEL: @test_recursive(
78 ; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[A:%.*]], [[B:%.*]]
79 ; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[TMP0]], [[C:%.*]]
80 ; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[D:%.*]]
81 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP2]], 0
82 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[TMP4:%.*]], label [[TMP3:%.*]]
84 ; CHECK-NEXT: [[X4_NOT:%.*]] = icmp eq i32 [[D]], 0
85 ; CHECK-NEXT: [[X3_NOT:%.*]] = icmp eq i32 [[C]], 0
86 ; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0
87 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32
88 ; CHECK-NEXT: [[SPEC_SELECT1:%.*]] = select i1 [[X3_NOT]], i32 [[SPEC_SELECT]], i32 2
89 ; CHECK-NEXT: [[SPEC_SELECT2:%.*]] = select i1 [[X4_NOT]], i32 [[SPEC_SELECT1]], i32 3
90 ; CHECK-NEXT: store i32 [[SPEC_SELECT2]], ptr [[P:%.*]], align 4
91 ; CHECK-NEXT: br label [[TMP4]]
93 ; CHECK-NEXT: ret void
96 %x1 = icmp eq i32 %a, 0
97 br i1 %x1, label %fallthrough, label %yes1
101 br label %fallthrough
104 %x2 = icmp eq i32 %b, 0
105 br i1 %x2, label %next, label %yes2
112 %x3 = icmp eq i32 %c, 0
113 br i1 %x3, label %fallthrough2, label %yes3
117 br label %fallthrough2
120 %x4 = icmp eq i32 %d, 0
121 br i1 %x4, label %end, label %yes4
132 ; The code in each diamond is too large - it won't be if-converted so our
133 ; heuristics should say no.
134 define void @test_not_ifconverted(ptr %p, i32 %a, i32 %b) {
135 ; CHECK-LABEL: @test_not_ifconverted(
137 ; CHECK-NEXT: [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
138 ; CHECK-NEXT: br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]]
140 ; CHECK-NEXT: [[Y1:%.*]] = or i32 [[B:%.*]], 55
141 ; CHECK-NEXT: [[Y2:%.*]] = add i32 [[Y1]], 24
142 ; CHECK-NEXT: [[Y3:%.*]] = and i32 [[Y2]], 67
143 ; CHECK-NEXT: store i32 [[Y3]], ptr [[P:%.*]], align 4
144 ; CHECK-NEXT: br label [[FALLTHROUGH]]
145 ; CHECK: fallthrough:
146 ; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B]], 0
147 ; CHECK-NEXT: br i1 [[X2]], label [[END:%.*]], label [[YES2:%.*]]
149 ; CHECK-NEXT: [[Z1:%.*]] = or i32 [[A]], 55
150 ; CHECK-NEXT: [[Z2:%.*]] = add i32 [[Z1]], 24
151 ; CHECK-NEXT: [[Z3:%.*]] = and i32 [[Z2]], 67
152 ; CHECK-NEXT: store i32 [[Z3]], ptr [[P]], align 4
153 ; CHECK-NEXT: br label [[END]]
155 ; CHECK-NEXT: ret void
158 %x1 = icmp eq i32 %a, 0
159 br i1 %x1, label %fallthrough, label %yes1
163 %y2 = add i32 %y1, 24
164 %y3 = and i32 %y2, 67
165 store i32 %y3, ptr %p
166 br label %fallthrough
169 %x2 = icmp eq i32 %b, 0
170 br i1 %x2, label %end, label %yes2
174 %z2 = add i32 %z1, 24
175 %z3 = and i32 %z2, 67
176 store i32 %z3, ptr %p
183 ; The store to %p clobbers the previous store, so if-converting this would
185 define void @test_aliasing1(ptr %p, i32 %a, i32 %b) {
186 ; CHECK-LABEL: @test_aliasing1(
188 ; CHECK-NEXT: [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
189 ; CHECK-NEXT: br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]]
191 ; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4
192 ; CHECK-NEXT: br label [[FALLTHROUGH]]
193 ; CHECK: fallthrough:
194 ; CHECK-NEXT: [[Y1:%.*]] = load i32, ptr [[P]], align 4
195 ; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[Y1]], 0
196 ; CHECK-NEXT: br i1 [[X2]], label [[END:%.*]], label [[YES2:%.*]]
198 ; CHECK-NEXT: store i32 1, ptr [[P]], align 4
199 ; CHECK-NEXT: br label [[END]]
201 ; CHECK-NEXT: ret void
204 %x1 = icmp eq i32 %a, 0
205 br i1 %x1, label %fallthrough, label %yes1
209 br label %fallthrough
212 %y1 = load i32, ptr %p
213 %x2 = icmp eq i32 %y1, 0
214 br i1 %x2, label %end, label %yes2
224 ; The load from %q aliases with %p, so if-converting this would be illegal.
225 define void @test_aliasing2(ptr %p, ptr %q, i32 %a, i32 %b) {
226 ; CHECK-LABEL: @test_aliasing2(
228 ; CHECK-NEXT: [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
229 ; CHECK-NEXT: br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]]
231 ; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4
232 ; CHECK-NEXT: br label [[FALLTHROUGH]]
233 ; CHECK: fallthrough:
234 ; CHECK-NEXT: [[Y1:%.*]] = load i32, ptr [[Q:%.*]], align 4
235 ; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[Y1]], 0
236 ; CHECK-NEXT: br i1 [[X2]], label [[END:%.*]], label [[YES2:%.*]]
238 ; CHECK-NEXT: store i32 1, ptr [[P]], align 4
239 ; CHECK-NEXT: br label [[END]]
241 ; CHECK-NEXT: ret void
244 %x1 = icmp eq i32 %a, 0
245 br i1 %x1, label %fallthrough, label %yes1
249 br label %fallthrough
252 %y1 = load i32, ptr %q
253 %x2 = icmp eq i32 %y1, 0
254 br i1 %x2, label %end, label %yes2
266 ; This should get if-converted.
267 define i32 @test_diamond_simple(ptr %p, ptr %q, i32 %a, i32 %b) {
268 ; CHECK-LABEL: @test_diamond_simple(
270 ; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B:%.*]], 0
271 ; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[A:%.*]], [[B]]
272 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP0]], 0
273 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[TMP2:%.*]], label [[TMP1:%.*]]
275 ; CHECK-NEXT: [[SIMPLIFYCFG_MERGE:%.*]] = zext i1 [[X2]] to i32
276 ; CHECK-NEXT: store i32 [[SIMPLIFYCFG_MERGE]], ptr [[P:%.*]], align 4
277 ; CHECK-NEXT: br label [[TMP2]]
279 ; CHECK-NEXT: [[Z4:%.*]] = select i1 [[X2]], i32 3, i32 0
280 ; CHECK-NEXT: ret i32 [[Z4]]
283 %x1 = icmp eq i32 %a, 0
284 br i1 %x1, label %no1, label %yes1
288 br label %fallthrough
292 br label %fallthrough
295 %z2 = phi i32 [ %z1, %no1 ], [ 0, %yes1 ]
296 %x2 = icmp eq i32 %b, 0
297 br i1 %x2, label %no2, label %yes2
304 %z3 = sub i32 %z2, %b
308 %z4 = phi i32 [ %z3, %no2 ], [ 3, %yes2 ]
312 ; Now there is a call to f() in the bottom branch. The store in the first
313 ; branch would now be reordered with respect to the call if we if-converted,
315 define i32 @test_diamond_alias3(ptr %p, ptr %q, i32 %a, i32 %b) {
316 ; CHECK-LABEL: @test_diamond_alias3(
318 ; CHECK-NEXT: [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
319 ; CHECK-NEXT: br i1 [[X1]], label [[NO1:%.*]], label [[YES1:%.*]]
321 ; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4
322 ; CHECK-NEXT: br label [[FALLTHROUGH:%.*]]
324 ; CHECK-NEXT: call void @f()
325 ; CHECK-NEXT: br label [[FALLTHROUGH]]
326 ; CHECK: fallthrough:
327 ; CHECK-NEXT: [[Z2:%.*]] = phi i32 [ [[B:%.*]], [[NO1]] ], [ 0, [[YES1]] ]
328 ; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B]], 0
329 ; CHECK-NEXT: br i1 [[X2]], label [[NO2:%.*]], label [[YES2:%.*]]
331 ; CHECK-NEXT: store i32 1, ptr [[P]], align 4
332 ; CHECK-NEXT: br label [[END:%.*]]
334 ; CHECK-NEXT: call void @f()
335 ; CHECK-NEXT: [[Z3:%.*]] = sub nuw nsw i32 [[Z2]], [[B]]
336 ; CHECK-NEXT: br label [[END]]
338 ; CHECK-NEXT: [[Z4:%.*]] = phi i32 [ [[Z3]], [[NO2]] ], [ 3, [[YES2]] ]
339 ; CHECK-NEXT: ret i32 [[Z4]]
342 %x1 = icmp eq i32 %a, 0
343 br i1 %x1, label %no1, label %yes1
347 br label %fallthrough
352 br label %fallthrough
355 %z2 = phi i32 [ %z1, %no1 ], [ 0, %yes1 ]
356 %x2 = icmp eq i32 %b, 0
357 br i1 %x2, label %no2, label %yes2
365 %z3 = sub i32 %z2, %b
369 %z4 = phi i32 [ %z3, %no2 ], [ 3, %yes2 ]
373 ; This test has an outer if over the two triangles. This requires creating a new BB to hold the store.
374 define void @test_outer_if(ptr %p, i32 %a, i32 %b, i32 %c) {
375 ; CHECK-LABEL: @test_outer_if(
377 ; CHECK-NEXT: [[X3:%.*]] = icmp eq i32 [[C:%.*]], 0
378 ; CHECK-NEXT: br i1 [[X3]], label [[END:%.*]], label [[CONTINUE:%.*]]
380 ; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[A:%.*]], [[B:%.*]]
381 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP0]], 0
382 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[END]], label [[TMP1:%.*]]
384 ; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0
385 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32
386 ; CHECK-NEXT: store i32 [[SPEC_SELECT]], ptr [[P:%.*]], align 4
387 ; CHECK-NEXT: br label [[END]]
389 ; CHECK-NEXT: ret void
392 %x3 = icmp eq i32 %c, 0
393 br i1 %x3, label %end, label %continue
395 %x1 = icmp eq i32 %a, 0
396 br i1 %x1, label %fallthrough, label %yes1
399 br label %fallthrough
401 %x2 = icmp eq i32 %b, 0
402 br i1 %x2, label %end, label %yes2