1; RUN: opt -simplifycfg -instcombine < %s -simplifycfg-merge-cond-stores=true -simplifycfg-merge-cond-stores-aggressively=false -phi-node-folding-threshold=2 -S | FileCheck %s
2
3; CHECK-LABEL: @test_simple
4; This test should succeed and end up if-converted.
5; CHECK: icmp eq i32 %b, 0
6; CHECK-NEXT: icmp ne i32 %a, 0
7; CHECK-NEXT: xor i1 %x2, true
8; CHECK-NEXT: %[[x:.*]] = or i1 %{{.*}}, %{{.*}}
9; CHECK-NEXT: br i1 %[[x]]
10; CHECK: store
11; CHECK-NOT: store
12; CHECK: ret
13define void @test_simple(i32* %p, i32 %a, i32 %b) {
14entry:
15  %x1 = icmp eq i32 %a, 0
16  br i1 %x1, label %fallthrough, label %yes1
17
18yes1:
19  store i32 0, i32* %p
20  br label %fallthrough
21
22fallthrough:
23  %x2 = icmp eq i32 %b, 0
24  br i1 %x2, label %end, label %yes2
25
26yes2:
27  store i32 1, i32* %p
28  br label %end
29
30end:
31  ret void
32}
33
34; CHECK-LABEL: @test_recursive
35; This test should entirely fold away, leaving one large basic block.
36; CHECK: store
37; CHECK-NOT: store
38; CHECK: ret
39define void @test_recursive(i32* %p, i32 %a, i32 %b, i32 %c, i32 %d) {
40entry:
41  %x1 = icmp eq i32 %a, 0
42  br i1 %x1, label %fallthrough, label %yes1
43
44yes1:
45  store i32 0, i32* %p
46  br label %fallthrough
47
48fallthrough:
49  %x2 = icmp eq i32 %b, 0
50  br i1 %x2, label %next, label %yes2
51
52yes2:
53  store i32 1, i32* %p
54  br label %next
55
56next:
57  %x3 = icmp eq i32 %c, 0
58  br i1 %x3, label %fallthrough2, label %yes3
59
60yes3:
61  store i32 2, i32* %p
62  br label %fallthrough2
63
64fallthrough2:
65  %x4 = icmp eq i32 %d, 0
66  br i1 %x4, label %end, label %yes4
67
68yes4:
69  store i32 3, i32* %p
70  br label %end
71
72
73end:
74  ret void
75}
76
77; CHECK-LABEL: @test_not_ifconverted
78; The code in each diamond is too large - it won't be if-converted so our
79; heuristics should say no.
80; CHECK: store
81; CHECK: store
82; CHECK: ret
83define void @test_not_ifconverted(i32* %p, i32 %a, i32 %b) {
84entry:
85  %x1 = icmp eq i32 %a, 0
86  br i1 %x1, label %fallthrough, label %yes1
87
88yes1:
89  %y1 = or i32 %b, 55
90  %y2 = add i32 %y1, 24
91  %y3 = and i32 %y2, 67
92  store i32 %y3, i32* %p
93  br label %fallthrough
94
95fallthrough:
96  %x2 = icmp eq i32 %b, 0
97  br i1 %x2, label %end, label %yes2
98
99yes2:
100  %z1 = or i32 %a, 55
101  %z2 = add i32 %z1, 24
102  %z3 = and i32 %z2, 67
103  store i32 %z3, i32* %p
104  br label %end
105
106end:
107  ret void
108}
109
110; CHECK-LABEL: @test_aliasing1
111; The store to %p clobbers the previous store, so if-converting this would
112; be illegal.
113; CHECK: store
114; CHECK: store
115; CHECK: ret
116define void @test_aliasing1(i32* %p, i32 %a, i32 %b) {
117entry:
118  %x1 = icmp eq i32 %a, 0
119  br i1 %x1, label %fallthrough, label %yes1
120
121yes1:
122  store i32 0, i32* %p
123  br label %fallthrough
124
125fallthrough:
126  %y1 = load i32, i32* %p
127  %x2 = icmp eq i32 %y1, 0
128  br i1 %x2, label %end, label %yes2
129
130yes2:
131  store i32 1, i32* %p
132  br label %end
133
134end:
135  ret void
136}
137
138; CHECK-LABEL: @test_aliasing2
139; The load from %q aliases with %p, so if-converting this would be illegal.
140; CHECK: store
141; CHECK: store
142; CHECK: ret
143define void @test_aliasing2(i32* %p, i32* %q, i32 %a, i32 %b) {
144entry:
145  %x1 = icmp eq i32 %a, 0
146  br i1 %x1, label %fallthrough, label %yes1
147
148yes1:
149  store i32 0, i32* %p
150  br label %fallthrough
151
152fallthrough:
153  %y1 = load i32, i32* %q
154  %x2 = icmp eq i32 %y1, 0
155  br i1 %x2, label %end, label %yes2
156
157yes2:
158  store i32 1, i32* %p
159  br label %end
160
161end:
162  ret void
163}
164
165declare void @f()
166
167; CHECK-LABEL: @test_diamond_simple
168; This should get if-converted.
169; CHECK: store
170; CHECK-NOT: store
171; CHECK: ret
172define i32 @test_diamond_simple(i32* %p, i32* %q, i32 %a, i32 %b) {
173entry:
174  %x1 = icmp eq i32 %a, 0
175  br i1 %x1, label %no1, label %yes1
176
177yes1:
178  store i32 0, i32* %p
179  br label %fallthrough
180
181no1:
182  %z1 = add i32 %a, %b
183  br label %fallthrough
184
185fallthrough:
186  %z2 = phi i32 [ %z1, %no1 ], [ 0, %yes1 ]
187  %x2 = icmp eq i32 %b, 0
188  br i1 %x2, label %no2, label %yes2
189
190yes2:
191  store i32 1, i32* %p
192  br label %end
193
194no2:
195  %z3 = sub i32 %z2, %b
196  br label %end
197
198end:
199  %z4 = phi i32 [ %z3, %no2 ], [ 3, %yes2 ]
200  ret i32 %z4
201}
202
203; CHECK-LABEL: @test_diamond_alias3
204; Now there is a call to f() in the bottom branch. The store in the first
205; branch would now be reordered with respect to the call if we if-converted,
206; so we must not.
207; CHECK: store
208; CHECK: store
209; CHECK: ret
210define i32 @test_diamond_alias3(i32* %p, i32* %q, i32 %a, i32 %b) {
211entry:
212  %x1 = icmp eq i32 %a, 0
213  br i1 %x1, label %no1, label %yes1
214
215yes1:
216  store i32 0, i32* %p
217  br label %fallthrough
218
219no1:
220  call void @f()
221  %z1 = add i32 %a, %b
222  br label %fallthrough
223
224fallthrough:
225  %z2 = phi i32 [ %z1, %no1 ], [ 0, %yes1 ]
226  %x2 = icmp eq i32 %b, 0
227  br i1 %x2, label %no2, label %yes2
228
229yes2:
230  store i32 1, i32* %p
231  br label %end
232
233no2:
234  call void @f()
235  %z3 = sub i32 %z2, %b
236  br label %end
237
238end:
239  %z4 = phi i32 [ %z3, %no2 ], [ 3, %yes2 ]
240  ret i32 %z4
241}
242