xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/merge-cond-stores.ll (revision d77067d08a3f56dc2d0e6c95bd2852c943df743a)
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
3
4; This test should succeed and end up if-converted.
5define void @test_simple(ptr %p, i32 %a, i32 %b) {
6; CHECK-LABEL: @test_simple(
7; CHECK-NEXT:  entry:
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:%.*]]
11; CHECK:       1:
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]]
16; CHECK:       2:
17; CHECK-NEXT:    ret void
18;
19entry:
20  %x1 = icmp eq i32 %a, 0
21  br i1 %x1, label %fallthrough, label %yes1
22
23yes1:
24  store i32 0, ptr %p
25  br label %fallthrough
26
27fallthrough:
28  %x2 = icmp eq i32 %b, 0
29  br i1 %x2, label %end, label %yes2
30
31yes2:
32  store i32 1, ptr %p
33  br label %end
34
35end:
36  ret void
37}
38
39; This is the same as test_simple, but the branch target order has been swapped
40define void @test_simple_commuted(ptr %p, i32 %a, i32 %b) {
41; CHECK-LABEL: @test_simple_commuted(
42; CHECK-NEXT:  entry:
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:%.*]]
47; CHECK:       1:
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]]
51; CHECK:       2:
52; CHECK-NEXT:    ret void
53;
54entry:
55  %x1 = icmp eq i32 %a, 0
56  br i1 %x1, label %yes1, label %fallthrough
57
58yes1:
59  store i32 0, ptr %p
60  br label %fallthrough
61
62fallthrough:
63  %x2 = icmp eq i32 %b, 0
64  br i1 %x2, label %yes2, label %end
65
66yes2:
67  store i32 1, ptr %p
68  br label %end
69
70end:
71  ret void
72}
73
74; This test should entirely fold away, leaving one large basic block.
75define void @test_recursive(ptr %p, i32 %a, i32 %b, i32 %c, i32 %d) {
76; CHECK-LABEL: @test_recursive(
77; CHECK-NEXT:  entry:
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:%.*]]
83; CHECK:       3:
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]]
92; CHECK:       4:
93; CHECK-NEXT:    ret void
94;
95entry:
96  %x1 = icmp eq i32 %a, 0
97  br i1 %x1, label %fallthrough, label %yes1
98
99yes1:
100  store i32 0, ptr %p
101  br label %fallthrough
102
103fallthrough:
104  %x2 = icmp eq i32 %b, 0
105  br i1 %x2, label %next, label %yes2
106
107yes2:
108  store i32 1, ptr %p
109  br label %next
110
111next:
112  %x3 = icmp eq i32 %c, 0
113  br i1 %x3, label %fallthrough2, label %yes3
114
115yes3:
116  store i32 2, ptr %p
117  br label %fallthrough2
118
119fallthrough2:
120  %x4 = icmp eq i32 %d, 0
121  br i1 %x4, label %end, label %yes4
122
123yes4:
124  store i32 3, ptr %p
125  br label %end
126
127
128end:
129  ret void
130}
131
132; The code in each diamond is too large - it won't be if-converted so our
133; heuristics should say no.
134define void @test_not_ifconverted(ptr %p, i32 %a, i32 %b) {
135; CHECK-LABEL: @test_not_ifconverted(
136; CHECK-NEXT:  entry:
137; CHECK-NEXT:    [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
138; CHECK-NEXT:    br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]]
139; CHECK:       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:%.*]]
148; CHECK:       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]]
154; CHECK:       end:
155; CHECK-NEXT:    ret void
156;
157entry:
158  %x1 = icmp eq i32 %a, 0
159  br i1 %x1, label %fallthrough, label %yes1
160
161yes1:
162  %y1 = or i32 %b, 55
163  %y2 = add i32 %y1, 24
164  %y3 = and i32 %y2, 67
165  store i32 %y3, ptr %p
166  br label %fallthrough
167
168fallthrough:
169  %x2 = icmp eq i32 %b, 0
170  br i1 %x2, label %end, label %yes2
171
172yes2:
173  %z1 = or i32 %a, 55
174  %z2 = add i32 %z1, 24
175  %z3 = and i32 %z2, 67
176  store i32 %z3, ptr %p
177  br label %end
178
179end:
180  ret void
181}
182
183; The store to %p clobbers the previous store, so if-converting this would
184; be illegal.
185define void @test_aliasing1(ptr %p, i32 %a, i32 %b) {
186; CHECK-LABEL: @test_aliasing1(
187; CHECK-NEXT:  entry:
188; CHECK-NEXT:    [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
189; CHECK-NEXT:    br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]]
190; CHECK:       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:%.*]]
197; CHECK:       yes2:
198; CHECK-NEXT:    store i32 1, ptr [[P]], align 4
199; CHECK-NEXT:    br label [[END]]
200; CHECK:       end:
201; CHECK-NEXT:    ret void
202;
203entry:
204  %x1 = icmp eq i32 %a, 0
205  br i1 %x1, label %fallthrough, label %yes1
206
207yes1:
208  store i32 0, ptr %p
209  br label %fallthrough
210
211fallthrough:
212  %y1 = load i32, ptr %p
213  %x2 = icmp eq i32 %y1, 0
214  br i1 %x2, label %end, label %yes2
215
216yes2:
217  store i32 1, ptr %p
218  br label %end
219
220end:
221  ret void
222}
223
224; The load from %q aliases with %p, so if-converting this would be illegal.
225define void @test_aliasing2(ptr %p, ptr %q, i32 %a, i32 %b) {
226; CHECK-LABEL: @test_aliasing2(
227; CHECK-NEXT:  entry:
228; CHECK-NEXT:    [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
229; CHECK-NEXT:    br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]]
230; CHECK:       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:%.*]]
237; CHECK:       yes2:
238; CHECK-NEXT:    store i32 1, ptr [[P]], align 4
239; CHECK-NEXT:    br label [[END]]
240; CHECK:       end:
241; CHECK-NEXT:    ret void
242;
243entry:
244  %x1 = icmp eq i32 %a, 0
245  br i1 %x1, label %fallthrough, label %yes1
246
247yes1:
248  store i32 0, ptr %p
249  br label %fallthrough
250
251fallthrough:
252  %y1 = load i32, ptr %q
253  %x2 = icmp eq i32 %y1, 0
254  br i1 %x2, label %end, label %yes2
255
256yes2:
257  store i32 1, ptr %p
258  br label %end
259
260end:
261  ret void
262}
263
264declare void @f()
265
266; This should get if-converted.
267define i32 @test_diamond_simple(ptr %p, ptr %q, i32 %a, i32 %b) {
268; CHECK-LABEL: @test_diamond_simple(
269; CHECK-NEXT:  entry:
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:%.*]]
274; CHECK:       1:
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]]
278; CHECK:       2:
279; CHECK-NEXT:    [[Z4:%.*]] = select i1 [[X2]], i32 3, i32 0
280; CHECK-NEXT:    ret i32 [[Z4]]
281;
282entry:
283  %x1 = icmp eq i32 %a, 0
284  br i1 %x1, label %no1, label %yes1
285
286yes1:
287  store i32 0, ptr %p
288  br label %fallthrough
289
290no1:
291  %z1 = add i32 %a, %b
292  br label %fallthrough
293
294fallthrough:
295  %z2 = phi i32 [ %z1, %no1 ], [ 0, %yes1 ]
296  %x2 = icmp eq i32 %b, 0
297  br i1 %x2, label %no2, label %yes2
298
299yes2:
300  store i32 1, ptr %p
301  br label %end
302
303no2:
304  %z3 = sub i32 %z2, %b
305  br label %end
306
307end:
308  %z4 = phi i32 [ %z3, %no2 ], [ 3, %yes2 ]
309  ret i32 %z4
310}
311
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,
314; so we must not.
315define i32 @test_diamond_alias3(ptr %p, ptr %q, i32 %a, i32 %b) {
316; CHECK-LABEL: @test_diamond_alias3(
317; CHECK-NEXT:  entry:
318; CHECK-NEXT:    [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
319; CHECK-NEXT:    br i1 [[X1]], label [[NO1:%.*]], label [[YES1:%.*]]
320; CHECK:       yes1:
321; CHECK-NEXT:    store i32 0, ptr [[P:%.*]], align 4
322; CHECK-NEXT:    br label [[FALLTHROUGH:%.*]]
323; CHECK:       no1:
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:%.*]]
330; CHECK:       yes2:
331; CHECK-NEXT:    store i32 1, ptr [[P]], align 4
332; CHECK-NEXT:    br label [[END:%.*]]
333; CHECK:       no2:
334; CHECK-NEXT:    call void @f()
335; CHECK-NEXT:    [[Z3:%.*]] = sub nuw nsw i32 [[Z2]], [[B]]
336; CHECK-NEXT:    br label [[END]]
337; CHECK:       end:
338; CHECK-NEXT:    [[Z4:%.*]] = phi i32 [ [[Z3]], [[NO2]] ], [ 3, [[YES2]] ]
339; CHECK-NEXT:    ret i32 [[Z4]]
340;
341entry:
342  %x1 = icmp eq i32 %a, 0
343  br i1 %x1, label %no1, label %yes1
344
345yes1:
346  store i32 0, ptr %p
347  br label %fallthrough
348
349no1:
350  call void @f()
351  %z1 = add i32 %a, %b
352  br label %fallthrough
353
354fallthrough:
355  %z2 = phi i32 [ %z1, %no1 ], [ 0, %yes1 ]
356  %x2 = icmp eq i32 %b, 0
357  br i1 %x2, label %no2, label %yes2
358
359yes2:
360  store i32 1, ptr %p
361  br label %end
362
363no2:
364  call void @f()
365  %z3 = sub i32 %z2, %b
366  br label %end
367
368end:
369  %z4 = phi i32 [ %z3, %no2 ], [ 3, %yes2 ]
370  ret i32 %z4
371}
372
373; This test has an outer if over the two triangles. This requires creating a new BB to hold the store.
374define void @test_outer_if(ptr %p, i32 %a, i32 %b, i32 %c) {
375; CHECK-LABEL: @test_outer_if(
376; CHECK-NEXT:  entry:
377; CHECK-NEXT:    [[X3:%.*]] = icmp eq i32 [[C:%.*]], 0
378; CHECK-NEXT:    br i1 [[X3]], label [[END:%.*]], label [[CONTINUE:%.*]]
379; CHECK:       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:%.*]]
383; CHECK:       1:
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]]
388; CHECK:       end:
389; CHECK-NEXT:    ret void
390;
391entry:
392  %x3 = icmp eq i32 %c, 0
393  br i1 %x3, label %end, label %continue
394continue:
395  %x1 = icmp eq i32 %a, 0
396  br i1 %x1, label %fallthrough, label %yes1
397yes1:
398  store i32 0, ptr %p
399  br label %fallthrough
400  fallthrough:
401  %x2 = icmp eq i32 %b, 0
402  br i1 %x2, label %end, label %yes2
403yes2:
404  store i32 1, ptr %p
405  br label %end
406end:
407  ret void
408}
409