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=DL %s
3
4; TODO: Other tests should also have check lines with datalayout
5
6declare void @foo1()
7
8declare void @foo2()
9
10define void @test1(i32 %V) {
11        %C1 = icmp eq i32 %V, 4         ; <i1> [#uses=1]
12        %C2 = icmp eq i32 %V, 17                ; <i1> [#uses=1]
13        %CN = or i1 %C1, %C2            ; <i1> [#uses=1]
14        br i1 %CN, label %T, label %F
15T:              ; preds = %0
16        call void @foo1( )
17        ret void
18F:              ; preds = %0
19        call void @foo2( )
20        ret void
21; CHECK-LABEL: @test1(
22; CHECK:  switch i32 %V, label %F [
23; CHECK:    i32 17, label %T
24; CHECK:    i32 4, label %T
25; CHECK:  ]
26}
27
28define void @test1_ptr(i32* %V) {
29        %C1 = icmp eq i32* %V, inttoptr (i32 4 to i32*)
30        %C2 = icmp eq i32* %V, inttoptr (i32 17 to i32*)
31        %CN = or i1 %C1, %C2            ; <i1> [#uses=1]
32        br i1 %CN, label %T, label %F
33T:              ; preds = %0
34        call void @foo1( )
35        ret void
36F:              ; preds = %0
37        call void @foo2( )
38        ret void
39; DL-LABEL: @test1_ptr(
40; DL:  %magicptr = ptrtoint i32* %V to i32
41; DL:  switch i32 %magicptr, label %F [
42; DL:    i32 17, label %T
43; DL:    i32 4, label %T
44; DL:  ]
45}
46
47define void @test1_ptr_as1(i32 addrspace(1)* %V) {
48        %C1 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 4 to i32 addrspace(1)*)
49        %C2 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 17 to i32 addrspace(1)*)
50        %CN = or i1 %C1, %C2            ; <i1> [#uses=1]
51        br i1 %CN, label %T, label %F
52T:              ; preds = %0
53        call void @foo1( )
54        ret void
55F:              ; preds = %0
56        call void @foo2( )
57        ret void
58; DL-LABEL: @test1_ptr_as1(
59; DL:  %magicptr = ptrtoint i32 addrspace(1)* %V to i16
60; DL:  switch i16 %magicptr, label %F [
61; DL:    i16 17, label %T
62; DL:    i16 4, label %T
63; DL:  ]
64}
65
66define void @test2(i32 %V) {
67        %C1 = icmp ne i32 %V, 4         ; <i1> [#uses=1]
68        %C2 = icmp ne i32 %V, 17                ; <i1> [#uses=1]
69        %CN = and i1 %C1, %C2           ; <i1> [#uses=1]
70        br i1 %CN, label %T, label %F
71T:              ; preds = %0
72        call void @foo1( )
73        ret void
74F:              ; preds = %0
75        call void @foo2( )
76        ret void
77; CHECK-LABEL: @test2(
78; CHECK:  switch i32 %V, label %T [
79; CHECK:    i32 17, label %F
80; CHECK:    i32 4, label %F
81; CHECK:  ]
82}
83
84define void @test3(i32 %V) {
85        %C1 = icmp eq i32 %V, 4         ; <i1> [#uses=1]
86        br i1 %C1, label %T, label %N
87N:              ; preds = %0
88        %C2 = icmp eq i32 %V, 17                ; <i1> [#uses=1]
89        br i1 %C2, label %T, label %F
90T:              ; preds = %N, %0
91        call void @foo1( )
92        ret void
93F:              ; preds = %N
94        call void @foo2( )
95        ret void
96
97; CHECK-LABEL: @test3(
98; CHECK: switch i32 %V, label %F [
99; CHECK:     i32 4, label %T
100; CHECK:     i32 17, label %T
101; CHECK:   ]
102}
103
104
105
106define i32 @test4(i8 zeroext %c) nounwind ssp noredzone {
107entry:
108  %cmp = icmp eq i8 %c, 62
109  br i1 %cmp, label %lor.end, label %lor.lhs.false
110
111lor.lhs.false:                                    ; preds = %entry
112  %cmp4 = icmp eq i8 %c, 34
113  br i1 %cmp4, label %lor.end, label %lor.rhs
114
115lor.rhs:                                          ; preds = %lor.lhs.false
116  %cmp8 = icmp eq i8 %c, 92
117  br label %lor.end
118
119lor.end:                                          ; preds = %lor.rhs, %lor.lhs.false, %entry
120  %0 = phi i1 [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp8, %lor.rhs ]
121  %lor.ext = zext i1 %0 to i32
122  ret i32 %lor.ext
123
124; CHECK-LABEL: @test4(
125; CHECK:  switch i8 %c, label %lor.rhs [
126; CHECK:    i8 62, label %lor.end
127; CHECK:    i8 34, label %lor.end
128; CHECK:    i8 92, label %lor.end
129; CHECK:  ]
130}
131
132define i32 @test5(i8 zeroext %c) nounwind ssp noredzone {
133entry:
134  switch i8 %c, label %lor.rhs [
135    i8 62, label %lor.end
136    i8 34, label %lor.end
137    i8 92, label %lor.end
138  ]
139
140lor.rhs:                                          ; preds = %entry
141  %V = icmp eq i8 %c, 92
142  br label %lor.end
143
144lor.end:                                          ; preds = %entry, %entry, %entry, %lor.rhs
145  %0 = phi i1 [ true, %entry ], [ %V, %lor.rhs ], [ true, %entry ], [ true, %entry ]
146  %lor.ext = zext i1 %0 to i32
147  ret i32 %lor.ext
148; CHECK-LABEL: @test5(
149; CHECK:  switch i8 %c, label %lor.rhs [
150; CHECK:    i8 62, label %lor.end
151; CHECK:    i8 34, label %lor.end
152; CHECK:    i8 92, label %lor.end
153; CHECK:  ]
154}
155
156
157define i1 @test6({ i32, i32 }* %I) {
158entry:
159        %tmp.1.i = getelementptr { i32, i32 }* %I, i64 0, i32 1         ; <i32*> [#uses=1]
160        %tmp.2.i = load i32* %tmp.1.i           ; <i32> [#uses=6]
161        %tmp.2 = icmp eq i32 %tmp.2.i, 14               ; <i1> [#uses=1]
162        br i1 %tmp.2, label %shortcirc_done.4, label %shortcirc_next.0
163shortcirc_next.0:               ; preds = %entry
164        %tmp.6 = icmp eq i32 %tmp.2.i, 15               ; <i1> [#uses=1]
165        br i1 %tmp.6, label %shortcirc_done.4, label %shortcirc_next.1
166shortcirc_next.1:               ; preds = %shortcirc_next.0
167        %tmp.11 = icmp eq i32 %tmp.2.i, 16              ; <i1> [#uses=1]
168        br i1 %tmp.11, label %shortcirc_done.4, label %shortcirc_next.2
169shortcirc_next.2:               ; preds = %shortcirc_next.1
170        %tmp.16 = icmp eq i32 %tmp.2.i, 17              ; <i1> [#uses=1]
171        br i1 %tmp.16, label %shortcirc_done.4, label %shortcirc_next.3
172shortcirc_next.3:               ; preds = %shortcirc_next.2
173        %tmp.21 = icmp eq i32 %tmp.2.i, 18              ; <i1> [#uses=1]
174        br i1 %tmp.21, label %shortcirc_done.4, label %shortcirc_next.4
175shortcirc_next.4:               ; preds = %shortcirc_next.3
176        %tmp.26 = icmp eq i32 %tmp.2.i, 19              ; <i1> [#uses=1]
177        br label %UnifiedReturnBlock
178shortcirc_done.4:               ; preds = %shortcirc_next.3, %shortcirc_next.2, %shortcirc_next.1, %shortcirc_next.0, %entry
179        br label %UnifiedReturnBlock
180UnifiedReturnBlock:             ; preds = %shortcirc_done.4, %shortcirc_next.4
181        %UnifiedRetVal = phi i1 [ %tmp.26, %shortcirc_next.4 ], [ true, %shortcirc_done.4 ]             ; <i1> [#uses=1]
182        ret i1 %UnifiedRetVal
183
184; CHECK-LABEL: @test6(
185; CHECK: %tmp.2.i.off = add i32 %tmp.2.i, -14
186; CHECK: %switch = icmp ult i32 %tmp.2.i.off, 6
187}
188
189define void @test7(i8 zeroext %c, i32 %x) nounwind ssp noredzone {
190entry:
191  %cmp = icmp ult i32 %x, 32
192  %cmp4 = icmp eq i8 %c, 97
193  %or.cond = or i1 %cmp, %cmp4
194  %cmp9 = icmp eq i8 %c, 99
195  %or.cond11 = or i1 %or.cond, %cmp9
196  br i1 %or.cond11, label %if.then, label %if.end
197
198if.then:                                          ; preds = %entry
199  tail call void @foo1() nounwind noredzone
200  ret void
201
202if.end:                                           ; preds = %entry
203  ret void
204
205; CHECK-LABEL: @test7(
206; CHECK:   %cmp = icmp ult i32 %x, 32
207; CHECK:   br i1 %cmp, label %if.then, label %switch.early.test
208; CHECK: switch.early.test:
209; CHECK:   switch i8 %c, label %if.end [
210; CHECK:     i8 99, label %if.then
211; CHECK:     i8 97, label %if.then
212; CHECK:   ]
213}
214
215define i32 @test8(i8 zeroext %c, i32 %x, i1 %C) nounwind ssp noredzone {
216entry:
217  br i1 %C, label %N, label %if.then
218N:
219  %cmp = icmp ult i32 %x, 32
220  %cmp4 = icmp eq i8 %c, 97
221  %or.cond = or i1 %cmp, %cmp4
222  %cmp9 = icmp eq i8 %c, 99
223  %or.cond11 = or i1 %or.cond, %cmp9
224  br i1 %or.cond11, label %if.then, label %if.end
225
226if.then:                                          ; preds = %entry
227  %A = phi i32 [0, %entry], [42, %N]
228  tail call void @foo1() nounwind noredzone
229  ret i32 %A
230
231if.end:                                           ; preds = %entry
232  ret i32 0
233
234; CHECK-LABEL: @test8(
235; CHECK: switch.early.test:
236; CHECK:   switch i8 %c, label %if.end [
237; CHECK:     i8 99, label %if.then
238; CHECK:     i8 97, label %if.then
239; CHECK:   ]
240; CHECK:   %A = phi i32 [ 0, %entry ], [ 42, %switch.early.test ], [ 42, %N ], [ 42, %switch.early.test ]
241}
242
243;; This is "Example 7" from http://blog.regehr.org/archives/320
244define i32 @test9(i8 zeroext %c) nounwind ssp noredzone {
245entry:
246  %cmp = icmp ult i8 %c, 33
247  br i1 %cmp, label %lor.end, label %lor.lhs.false
248
249lor.lhs.false:                                    ; preds = %entry
250  %cmp4 = icmp eq i8 %c, 46
251  br i1 %cmp4, label %lor.end, label %lor.lhs.false6
252
253lor.lhs.false6:                                   ; preds = %lor.lhs.false
254  %cmp9 = icmp eq i8 %c, 44
255  br i1 %cmp9, label %lor.end, label %lor.lhs.false11
256
257lor.lhs.false11:                                  ; preds = %lor.lhs.false6
258  %cmp14 = icmp eq i8 %c, 58
259  br i1 %cmp14, label %lor.end, label %lor.lhs.false16
260
261lor.lhs.false16:                                  ; preds = %lor.lhs.false11
262  %cmp19 = icmp eq i8 %c, 59
263  br i1 %cmp19, label %lor.end, label %lor.lhs.false21
264
265lor.lhs.false21:                                  ; preds = %lor.lhs.false16
266  %cmp24 = icmp eq i8 %c, 60
267  br i1 %cmp24, label %lor.end, label %lor.lhs.false26
268
269lor.lhs.false26:                                  ; preds = %lor.lhs.false21
270  %cmp29 = icmp eq i8 %c, 62
271  br i1 %cmp29, label %lor.end, label %lor.lhs.false31
272
273lor.lhs.false31:                                  ; preds = %lor.lhs.false26
274  %cmp34 = icmp eq i8 %c, 34
275  br i1 %cmp34, label %lor.end, label %lor.lhs.false36
276
277lor.lhs.false36:                                  ; preds = %lor.lhs.false31
278  %cmp39 = icmp eq i8 %c, 92
279  br i1 %cmp39, label %lor.end, label %lor.rhs
280
281lor.rhs:                                          ; preds = %lor.lhs.false36
282  %cmp43 = icmp eq i8 %c, 39
283  br label %lor.end
284
285lor.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
286  %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 ]
287  %conv46 = zext i1 %0 to i32
288  ret i32 %conv46
289
290; CHECK-LABEL: @test9(
291; CHECK:   %cmp = icmp ult i8 %c, 33
292; CHECK:   br i1 %cmp, label %lor.end, label %switch.early.test
293
294; CHECK: switch.early.test:
295; CHECK:   switch i8 %c, label %lor.rhs [
296; CHECK:     i8 92, label %lor.end
297; CHECK:     i8 62, label %lor.end
298; CHECK:     i8 60, label %lor.end
299; CHECK:     i8 59, label %lor.end
300; CHECK:     i8 58, label %lor.end
301; CHECK:     i8 46, label %lor.end
302; CHECK:     i8 44, label %lor.end
303; CHECK:     i8 34, label %lor.end
304; CHECK:     i8 39, label %lor.end
305; CHECK:   ]
306}
307
308define i32 @test10(i32 %mode, i1 %Cond) {
309  %A = icmp ne i32 %mode, 0
310  %B = icmp ne i32 %mode, 51
311  %C = and i1 %A, %B
312  %D = and i1 %C, %Cond
313  br i1 %D, label %T, label %F
314T:
315  ret i32 123
316F:
317  ret i32 324
318
319; CHECK-LABEL: @test10(
320; CHECK:  br i1 %Cond, label %switch.early.test, label %F
321; CHECK:switch.early.test:
322; CHECK:  switch i32 %mode, label %T [
323; CHECK:    i32 51, label %F
324; CHECK:    i32 0, label %F
325; CHECK:  ]
326}
327
328; PR8780
329define i32 @test11(i32 %bar) nounwind {
330entry:
331  %cmp = icmp eq i32 %bar, 4
332  %cmp2 = icmp eq i32 %bar, 35
333  %or.cond = or i1 %cmp, %cmp2
334  %cmp5 = icmp eq i32 %bar, 53
335  %or.cond1 = or i1 %or.cond, %cmp5
336  %cmp8 = icmp eq i32 %bar, 24
337  %or.cond2 = or i1 %or.cond1, %cmp8
338  %cmp11 = icmp eq i32 %bar, 23
339  %or.cond3 = or i1 %or.cond2, %cmp11
340  %cmp14 = icmp eq i32 %bar, 55
341  %or.cond4 = or i1 %or.cond3, %cmp14
342  %cmp17 = icmp eq i32 %bar, 12
343  %or.cond5 = or i1 %or.cond4, %cmp17
344  %cmp20 = icmp eq i32 %bar, 35
345  %or.cond6 = or i1 %or.cond5, %cmp20
346  br i1 %or.cond6, label %if.then, label %if.end
347
348if.then:                                          ; preds = %entry
349  br label %return
350
351if.end:                                           ; preds = %entry
352  br label %return
353
354return:                                           ; preds = %if.end, %if.then
355  %retval.0 = phi i32 [ 1, %if.then ], [ 0, %if.end ]
356  ret i32 %retval.0
357
358; CHECK-LABEL: @test11(
359; CHECK: switch i32 %bar, label %if.end [
360; CHECK:   i32 55, label %return
361; CHECK:   i32 53, label %return
362; CHECK:   i32 35, label %return
363; CHECK:   i32 24, label %return
364; CHECK:   i32 23, label %return
365; CHECK:   i32 12, label %return
366; CHECK:   i32 4, label %return
367; CHECK: ]
368}
369
370define void @test12() nounwind {
371entry:
372  br label %bb49.us.us
373
374bb49.us.us:
375  %A = icmp eq i32 undef, undef
376  br i1 %A, label %bb55.us.us, label %malformed
377
378bb48.us.us:
379  %B = icmp ugt i32 undef, undef
380  br i1 %B, label %bb55.us.us, label %bb49.us.us
381
382bb55.us.us:
383  br label %bb48.us.us
384
385malformed:
386  ret void
387; CHECK-LABEL: @test12(
388
389}
390
391; test13 - handle switch formation with ult.
392define void @test13(i32 %x) nounwind ssp noredzone {
393entry:
394  %cmp = icmp ult i32 %x, 2
395  br i1 %cmp, label %if.then, label %lor.lhs.false3
396
397lor.lhs.false3:                                   ; preds = %lor.lhs.false
398  %cmp5 = icmp eq i32 %x, 3
399  br i1 %cmp5, label %if.then, label %lor.lhs.false6
400
401lor.lhs.false6:                                   ; preds = %lor.lhs.false3
402  %cmp8 = icmp eq i32 %x, 4
403  br i1 %cmp8, label %if.then, label %lor.lhs.false9
404
405lor.lhs.false9:                                   ; preds = %lor.lhs.false6
406  %cmp11 = icmp eq i32 %x, 6
407  br i1 %cmp11, label %if.then, label %if.end
408
409if.then:                                          ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
410  call void @foo1() noredzone
411  br label %if.end
412
413if.end:                                           ; preds = %if.then, %lor.lhs.false9
414  ret void
415; CHECK-LABEL: @test13(
416; CHECK:  switch i32 %x, label %if.end [
417; CHECK:     i32 6, label %if.then
418; CHECK:     i32 4, label %if.then
419; CHECK:     i32 3, label %if.then
420; CHECK:     i32 1, label %if.then
421; CHECK:     i32 0, label %if.then
422; CHECK:   ]
423}
424
425; test14 - handle switch formation with ult.
426define void @test14(i32 %x) nounwind ssp noredzone {
427entry:
428  %cmp = icmp ugt i32 %x, 2
429  br i1 %cmp, label %lor.lhs.false3, label %if.then
430
431lor.lhs.false3:                                   ; preds = %lor.lhs.false
432  %cmp5 = icmp ne i32 %x, 3
433  br i1 %cmp5, label %lor.lhs.false6, label %if.then
434
435lor.lhs.false6:                                   ; preds = %lor.lhs.false3
436  %cmp8 = icmp ne i32 %x, 4
437  br i1 %cmp8, label %lor.lhs.false9, label %if.then
438
439lor.lhs.false9:                                   ; preds = %lor.lhs.false6
440  %cmp11 = icmp ne i32 %x, 6
441  br i1 %cmp11, label %if.end, label %if.then
442
443if.then:                                          ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
444  call void @foo1() noredzone
445  br label %if.end
446
447if.end:                                           ; preds = %if.then, %lor.lhs.false9
448  ret void
449; CHECK-LABEL: @test14(
450; CHECK:  switch i32 %x, label %if.end [
451; CHECK:     i32 6, label %if.then
452; CHECK:     i32 4, label %if.then
453; CHECK:     i32 3, label %if.then
454; CHECK:     i32 1, label %if.then
455; CHECK:     i32 0, label %if.then
456; CHECK:   ]
457}
458
459; Don't crash on ginormous ranges.
460define void @test15(i128 %x) nounwind {
461  %cmp = icmp ugt i128 %x, 2
462  br i1 %cmp, label %if.end, label %lor.false
463
464lor.false:
465  %cmp2 = icmp ne i128 %x, 100000000000000000000
466  br i1 %cmp2, label %if.end, label %if.then
467
468if.then:
469  call void @foo1() noredzone
470  br label %if.end
471
472if.end:
473  ret void
474
475; CHECK-LABEL: @test15(
476; CHECK-NOT: switch
477; CHECK: ret void
478}
479
480; PR8675
481; rdar://5134905
482define zeroext i1 @test16(i32 %x) nounwind {
483entry:
484; CHECK-LABEL: @test16(
485; CHECK: %x.off = add i32 %x, -1
486; CHECK: %switch = icmp ult i32 %x.off, 3
487  %cmp.i = icmp eq i32 %x, 1
488  br i1 %cmp.i, label %lor.end, label %lor.lhs.false
489
490lor.lhs.false:
491  %cmp.i2 = icmp eq i32 %x, 2
492  br i1 %cmp.i2, label %lor.end, label %lor.rhs
493
494lor.rhs:
495  %cmp.i1 = icmp eq i32 %x, 3
496  br label %lor.end
497
498lor.end:
499  %0 = phi i1 [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp.i1, %lor.rhs ]
500  ret i1 %0
501}
502
503; Check that we don't turn an icmp into a switch where it's not useful.
504define void @test17(i32 %x, i32 %y) {
505  %cmp = icmp ult i32 %x, 3
506  %switch = icmp ult i32 %y, 2
507  %or.cond775 = or i1 %cmp, %switch
508  br i1 %or.cond775, label %lor.lhs.false8, label %return
509
510lor.lhs.false8:
511  tail call void @foo1()
512  ret void
513
514return:
515  ret void
516
517; CHECK-LABEL: @test17(
518; CHECK-NOT: switch.early.test
519; CHECK-NOT: switch i32
520; CHECK: ret void
521}
522
523define void @test18(i32 %arg) {
524bb:
525  %tmp = and i32 %arg, -2
526  %tmp1 = icmp eq i32 %tmp, 8
527  %tmp2 = icmp eq i32 %arg, 10
528  %tmp3 = or i1 %tmp1, %tmp2
529  %tmp4 = icmp eq i32 %arg, 11
530  %tmp5 = or i1 %tmp3, %tmp4
531  %tmp6 = icmp eq i32 %arg, 12
532  %tmp7 = or i1 %tmp5, %tmp6
533  br i1 %tmp7, label %bb19, label %bb8
534
535bb8:                                              ; preds = %bb
536  %tmp9 = add i32 %arg, -13
537  %tmp10 = icmp ult i32 %tmp9, 2
538  %tmp11 = icmp eq i32 %arg, 16
539  %tmp12 = or i1 %tmp10, %tmp11
540  %tmp13 = icmp eq i32 %arg, 17
541  %tmp14 = or i1 %tmp12, %tmp13
542  %tmp15 = icmp eq i32 %arg, 18
543  %tmp16 = or i1 %tmp14, %tmp15
544  %tmp17 = icmp eq i32 %arg, 15
545  %tmp18 = or i1 %tmp16, %tmp17
546  br i1 %tmp18, label %bb19, label %bb20
547
548bb19:                                             ; preds = %bb8, %bb
549  tail call void @foo1()
550  br label %bb20
551
552bb20:                                             ; preds = %bb19, %bb8
553  ret void
554
555; CHECK-LABEL: @test18(
556; CHECK: %arg.off = add i32 %arg, -8
557; CHECK: icmp ult i32 %arg.off, 11
558}
559