blob: 77e3158d9bbde0731a0ee738848d093490a0f3c0 [file] [log] [blame]
James Molloy4de84dd2015-11-04 15:28:04 +00001; 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.
Reid Klecknerdb9a91e2015-12-14 22:36:57 +00005; 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 %{{.*}}, %{{.*}}
James Molloy4de84dd2015-11-04 15:28:04 +00009; 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}