1 ; RUN: opt -S -simplifycfg < %s | FileCheck -check-prefix=CHECK %s
2 ; RUN: opt -S -default-data-layout="p:32:32-p1:16:16" -simplifycfg < %s | FileCheck -check-prefix=CHECK -check-prefix=DL %s
8 define void @test1(i32 %V) {
9 %C1 = icmp eq i32 %V, 4 ; <i1> [#uses=1]
10 %C2 = icmp eq i32 %V, 17 ; <i1> [#uses=1]
11 %CN = or i1 %C1, %C2 ; <i1> [#uses=1]
12 br i1 %CN, label %T, label %F
19 ; CHECK-LABEL: @test1(
20 ; CHECK: switch i32 %V, label %F [
21 ; CHECK: i32 17, label %T
22 ; CHECK: i32 4, label %T
26 define void @test1_ptr(i32* %V) {
27 %C1 = icmp eq i32* %V, inttoptr (i32 4 to i32*)
28 %C2 = icmp eq i32* %V, inttoptr (i32 17 to i32*)
29 %CN = or i1 %C1, %C2 ; <i1> [#uses=1]
30 br i1 %CN, label %T, label %F
37 ; CHECK-LABEL: @test1_ptr(
38 ; DL: %magicptr = ptrtoint i32* %V to i32
39 ; DL: switch i32 %magicptr, label %F [
40 ; DL: i32 17, label %T
45 define void @test1_ptr_as1(i32 addrspace(1)* %V) {
46 %C1 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 4 to i32 addrspace(1)*)
47 %C2 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 17 to i32 addrspace(1)*)
48 %CN = or i1 %C1, %C2 ; <i1> [#uses=1]
49 br i1 %CN, label %T, label %F
56 ; CHECK-LABEL: @test1_ptr_as1(
57 ; DL: %magicptr = ptrtoint i32 addrspace(1)* %V to i16
58 ; DL: switch i16 %magicptr, label %F [
59 ; DL: i16 17, label %T
64 define void @test2(i32 %V) {
65 %C1 = icmp ne i32 %V, 4 ; <i1> [#uses=1]
66 %C2 = icmp ne i32 %V, 17 ; <i1> [#uses=1]
67 %CN = and i1 %C1, %C2 ; <i1> [#uses=1]
68 br i1 %CN, label %T, label %F
75 ; CHECK-LABEL: @test2(
76 ; CHECK: switch i32 %V, label %T [
77 ; CHECK: i32 17, label %F
78 ; CHECK: i32 4, label %F
82 define void @test3(i32 %V) {
83 %C1 = icmp eq i32 %V, 4 ; <i1> [#uses=1]
84 br i1 %C1, label %T, label %N
86 %C2 = icmp eq i32 %V, 17 ; <i1> [#uses=1]
87 br i1 %C2, label %T, label %F
95 ; CHECK-LABEL: @test3(
96 ; CHECK: switch i32 %V, label %F [
97 ; CHECK: i32 4, label %T
98 ; CHECK: i32 17, label %T
104 define i32 @test4(i8 zeroext %c) nounwind ssp noredzone {
106 %cmp = icmp eq i8 %c, 62
107 br i1 %cmp, label %lor.end, label %lor.lhs.false
109 lor.lhs.false: ; preds = %entry
110 %cmp4 = icmp eq i8 %c, 34
111 br i1 %cmp4, label %lor.end, label %lor.rhs
113 lor.rhs: ; preds = %lor.lhs.false
114 %cmp8 = icmp eq i8 %c, 92
117 lor.end: ; preds = %lor.rhs, %lor.lhs.false, %entry
118 %0 = phi i1 [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp8, %lor.rhs ]
119 %lor.ext = zext i1 %0 to i32
122 ; CHECK-LABEL: @test4(
123 ; CHECK: switch i8 %c, label %lor.rhs [
124 ; CHECK: i8 62, label %lor.end
125 ; CHECK: i8 34, label %lor.end
126 ; CHECK: i8 92, label %lor.end
130 define i32 @test5(i8 zeroext %c) nounwind ssp noredzone {
132 switch i8 %c, label %lor.rhs [
133 i8 62, label %lor.end
134 i8 34, label %lor.end
135 i8 92, label %lor.end
138 lor.rhs: ; preds = %entry
139 %V = icmp eq i8 %c, 92
142 lor.end: ; preds = %entry, %entry, %entry, %lor.rhs
143 %0 = phi i1 [ true, %entry ], [ %V, %lor.rhs ], [ true, %entry ], [ true, %entry ]
144 %lor.ext = zext i1 %0 to i32
146 ; CHECK-LABEL: @test5(
147 ; CHECK: switch i8 %c, label %lor.rhs [
148 ; CHECK: i8 62, label %lor.end
149 ; CHECK: i8 34, label %lor.end
150 ; CHECK: i8 92, label %lor.end
155 define i1 @test6({ i32, i32 }* %I) {
157 %tmp.1.i = getelementptr { i32, i32 }, { i32, i32 }* %I, i64 0, i32 1 ; <i32*> [#uses=1]
158 %tmp.2.i = load i32, i32* %tmp.1.i ; <i32> [#uses=6]
159 %tmp.2 = icmp eq i32 %tmp.2.i, 14 ; <i1> [#uses=1]
160 br i1 %tmp.2, label %shortcirc_done.4, label %shortcirc_next.0
161 shortcirc_next.0: ; preds = %entry
162 %tmp.6 = icmp eq i32 %tmp.2.i, 15 ; <i1> [#uses=1]
163 br i1 %tmp.6, label %shortcirc_done.4, label %shortcirc_next.1
164 shortcirc_next.1: ; preds = %shortcirc_next.0
165 %tmp.11 = icmp eq i32 %tmp.2.i, 16 ; <i1> [#uses=1]
166 br i1 %tmp.11, label %shortcirc_done.4, label %shortcirc_next.2
167 shortcirc_next.2: ; preds = %shortcirc_next.1
168 %tmp.16 = icmp eq i32 %tmp.2.i, 17 ; <i1> [#uses=1]
169 br i1 %tmp.16, label %shortcirc_done.4, label %shortcirc_next.3
170 shortcirc_next.3: ; preds = %shortcirc_next.2
171 %tmp.21 = icmp eq i32 %tmp.2.i, 18 ; <i1> [#uses=1]
172 br i1 %tmp.21, label %shortcirc_done.4, label %shortcirc_next.4
173 shortcirc_next.4: ; preds = %shortcirc_next.3
174 %tmp.26 = icmp eq i32 %tmp.2.i, 19 ; <i1> [#uses=1]
175 br label %UnifiedReturnBlock
176 shortcirc_done.4: ; preds = %shortcirc_next.3, %shortcirc_next.2, %shortcirc_next.1, %shortcirc_next.0, %entry
177 br label %UnifiedReturnBlock
178 UnifiedReturnBlock: ; preds = %shortcirc_done.4, %shortcirc_next.4
179 %UnifiedRetVal = phi i1 [ %tmp.26, %shortcirc_next.4 ], [ true, %shortcirc_done.4 ] ; <i1> [#uses=1]
180 ret i1 %UnifiedRetVal
182 ; CHECK-LABEL: @test6(
183 ; CHECK: %tmp.2.i.off = add i32 %tmp.2.i, -14
184 ; CHECK: %switch = icmp ult i32 %tmp.2.i.off, 6
187 define void @test7(i8 zeroext %c, i32 %x) nounwind ssp noredzone {
189 %cmp = icmp ult i32 %x, 32
190 %cmp4 = icmp eq i8 %c, 97
191 %or.cond = or i1 %cmp, %cmp4
192 %cmp9 = icmp eq i8 %c, 99
193 %or.cond11 = or i1 %or.cond, %cmp9
194 br i1 %or.cond11, label %if.then, label %if.end
196 if.then: ; preds = %entry
197 tail call void @foo1() nounwind noredzone
200 if.end: ; preds = %entry
203 ; CHECK-LABEL: @test7(
204 ; CHECK: %cmp = icmp ult i32 %x, 32
205 ; CHECK: br i1 %cmp, label %if.then, label %switch.early.test
206 ; CHECK: switch.early.test:
207 ; CHECK: switch i8 %c, label %if.end [
208 ; CHECK: i8 99, label %if.then
209 ; CHECK: i8 97, label %if.then
213 define i32 @test8(i8 zeroext %c, i32 %x, i1 %C) nounwind ssp noredzone {
215 br i1 %C, label %N, label %if.then
217 %cmp = icmp ult i32 %x, 32
218 %cmp4 = icmp eq i8 %c, 97
219 %or.cond = or i1 %cmp, %cmp4
220 %cmp9 = icmp eq i8 %c, 99
221 %or.cond11 = or i1 %or.cond, %cmp9
222 br i1 %or.cond11, label %if.then, label %if.end
224 if.then: ; preds = %entry
225 %A = phi i32 [0, %entry], [42, %N]
226 tail call void @foo1() nounwind noredzone
229 if.end: ; preds = %entry
232 ; CHECK-LABEL: @test8(
233 ; CHECK: switch.early.test:
234 ; CHECK: switch i8 %c, label %if.end [
235 ; CHECK: i8 99, label %if.then
236 ; CHECK: i8 97, label %if.then
238 ; CHECK: %A = phi i32 [ 0, %entry ], [ 42, %switch.early.test ], [ 42, %N ], [ 42, %switch.early.test ]
241 ;; This is "Example 7" from http://blog.regehr.org/archives/320
242 define i32 @test9(i8 zeroext %c) nounwind ssp noredzone {
244 %cmp = icmp ult i8 %c, 33
245 br i1 %cmp, label %lor.end, label %lor.lhs.false
247 lor.lhs.false: ; preds = %entry
248 %cmp4 = icmp eq i8 %c, 46
249 br i1 %cmp4, label %lor.end, label %lor.lhs.false6
251 lor.lhs.false6: ; preds = %lor.lhs.false
252 %cmp9 = icmp eq i8 %c, 44
253 br i1 %cmp9, label %lor.end, label %lor.lhs.false11
255 lor.lhs.false11: ; preds = %lor.lhs.false6
256 %cmp14 = icmp eq i8 %c, 58
257 br i1 %cmp14, label %lor.end, label %lor.lhs.false16
259 lor.lhs.false16: ; preds = %lor.lhs.false11
260 %cmp19 = icmp eq i8 %c, 59
261 br i1 %cmp19, label %lor.end, label %lor.lhs.false21
263 lor.lhs.false21: ; preds = %lor.lhs.false16
264 %cmp24 = icmp eq i8 %c, 60
265 br i1 %cmp24, label %lor.end, label %lor.lhs.false26
267 lor.lhs.false26: ; preds = %lor.lhs.false21
268 %cmp29 = icmp eq i8 %c, 62
269 br i1 %cmp29, label %lor.end, label %lor.lhs.false31
271 lor.lhs.false31: ; preds = %lor.lhs.false26
272 %cmp34 = icmp eq i8 %c, 34
273 br i1 %cmp34, label %lor.end, label %lor.lhs.false36
275 lor.lhs.false36: ; preds = %lor.lhs.false31
276 %cmp39 = icmp eq i8 %c, 92
277 br i1 %cmp39, label %lor.end, label %lor.rhs
279 lor.rhs: ; preds = %lor.lhs.false36
280 %cmp43 = icmp eq i8 %c, 39
283 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
284 %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 ]
285 %conv46 = zext i1 %0 to i32
288 ; CHECK-LABEL: @test9(
289 ; CHECK: %cmp = icmp ult i8 %c, 33
290 ; CHECK: br i1 %cmp, label %lor.end, label %switch.early.test
292 ; CHECK: switch.early.test:
293 ; CHECK: switch i8 %c, label %lor.rhs [
294 ; CHECK: i8 92, label %lor.end
295 ; CHECK: i8 62, label %lor.end
296 ; CHECK: i8 60, label %lor.end
297 ; CHECK: i8 59, label %lor.end
298 ; CHECK: i8 58, label %lor.end
299 ; CHECK: i8 46, label %lor.end
300 ; CHECK: i8 44, label %lor.end
301 ; CHECK: i8 34, label %lor.end
302 ; CHECK: i8 39, label %lor.end
306 define i32 @test10(i32 %mode, i1 %Cond) {
307 %A = icmp ne i32 %mode, 0
308 %B = icmp ne i32 %mode, 51
310 %D = and i1 %C, %Cond
311 br i1 %D, label %T, label %F
317 ; CHECK-LABEL: @test10(
318 ; CHECK: br i1 %Cond, label %switch.early.test, label %F
319 ; CHECK:switch.early.test:
320 ; CHECK: switch i32 %mode, label %T [
321 ; CHECK: i32 51, label %F
322 ; CHECK: i32 0, label %F
327 define i32 @test11(i32 %bar) nounwind {
329 %cmp = icmp eq i32 %bar, 4
330 %cmp2 = icmp eq i32 %bar, 35
331 %or.cond = or i1 %cmp, %cmp2
332 %cmp5 = icmp eq i32 %bar, 53
333 %or.cond1 = or i1 %or.cond, %cmp5
334 %cmp8 = icmp eq i32 %bar, 24
335 %or.cond2 = or i1 %or.cond1, %cmp8
336 %cmp11 = icmp eq i32 %bar, 23
337 %or.cond3 = or i1 %or.cond2, %cmp11
338 %cmp14 = icmp eq i32 %bar, 55
339 %or.cond4 = or i1 %or.cond3, %cmp14
340 %cmp17 = icmp eq i32 %bar, 12
341 %or.cond5 = or i1 %or.cond4, %cmp17
342 %cmp20 = icmp eq i32 %bar, 35
343 %or.cond6 = or i1 %or.cond5, %cmp20
344 br i1 %or.cond6, label %if.then, label %if.end
346 if.then: ; preds = %entry
349 if.end: ; preds = %entry
352 return: ; preds = %if.end, %if.then
353 %retval.0 = phi i32 [ 1, %if.then ], [ 0, %if.end ]
356 ; CHECK-LABEL: @test11(
357 ; CHECK: switch i32 %bar, label %if.end [
358 ; CHECK: i32 55, label %return
359 ; CHECK: i32 53, label %return
360 ; CHECK: i32 35, label %return
361 ; CHECK: i32 24, label %return
362 ; CHECK: i32 23, label %return
363 ; CHECK: i32 12, label %return
364 ; CHECK: i32 4, label %return
368 define void @test12() nounwind {
373 %A = icmp eq i32 undef, undef
374 br i1 %A, label %bb55.us.us, label %malformed
377 %B = icmp ugt i32 undef, undef
378 br i1 %B, label %bb55.us.us, label %bb49.us.us
385 ; CHECK-LABEL: @test12(
389 ; test13 - handle switch formation with ult.
390 define void @test13(i32 %x) nounwind ssp noredzone {
392 %cmp = icmp ult i32 %x, 2
393 br i1 %cmp, label %if.then, label %lor.lhs.false3
395 lor.lhs.false3: ; preds = %lor.lhs.false
396 %cmp5 = icmp eq i32 %x, 3
397 br i1 %cmp5, label %if.then, label %lor.lhs.false6
399 lor.lhs.false6: ; preds = %lor.lhs.false3
400 %cmp8 = icmp eq i32 %x, 4
401 br i1 %cmp8, label %if.then, label %lor.lhs.false9
403 lor.lhs.false9: ; preds = %lor.lhs.false6
404 %cmp11 = icmp eq i32 %x, 6
405 br i1 %cmp11, label %if.then, label %if.end
407 if.then: ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
408 call void @foo1() noredzone
411 if.end: ; preds = %if.then, %lor.lhs.false9
413 ; CHECK-LABEL: @test13(
414 ; CHECK: switch i32 %x, label %if.end [
415 ; CHECK: i32 6, label %if.then
416 ; CHECK: i32 4, label %if.then
417 ; CHECK: i32 3, label %if.then
418 ; CHECK: i32 1, label %if.then
419 ; CHECK: i32 0, label %if.then
423 ; test14 - handle switch formation with ult.
424 define void @test14(i32 %x) nounwind ssp noredzone {
426 %cmp = icmp ugt i32 %x, 2
427 br i1 %cmp, label %lor.lhs.false3, label %if.then
429 lor.lhs.false3: ; preds = %lor.lhs.false
430 %cmp5 = icmp ne i32 %x, 3
431 br i1 %cmp5, label %lor.lhs.false6, label %if.then
433 lor.lhs.false6: ; preds = %lor.lhs.false3
434 %cmp8 = icmp ne i32 %x, 4
435 br i1 %cmp8, label %lor.lhs.false9, label %if.then
437 lor.lhs.false9: ; preds = %lor.lhs.false6
438 %cmp11 = icmp ne i32 %x, 6
439 br i1 %cmp11, label %if.end, label %if.then
441 if.then: ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
442 call void @foo1() noredzone
445 if.end: ; preds = %if.then, %lor.lhs.false9
447 ; CHECK-LABEL: @test14(
448 ; CHECK: switch i32 %x, label %if.end [
449 ; CHECK: i32 6, label %if.then
450 ; CHECK: i32 4, label %if.then
451 ; CHECK: i32 3, label %if.then
452 ; CHECK: i32 1, label %if.then
453 ; CHECK: i32 0, label %if.then
457 ; Don't crash on ginormous ranges.
458 define void @test15(i128 %x) nounwind {
459 %cmp = icmp ugt i128 %x, 2
460 br i1 %cmp, label %if.end, label %lor.false
463 %cmp2 = icmp ne i128 %x, 100000000000000000000
464 br i1 %cmp2, label %if.end, label %if.then
467 call void @foo1() noredzone
473 ; CHECK-LABEL: @test15(
480 define zeroext i1 @test16(i32 %x) nounwind {
482 ; CHECK-LABEL: @test16(
483 ; CHECK: %x.off = add i32 %x, -1
484 ; CHECK: %switch = icmp ult i32 %x.off, 3
485 %cmp.i = icmp eq i32 %x, 1
486 br i1 %cmp.i, label %lor.end, label %lor.lhs.false
489 %cmp.i2 = icmp eq i32 %x, 2
490 br i1 %cmp.i2, label %lor.end, label %lor.rhs
493 %cmp.i1 = icmp eq i32 %x, 3
497 %0 = phi i1 [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp.i1, %lor.rhs ]
501 ; Check that we don't turn an icmp into a switch where it's not useful.
502 define void @test17(i32 %x, i32 %y) {
503 %cmp = icmp ult i32 %x, 3
504 %switch = icmp ult i32 %y, 2
505 %or.cond775 = or i1 %cmp, %switch
506 br i1 %or.cond775, label %lor.lhs.false8, label %return
509 tail call void @foo1()
515 ; CHECK-LABEL: @test17(
516 ; CHECK-NOT: switch.early.test
517 ; CHECK-NOT: switch i32
521 define void @test18(i32 %arg) {
523 %tmp = and i32 %arg, -2
524 %tmp1 = icmp eq i32 %tmp, 8
525 %tmp2 = icmp eq i32 %arg, 10
526 %tmp3 = or i1 %tmp1, %tmp2
527 %tmp4 = icmp eq i32 %arg, 11
528 %tmp5 = or i1 %tmp3, %tmp4
529 %tmp6 = icmp eq i32 %arg, 12
530 %tmp7 = or i1 %tmp5, %tmp6
531 br i1 %tmp7, label %bb19, label %bb8
534 %tmp9 = add i32 %arg, -13
535 %tmp10 = icmp ult i32 %tmp9, 2
536 %tmp11 = icmp eq i32 %arg, 16
537 %tmp12 = or i1 %tmp10, %tmp11
538 %tmp13 = icmp eq i32 %arg, 17
539 %tmp14 = or i1 %tmp12, %tmp13
540 %tmp15 = icmp eq i32 %arg, 18
541 %tmp16 = or i1 %tmp14, %tmp15
542 %tmp17 = icmp eq i32 %arg, 15
543 %tmp18 = or i1 %tmp16, %tmp17
544 br i1 %tmp18, label %bb19, label %bb20
546 bb19: ; preds = %bb8, %bb
547 tail call void @foo1()
550 bb20: ; preds = %bb19, %bb8
553 ; CHECK-LABEL: @test18(
554 ; CHECK: %arg.off = add i32 %arg, -8
555 ; CHECK: icmp ult i32 %arg.off, 11