1 ; RUN: opt < %s -simplifycfg -S | FileCheck %s
7 define void @test1(i32 %V) {
8 %C1 = icmp eq i32 %V, 4 ; <i1> [#uses=1]
9 %C2 = icmp eq i32 %V, 17 ; <i1> [#uses=1]
10 %CN = or i1 %C1, %C2 ; <i1> [#uses=1]
11 br i1 %CN, label %T, label %F
19 ; CHECK: switch i32 %V, label %F [
20 ; CHECK: i32 17, label %T
21 ; CHECK: i32 4, label %T
25 define void @test2(i32 %V) {
26 %C1 = icmp ne i32 %V, 4 ; <i1> [#uses=1]
27 %C2 = icmp ne i32 %V, 17 ; <i1> [#uses=1]
28 %CN = and i1 %C1, %C2 ; <i1> [#uses=1]
29 br i1 %CN, label %T, label %F
37 ; CHECK: switch i32 %V, label %T [
38 ; CHECK: i32 17, label %F
39 ; CHECK: i32 4, label %F
43 define void @test3(i32 %V) {
44 %C1 = icmp eq i32 %V, 4 ; <i1> [#uses=1]
45 br i1 %C1, label %T, label %N
47 %C2 = icmp eq i32 %V, 17 ; <i1> [#uses=1]
48 br i1 %C2, label %T, label %F
57 ; CHECK: switch i32 %V, label %F [
58 ; CHECK: i32 4, label %T
59 ; CHECK: i32 17, label %T
65 define i32 @test4(i8 zeroext %c) nounwind ssp noredzone {
67 %cmp = icmp eq i8 %c, 62
68 br i1 %cmp, label %lor.end, label %lor.lhs.false
70 lor.lhs.false: ; preds = %entry
71 %cmp4 = icmp eq i8 %c, 34
72 br i1 %cmp4, label %lor.end, label %lor.rhs
74 lor.rhs: ; preds = %lor.lhs.false
75 %cmp8 = icmp eq i8 %c, 92
78 lor.end: ; preds = %lor.rhs, %lor.lhs.false, %entry
79 %0 = phi i1 [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp8, %lor.rhs ]
80 %lor.ext = zext i1 %0 to i32
84 ; CHECK: switch i8 %c, label %lor.rhs [
85 ; CHECK: i8 62, label %lor.end
86 ; CHECK: i8 34, label %lor.end
87 ; CHECK: i8 92, label %lor.end
91 define i32 @test5(i8 zeroext %c) nounwind ssp noredzone {
93 switch i8 %c, label %lor.rhs [
99 lor.rhs: ; preds = %entry
100 %V = icmp eq i8 %c, 92
103 lor.end: ; preds = %entry, %entry, %entry, %lor.rhs
104 %0 = phi i1 [ true, %entry ], [ %V, %lor.rhs ], [ true, %entry ], [ true, %entry ]
105 %lor.ext = zext i1 %0 to i32
108 ; CHECK: switch i8 %c, label %lor.rhs [
109 ; CHECK: i8 62, label %lor.end
110 ; CHECK: i8 34, label %lor.end
111 ; CHECK: i8 92, label %lor.end
116 define i1 @test6({ i32, i32 }* %I) {
118 %tmp.1.i = getelementptr { i32, i32 }* %I, i64 0, i32 1 ; <i32*> [#uses=1]
119 %tmp.2.i = load i32* %tmp.1.i ; <i32> [#uses=6]
120 %tmp.2 = icmp eq i32 %tmp.2.i, 14 ; <i1> [#uses=1]
121 br i1 %tmp.2, label %shortcirc_done.4, label %shortcirc_next.0
122 shortcirc_next.0: ; preds = %entry
123 %tmp.6 = icmp eq i32 %tmp.2.i, 15 ; <i1> [#uses=1]
124 br i1 %tmp.6, label %shortcirc_done.4, label %shortcirc_next.1
125 shortcirc_next.1: ; preds = %shortcirc_next.0
126 %tmp.11 = icmp eq i32 %tmp.2.i, 16 ; <i1> [#uses=1]
127 br i1 %tmp.11, label %shortcirc_done.4, label %shortcirc_next.2
128 shortcirc_next.2: ; preds = %shortcirc_next.1
129 %tmp.16 = icmp eq i32 %tmp.2.i, 17 ; <i1> [#uses=1]
130 br i1 %tmp.16, label %shortcirc_done.4, label %shortcirc_next.3
131 shortcirc_next.3: ; preds = %shortcirc_next.2
132 %tmp.21 = icmp eq i32 %tmp.2.i, 18 ; <i1> [#uses=1]
133 br i1 %tmp.21, label %shortcirc_done.4, label %shortcirc_next.4
134 shortcirc_next.4: ; preds = %shortcirc_next.3
135 %tmp.26 = icmp eq i32 %tmp.2.i, 19 ; <i1> [#uses=1]
136 br label %UnifiedReturnBlock
137 shortcirc_done.4: ; preds = %shortcirc_next.3, %shortcirc_next.2, %shortcirc_next.1, %shortcirc_next.0, %entry
138 br label %UnifiedReturnBlock
139 UnifiedReturnBlock: ; preds = %shortcirc_done.4, %shortcirc_next.4
140 %UnifiedRetVal = phi i1 [ %tmp.26, %shortcirc_next.4 ], [ true, %shortcirc_done.4 ] ; <i1> [#uses=1]
141 ret i1 %UnifiedRetVal
144 ; CHECK: %switch.tableidx = sub i32 %tmp.2.i, 14
145 ; CHECK: %0 = icmp ult i32 %switch.tableidx, 6
146 ; CHECK: select i1 %0, i1 true, i1 false
149 define void @test7(i8 zeroext %c, i32 %x) nounwind ssp noredzone {
151 %cmp = icmp ult i32 %x, 32
152 %cmp4 = icmp eq i8 %c, 97
153 %or.cond = or i1 %cmp, %cmp4
154 %cmp9 = icmp eq i8 %c, 99
155 %or.cond11 = or i1 %or.cond, %cmp9
156 br i1 %or.cond11, label %if.then, label %if.end
158 if.then: ; preds = %entry
159 tail call void @foo1() nounwind noredzone
162 if.end: ; preds = %entry
166 ; CHECK: %cmp = icmp ult i32 %x, 32
167 ; CHECK: br i1 %cmp, label %if.then, label %switch.early.test
168 ; CHECK: switch.early.test:
169 ; CHECK: switch i8 %c, label %if.end [
170 ; CHECK: i8 99, label %if.then
171 ; CHECK: i8 97, label %if.then
175 define i32 @test8(i8 zeroext %c, i32 %x, i1 %C) nounwind ssp noredzone {
177 br i1 %C, label %N, label %if.then
179 %cmp = icmp ult i32 %x, 32
180 %cmp4 = icmp eq i8 %c, 97
181 %or.cond = or i1 %cmp, %cmp4
182 %cmp9 = icmp eq i8 %c, 99
183 %or.cond11 = or i1 %or.cond, %cmp9
184 br i1 %or.cond11, label %if.then, label %if.end
186 if.then: ; preds = %entry
187 %A = phi i32 [0, %entry], [42, %N]
188 tail call void @foo1() nounwind noredzone
191 if.end: ; preds = %entry
195 ; CHECK: switch.early.test:
196 ; CHECK: switch i8 %c, label %if.end [
197 ; CHECK: i8 99, label %if.then
198 ; CHECK: i8 97, label %if.then
200 ; CHECK: %A = phi i32 [ 0, %entry ], [ 42, %switch.early.test ], [ 42, %N ], [ 42, %switch.early.test ]
203 ;; This is "Example 7" from http://blog.regehr.org/archives/320
204 define i32 @test9(i8 zeroext %c) nounwind ssp noredzone {
206 %cmp = icmp ult i8 %c, 33
207 br i1 %cmp, label %lor.end, label %lor.lhs.false
209 lor.lhs.false: ; preds = %entry
210 %cmp4 = icmp eq i8 %c, 46
211 br i1 %cmp4, label %lor.end, label %lor.lhs.false6
213 lor.lhs.false6: ; preds = %lor.lhs.false
214 %cmp9 = icmp eq i8 %c, 44
215 br i1 %cmp9, label %lor.end, label %lor.lhs.false11
217 lor.lhs.false11: ; preds = %lor.lhs.false6
218 %cmp14 = icmp eq i8 %c, 58
219 br i1 %cmp14, label %lor.end, label %lor.lhs.false16
221 lor.lhs.false16: ; preds = %lor.lhs.false11
222 %cmp19 = icmp eq i8 %c, 59
223 br i1 %cmp19, label %lor.end, label %lor.lhs.false21
225 lor.lhs.false21: ; preds = %lor.lhs.false16
226 %cmp24 = icmp eq i8 %c, 60
227 br i1 %cmp24, label %lor.end, label %lor.lhs.false26
229 lor.lhs.false26: ; preds = %lor.lhs.false21
230 %cmp29 = icmp eq i8 %c, 62
231 br i1 %cmp29, label %lor.end, label %lor.lhs.false31
233 lor.lhs.false31: ; preds = %lor.lhs.false26
234 %cmp34 = icmp eq i8 %c, 34
235 br i1 %cmp34, label %lor.end, label %lor.lhs.false36
237 lor.lhs.false36: ; preds = %lor.lhs.false31
238 %cmp39 = icmp eq i8 %c, 92
239 br i1 %cmp39, label %lor.end, label %lor.rhs
241 lor.rhs: ; preds = %lor.lhs.false36
242 %cmp43 = icmp eq i8 %c, 39
245 lor.end: ; preds = %lor.rhs, %lor.lhs.false36, %lor.lhs.false31, %lor.lhs.false26, %lor.lhs.false21, %lor.lhs.false16, %lor.lhs.false11, %lor.lhs.false6, %lor.lhs.false, %entry
246 %0 = phi i1 [ true, %lor.lhs.false36 ], [ true, %lor.lhs.false31 ], [ true, %lor.lhs.false26 ], [ true, %lor.lhs.false21 ], [ true, %lor.lhs.false16 ], [ true, %lor.lhs.false11 ], [ true, %lor.lhs.false6 ], [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp43, %lor.rhs ]
247 %conv46 = zext i1 %0 to i32
251 ; CHECK: %cmp = icmp ult i8 %c, 33
252 ; CHECK: br i1 %cmp, label %lor.end, label %switch.early.test
254 ; CHECK: switch.early.test:
255 ; CHECK: switch i8 %c, label %lor.rhs [
256 ; CHECK: i8 92, label %lor.end
257 ; CHECK: i8 62, label %lor.end
258 ; CHECK: i8 60, label %lor.end
259 ; CHECK: i8 59, label %lor.end
260 ; CHECK: i8 58, label %lor.end
261 ; CHECK: i8 46, label %lor.end
262 ; CHECK: i8 44, label %lor.end
263 ; CHECK: i8 34, label %lor.end
264 ; CHECK: i8 39, label %lor.end
268 define i32 @test10(i32 %mode, i1 %Cond) {
269 %A = icmp ne i32 %mode, 0
270 %B = icmp ne i32 %mode, 51
272 %D = and i1 %C, %Cond
273 br i1 %D, label %T, label %F
280 ; CHECK: br i1 %Cond, label %switch.early.test, label %F
281 ; CHECK:switch.early.test:
282 ; CHECK: switch i32 %mode, label %T [
283 ; CHECK: i32 51, label %F
284 ; CHECK: i32 0, label %F
289 define i32 @test11(i32 %bar) nounwind {
291 %cmp = icmp eq i32 %bar, 4
292 %cmp2 = icmp eq i32 %bar, 35
293 %or.cond = or i1 %cmp, %cmp2
294 %cmp5 = icmp eq i32 %bar, 53
295 %or.cond1 = or i1 %or.cond, %cmp5
296 %cmp8 = icmp eq i32 %bar, 24
297 %or.cond2 = or i1 %or.cond1, %cmp8
298 %cmp11 = icmp eq i32 %bar, 23
299 %or.cond3 = or i1 %or.cond2, %cmp11
300 %cmp14 = icmp eq i32 %bar, 55
301 %or.cond4 = or i1 %or.cond3, %cmp14
302 %cmp17 = icmp eq i32 %bar, 12
303 %or.cond5 = or i1 %or.cond4, %cmp17
304 %cmp20 = icmp eq i32 %bar, 35
305 %or.cond6 = or i1 %or.cond5, %cmp20
306 br i1 %or.cond6, label %if.then, label %if.end
308 if.then: ; preds = %entry
311 if.end: ; preds = %entry
314 return: ; preds = %if.end, %if.then
315 %retval.0 = phi i32 [ 1, %if.then ], [ 0, %if.end ]
319 ; CHECK: switch i32 %bar, label %if.end [
320 ; CHECK: i32 55, label %return
321 ; CHECK: i32 53, label %return
322 ; CHECK: i32 35, label %return
323 ; CHECK: i32 24, label %return
324 ; CHECK: i32 23, label %return
325 ; CHECK: i32 12, label %return
326 ; CHECK: i32 4, label %return
330 define void @test12() nounwind {
335 %A = icmp eq i32 undef, undef
336 br i1 %A, label %bb55.us.us, label %malformed
339 %B = icmp ugt i32 undef, undef
340 br i1 %B, label %bb55.us.us, label %bb49.us.us
351 ; test13 - handle switch formation with ult.
352 define void @test13(i32 %x) nounwind ssp noredzone {
354 %cmp = icmp ult i32 %x, 2
355 br i1 %cmp, label %if.then, label %lor.lhs.false3
357 lor.lhs.false3: ; preds = %lor.lhs.false
358 %cmp5 = icmp eq i32 %x, 3
359 br i1 %cmp5, label %if.then, label %lor.lhs.false6
361 lor.lhs.false6: ; preds = %lor.lhs.false3
362 %cmp8 = icmp eq i32 %x, 4
363 br i1 %cmp8, label %if.then, label %lor.lhs.false9
365 lor.lhs.false9: ; preds = %lor.lhs.false6
366 %cmp11 = icmp eq i32 %x, 6
367 br i1 %cmp11, label %if.then, label %if.end
369 if.then: ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
370 call void @foo1() noredzone
373 if.end: ; preds = %if.then, %lor.lhs.false9
376 ; CHECK: switch i32 %x, label %if.end [
377 ; CHECK: i32 6, label %if.then
378 ; CHECK: i32 4, label %if.then
379 ; CHECK: i32 3, label %if.then
380 ; CHECK: i32 1, label %if.then
381 ; CHECK: i32 0, label %if.then
385 ; test14 - handle switch formation with ult.
386 define void @test14(i32 %x) nounwind ssp noredzone {
388 %cmp = icmp ugt i32 %x, 2
389 br i1 %cmp, label %lor.lhs.false3, label %if.then
391 lor.lhs.false3: ; preds = %lor.lhs.false
392 %cmp5 = icmp ne i32 %x, 3
393 br i1 %cmp5, label %lor.lhs.false6, label %if.then
395 lor.lhs.false6: ; preds = %lor.lhs.false3
396 %cmp8 = icmp ne i32 %x, 4
397 br i1 %cmp8, label %lor.lhs.false9, label %if.then
399 lor.lhs.false9: ; preds = %lor.lhs.false6
400 %cmp11 = icmp ne i32 %x, 6
401 br i1 %cmp11, label %if.end, label %if.then
403 if.then: ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
404 call void @foo1() noredzone
407 if.end: ; preds = %if.then, %lor.lhs.false9
410 ; CHECK: switch i32 %x, label %if.end [
411 ; CHECK: i32 6, label %if.then
412 ; CHECK: i32 4, label %if.then
413 ; CHECK: i32 3, label %if.then
414 ; CHECK: i32 1, label %if.then
415 ; CHECK: i32 0, label %if.then
419 ; Don't crash on ginormous ranges.
420 define void @test15(i128 %x) nounwind {
421 %cmp = icmp ugt i128 %x, 2
422 br i1 %cmp, label %if.end, label %lor.false
425 %cmp2 = icmp ne i128 %x, 100000000000000000000
426 br i1 %cmp2, label %if.end, label %if.then
429 call void @foo1() noredzone
442 define zeroext i1 @test16(i32 %x) nounwind {
445 ; CHECK: %x.off = add i32 %x, -1
446 ; CHECK: %switch = icmp ult i32 %x.off, 3
447 %cmp.i = icmp eq i32 %x, 1
448 br i1 %cmp.i, label %lor.end, label %lor.lhs.false
451 %cmp.i2 = icmp eq i32 %x, 2
452 br i1 %cmp.i2, label %lor.end, label %lor.rhs
455 %cmp.i1 = icmp eq i32 %x, 3
459 %0 = phi i1 [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp.i1, %lor.rhs ]
463 ; Check that we don't turn an icmp into a switch where it's not useful.
464 define void @test17(i32 %x, i32 %y) {
465 %cmp = icmp ult i32 %x, 3
466 %switch = icmp ult i32 %y, 2
467 %or.cond775 = or i1 %cmp, %switch
468 br i1 %or.cond775, label %lor.lhs.false8, label %return
471 tail call void @foo1()
478 ; CHECK-NOT: switch.early.test
479 ; CHECK-NOT: switch i32