1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -correlated-propagation -S < %s | FileCheck %s
3
4declare i32 @foo()
5
6define i32 @test1(i32 %a) nounwind {
7; CHECK-LABEL: @test1(
8; CHECK-NEXT:    [[A_OFF:%.*]] = add i32 [[A:%.*]], -8
9; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A_OFF]], 8
10; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
11; CHECK:       then:
12; CHECK-NEXT:    br i1 false, label [[END:%.*]], label [[ELSE]]
13; CHECK:       else:
14; CHECK-NEXT:    ret i32 1
15; CHECK:       end:
16; CHECK-NEXT:    ret i32 2
17;
18  %a.off = add i32 %a, -8
19  %cmp = icmp ult i32 %a.off, 8
20  br i1 %cmp, label %then, label %else
21
22then:
23  %dead = icmp eq i32 %a, 7
24  br i1 %dead, label %end, label %else
25
26else:
27  ret i32 1
28
29end:
30  ret i32 2
31}
32
33define i32 @test2(i32 %a) nounwind {
34; CHECK-LABEL: @test2(
35; CHECK-NEXT:    [[A_OFF:%.*]] = add i32 [[A:%.*]], -8
36; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A_OFF]], 8
37; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
38; CHECK:       then:
39; CHECK-NEXT:    br i1 false, label [[END:%.*]], label [[ELSE]]
40; CHECK:       else:
41; CHECK-NEXT:    ret i32 1
42; CHECK:       end:
43; CHECK-NEXT:    ret i32 2
44;
45  %a.off = add i32 %a, -8
46  %cmp = icmp ult i32 %a.off, 8
47  br i1 %cmp, label %then, label %else
48
49then:
50  %dead = icmp ugt i32 %a, 15
51  br i1 %dead, label %end, label %else
52
53else:
54  ret i32 1
55
56end:
57  ret i32 2
58}
59
60define i32 @test3(i32 %c) nounwind {
61; CHECK-LABEL: @test3(
62; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[C:%.*]], 2
63; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
64; CHECK:       if.then:
65; CHECK-NEXT:    ret i32 1
66; CHECK:       if.end:
67; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[C]], 3
68; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END8:%.*]]
69; CHECK:       if.then2:
70; CHECK-NEXT:    br i1 true, label [[IF_THEN4:%.*]], label [[IF_END6:%.*]]
71; CHECK:       if.end6:
72; CHECK-NEXT:    ret i32 2
73; CHECK:       if.then4:
74; CHECK-NEXT:    ret i32 3
75; CHECK:       if.end8:
76; CHECK-NEXT:    ret i32 4
77;
78  %cmp = icmp slt i32 %c, 2
79  br i1 %cmp, label %if.then, label %if.end
80
81if.then:
82  ret i32 1
83
84if.end:
85  %cmp1 = icmp slt i32 %c, 3
86  br i1 %cmp1, label %if.then2, label %if.end8
87
88if.then2:
89  %cmp2 = icmp eq i32 %c, 2
90  br i1 %cmp2, label %if.then4, label %if.end6
91
92if.end6:
93  ret i32 2
94
95if.then4:
96  ret i32 3
97
98if.end8:
99  ret i32 4
100}
101
102define i32 @test4(i32 %c) nounwind {
103; CHECK-LABEL: @test4(
104; CHECK-NEXT:    switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [
105; CHECK-NEXT:    i32 1, label [[SW_BB:%.*]]
106; CHECK-NEXT:    i32 2, label [[SW_BB]]
107; CHECK-NEXT:    i32 4, label [[SW_BB]]
108; CHECK-NEXT:    ]
109; CHECK:       sw.bb:
110; CHECK-NEXT:    br i1 true, label [[IF_THEN:%.*]], label [[IF_END:%.*]]
111; CHECK:       if.then:
112; CHECK-NEXT:    br label [[RETURN:%.*]]
113; CHECK:       if.end:
114; CHECK-NEXT:    br label [[RETURN]]
115; CHECK:       sw.default:
116; CHECK-NEXT:    br label [[RETURN]]
117; CHECK:       return:
118; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ 42, [[SW_DEFAULT]] ], [ 4, [[IF_THEN]] ], [ 9, [[IF_END]] ]
119; CHECK-NEXT:    ret i32 [[RETVAL_0]]
120;
121  switch i32 %c, label %sw.default [
122  i32 1, label %sw.bb
123  i32 2, label %sw.bb
124  i32 4, label %sw.bb
125  ]
126
127sw.bb:
128  %cmp = icmp sge i32 %c, 1
129  br i1 %cmp, label %if.then, label %if.end
130
131if.then:
132  br label %return
133
134if.end:
135  br label %return
136
137sw.default:
138  br label %return
139
140return:
141  %retval.0 = phi i32 [ 42, %sw.default ], [ 4, %if.then ], [ 9, %if.end ]
142  ret i32 %retval.0
143}
144
145define i1 @test5(i32 %c) nounwind {
146; CHECK-LABEL: @test5(
147; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[C:%.*]], 5
148; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
149; CHECK:       if.then:
150; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[C]], 4
151; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_END]], label [[IF_END8:%.*]]
152; CHECK:       if.end:
153; CHECK-NEXT:    ret i1 true
154; CHECK:       if.end8:
155; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[C]], 3
156; CHECK-NEXT:    [[OR:%.*]] = or i1 false, false
157; CHECK-NEXT:    ret i1 [[CMP2]]
158;
159  %cmp = icmp slt i32 %c, 5
160  br i1 %cmp, label %if.then, label %if.end
161
162if.then:
163  %cmp1 = icmp eq i32 %c, 4
164  br i1 %cmp1, label %if.end, label %if.end8
165
166if.end:
167  ret i1 true
168
169if.end8:
170  %cmp2 = icmp eq i32 %c, 3
171  %cmp3 = icmp eq i32 %c, 4
172  %cmp4 = icmp eq i32 %c, 6
173  %or = or i1 %cmp3, %cmp4
174  ret i1 %cmp2
175}
176
177define i1 @test6(i32 %c) nounwind {
178; CHECK-LABEL: @test6(
179; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i32 [[C:%.*]], 7
180; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
181; CHECK:       if.then:
182; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[C]], 6
183; CHECK-NEXT:    br i1 [[COND]], label [[SW_BB:%.*]], label [[IF_END]]
184; CHECK:       if.end:
185; CHECK-NEXT:    ret i1 true
186; CHECK:       sw.bb:
187; CHECK-NEXT:    ret i1 true
188;
189  %cmp = icmp ule i32 %c, 7
190  br i1 %cmp, label %if.then, label %if.end
191
192if.then:
193  switch i32 %c, label %if.end [
194  i32 6, label %sw.bb
195  i32 8, label %sw.bb
196  ]
197
198if.end:
199  ret i1 true
200
201sw.bb:
202  %cmp2 = icmp eq i32 %c, 6
203  ret i1 %cmp2
204}
205
206define i1 @test7(i32 %c) nounwind {
207; CHECK-LABEL: @test7(
208; CHECK-NEXT:  entry:
209; CHECK-NEXT:    switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [
210; CHECK-NEXT:    i32 6, label [[SW_BB:%.*]]
211; CHECK-NEXT:    i32 7, label [[SW_BB]]
212; CHECK-NEXT:    ]
213; CHECK:       sw.bb:
214; CHECK-NEXT:    ret i1 true
215; CHECK:       sw.default:
216; CHECK-NEXT:    [[CMP5:%.*]] = icmp eq i32 [[C]], 5
217; CHECK-NEXT:    [[CMP8:%.*]] = icmp eq i32 [[C]], 8
218; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP5]], false
219; CHECK-NEXT:    [[OR2:%.*]] = or i1 false, [[CMP8]]
220; CHECK-NEXT:    ret i1 false
221;
222entry:
223  switch i32 %c, label %sw.default [
224  i32 6, label %sw.bb
225  i32 7, label %sw.bb
226  ]
227
228sw.bb:
229  ret i1 true
230
231sw.default:
232  %cmp5 = icmp eq i32 %c, 5
233  %cmp6 = icmp eq i32 %c, 6
234  %cmp7 = icmp eq i32 %c, 7
235  %cmp8 = icmp eq i32 %c, 8
236  %or = or i1 %cmp5, %cmp6
237  %or2 = or i1 %cmp7, %cmp8
238  ret i1 false
239}
240
241define i1 @test8(i64* %p) {
242; CHECK-LABEL: @test8(
243; CHECK-NEXT:    [[A:%.*]] = load i64, i64* [[P:%.*]], align 4, !range [[RNG0:![0-9]+]]
244; CHECK-NEXT:    ret i1 false
245;
246  %a = load i64, i64* %p, !range !{i64 4, i64 255}
247  %res = icmp eq i64 %a, 0
248  ret i1 %res
249}
250
251define i1 @test9(i64* %p) {
252; CHECK-LABEL: @test9(
253; CHECK-NEXT:    [[A:%.*]] = load i64, i64* [[P:%.*]], align 4, !range [[RNG1:![0-9]+]]
254; CHECK-NEXT:    ret i1 true
255;
256  %a = load i64, i64* %p, !range !{i64 0, i64 1}
257  %res = icmp eq i64 %a, 0
258  ret i1 %res
259}
260
261define i1 @test10(i64* %p) {
262; CHECK-LABEL: @test10(
263; CHECK-NEXT:    [[A:%.*]] = load i64, i64* [[P:%.*]], align 4, !range [[RNG2:![0-9]+]]
264; CHECK-NEXT:    ret i1 false
265;
266  %a = load i64, i64* %p, !range !{i64 4, i64 8, i64 15, i64 20}
267  %res = icmp eq i64 %a, 0
268  ret i1 %res
269}
270
271@g = external global i32
272
273define i1 @test11() {
274; CHECK-LABEL: @test11(
275; CHECK-NEXT:    [[POSITIVE:%.*]] = load i32, i32* @g, align 4, !range [[RNG3:![0-9]+]]
276; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i32 [[POSITIVE]], 1
277; CHECK-NEXT:    br label [[NEXT:%.*]]
278; CHECK:       next:
279; CHECK-NEXT:    ret i1 true
280;
281  %positive = load i32, i32* @g, !range !{i32 1, i32 2048}
282  %add = add i32 %positive, 1
283  %test = icmp sgt i32 %add, 0
284  br label %next
285
286next:
287  ret i1 %test
288}
289
290define i32 @test12(i32 %a, i32 %b) {
291; CHECK-LABEL: @test12(
292; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
293; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
294; CHECK:       then:
295; CHECK-NEXT:    br i1 false, label [[END:%.*]], label [[ELSE]]
296; CHECK:       else:
297; CHECK-NEXT:    ret i32 1
298; CHECK:       end:
299; CHECK-NEXT:    ret i32 2
300;
301  %cmp = icmp ult i32 %a, %b
302  br i1 %cmp, label %then, label %else
303
304then:
305  %dead = icmp eq i32 %a, -1
306  br i1 %dead, label %end, label %else
307
308else:
309  ret i32 1
310
311end:
312  ret i32 2
313}
314
315define i32 @test12_swap(i32 %a, i32 %b) {
316; CHECK-LABEL: @test12_swap(
317; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[B:%.*]], [[A:%.*]]
318; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
319; CHECK:       then:
320; CHECK-NEXT:    br i1 false, label [[END:%.*]], label [[ELSE]]
321; CHECK:       else:
322; CHECK-NEXT:    ret i32 1
323; CHECK:       end:
324; CHECK-NEXT:    ret i32 2
325;
326  %cmp = icmp ugt i32 %b, %a
327  br i1 %cmp, label %then, label %else
328
329then:
330  %dead = icmp eq i32 %a, -1
331  br i1 %dead, label %end, label %else
332
333else:
334  ret i32 1
335
336end:
337  ret i32 2
338}
339
340; The same as @test12 but the second check is on the false path
341
342define i32 @test12_neg(i32 %a, i32 %b) {
343; CHECK-LABEL: @test12_neg(
344; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
345; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
346; CHECK:       else:
347; CHECK-NEXT:    [[ALIVE:%.*]] = icmp eq i32 [[A]], -1
348; CHECK-NEXT:    br i1 [[ALIVE]], label [[END:%.*]], label [[THEN]]
349; CHECK:       then:
350; CHECK-NEXT:    ret i32 1
351; CHECK:       end:
352; CHECK-NEXT:    ret i32 2
353;
354  %cmp = icmp ult i32 %a, %b
355  br i1 %cmp, label %then, label %else
356
357else:
358  %alive = icmp eq i32 %a, -1
359  br i1 %alive, label %end, label %then
360
361then:
362  ret i32 1
363
364end:
365  ret i32 2
366}
367
368; The same as @test12 but with signed comparison
369
370define i32 @test12_signed(i32 %a, i32 %b) {
371; CHECK-LABEL: @test12_signed(
372; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
373; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
374; CHECK:       then:
375; CHECK-NEXT:    br i1 false, label [[END:%.*]], label [[ELSE]]
376; CHECK:       else:
377; CHECK-NEXT:    ret i32 1
378; CHECK:       end:
379; CHECK-NEXT:    ret i32 2
380;
381  %cmp = icmp slt i32 %a, %b
382  br i1 %cmp, label %then, label %else
383
384then:
385  %dead = icmp eq i32 %a, 2147483647
386  br i1 %dead, label %end, label %else
387
388else:
389  ret i32 1
390
391end:
392  ret i32 2
393}
394
395define i32 @test13(i32 %a, i32 %b) {
396; CHECK-LABEL: @test13(
397; CHECK-NEXT:    [[A_OFF:%.*]] = add i32 [[A:%.*]], -8
398; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A_OFF]], [[B:%.*]]
399; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
400; CHECK:       then:
401; CHECK-NEXT:    br i1 false, label [[END:%.*]], label [[ELSE]]
402; CHECK:       else:
403; CHECK-NEXT:    ret i32 1
404; CHECK:       end:
405; CHECK-NEXT:    ret i32 2
406;
407  %a.off = add i32 %a, -8
408  %cmp = icmp ult i32 %a.off, %b
409  br i1 %cmp, label %then, label %else
410
411then:
412  %dead = icmp eq i32 %a, 7
413  br i1 %dead, label %end, label %else
414
415else:
416  ret i32 1
417
418end:
419  ret i32 2
420}
421
422define i32 @test13_swap(i32 %a, i32 %b) {
423; CHECK-LABEL: @test13_swap(
424; CHECK-NEXT:    [[A_OFF:%.*]] = add i32 [[A:%.*]], -8
425; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[B:%.*]], [[A_OFF]]
426; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
427; CHECK:       then:
428; CHECK-NEXT:    br i1 false, label [[END:%.*]], label [[ELSE]]
429; CHECK:       else:
430; CHECK-NEXT:    ret i32 1
431; CHECK:       end:
432; CHECK-NEXT:    ret i32 2
433;
434  %a.off = add i32 %a, -8
435  %cmp = icmp ugt i32 %b, %a.off
436  br i1 %cmp, label %then, label %else
437
438then:
439  %dead = icmp eq i32 %a, 7
440  br i1 %dead, label %end, label %else
441
442else:
443  ret i32 1
444
445end:
446  ret i32 2
447}
448
449define i1 @test14_slt(i32 %a) {
450; CHECK-LABEL: @test14_slt(
451; CHECK-NEXT:    [[A_OFF:%.*]] = add i32 [[A:%.*]], -8
452; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A_OFF]], 8
453; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
454; CHECK:       then:
455; CHECK-NEXT:    [[RESULT:%.*]] = or i1 false, false
456; CHECK-NEXT:    ret i1 false
457; CHECK:       else:
458; CHECK-NEXT:    ret i1 false
459;
460  %a.off = add i32 %a, -8
461  %cmp = icmp slt i32 %a.off, 8
462  br i1 %cmp, label %then, label %else
463
464then:
465  %dead.1 = icmp eq i32 %a, -2147483641
466  %dead.2 = icmp eq i32 %a, 16
467  %result = or i1 %dead.1, %dead.2
468  ret i1 %result
469
470else:
471  ret i1 false
472}
473
474define i1 @test14_sle(i32 %a) {
475; CHECK-LABEL: @test14_sle(
476; CHECK-NEXT:    [[A_OFF:%.*]] = add i32 [[A:%.*]], -8
477; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A_OFF]], 8
478; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
479; CHECK:       then:
480; CHECK-NEXT:    [[ALIVE:%.*]] = icmp eq i32 [[A]], 16
481; CHECK-NEXT:    [[RESULT:%.*]] = or i1 false, [[ALIVE]]
482; CHECK-NEXT:    ret i1 [[RESULT]]
483; CHECK:       else:
484; CHECK-NEXT:    ret i1 false
485;
486  %a.off = add i32 %a, -8
487  %cmp = icmp sle i32 %a.off, 8
488  br i1 %cmp, label %then, label %else
489
490then:
491  %dead = icmp eq i32 %a, -2147483641
492  %alive = icmp eq i32 %a, 16
493  %result = or i1 %dead, %alive
494  ret i1 %result
495
496else:
497  ret i1 false
498}
499
500define i1 @test14_sgt(i32 %a) {
501; CHECK-LABEL: @test14_sgt(
502; CHECK-NEXT:    [[A_OFF:%.*]] = add i32 [[A:%.*]], -8
503; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A_OFF]], 8
504; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
505; CHECK:       then:
506; CHECK-NEXT:    [[RESULT:%.*]] = or i1 false, false
507; CHECK-NEXT:    ret i1 false
508; CHECK:       else:
509; CHECK-NEXT:    ret i1 false
510;
511  %a.off = add i32 %a, -8
512  %cmp = icmp sgt i32 %a.off, 8
513  br i1 %cmp, label %then, label %else
514
515then:
516  %dead.1 = icmp eq i32 %a, -2147483640
517  %dead.2 = icmp eq i32 %a, 16
518  %result = or i1 %dead.1, %dead.2
519  ret i1 %result
520
521else:
522  ret i1 false
523}
524
525define i1 @test14_sge(i32 %a) {
526; CHECK-LABEL: @test14_sge(
527; CHECK-NEXT:    [[A_OFF:%.*]] = add i32 [[A:%.*]], -8
528; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A_OFF]], 8
529; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
530; CHECK:       then:
531; CHECK-NEXT:    [[ALIVE:%.*]] = icmp eq i32 [[A]], 16
532; CHECK-NEXT:    [[RESULT:%.*]] = or i1 false, [[ALIVE]]
533; CHECK-NEXT:    ret i1 [[RESULT]]
534; CHECK:       else:
535; CHECK-NEXT:    ret i1 false
536;
537  %a.off = add i32 %a, -8
538  %cmp = icmp sge i32 %a.off, 8
539  br i1 %cmp, label %then, label %else
540
541then:
542  %dead = icmp eq i32 %a, -2147483640
543  %alive = icmp eq i32 %a, 16
544  %result = or i1 %dead, %alive
545  ret i1 %result
546
547else:
548  ret i1 false
549}
550
551define i1 @test14_ule(i32 %a) {
552; CHECK-LABEL: @test14_ule(
553; CHECK-NEXT:    [[A_OFF:%.*]] = add i32 [[A:%.*]], -8
554; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i32 [[A_OFF]], 8
555; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
556; CHECK:       then:
557; CHECK-NEXT:    [[ALIVE:%.*]] = icmp eq i32 [[A]], 16
558; CHECK-NEXT:    [[RESULT:%.*]] = or i1 false, [[ALIVE]]
559; CHECK-NEXT:    ret i1 [[RESULT]]
560; CHECK:       else:
561; CHECK-NEXT:    ret i1 false
562;
563  %a.off = add i32 %a, -8
564  %cmp = icmp ule i32 %a.off, 8
565  br i1 %cmp, label %then, label %else
566
567then:
568  %dead = icmp eq i32 %a, 7
569  %alive = icmp eq i32 %a, 16
570  %result = or i1 %dead, %alive
571  ret i1 %result
572
573else:
574  ret i1 false
575}
576
577define i1 @test14_ugt(i32 %a) {
578; CHECK-LABEL: @test14_ugt(
579; CHECK-NEXT:    [[A_OFF:%.*]] = add i32 [[A:%.*]], -8
580; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A_OFF]], 8
581; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
582; CHECK:       then:
583; CHECK-NEXT:    [[RESULT:%.*]] = or i1 false, false
584; CHECK-NEXT:    ret i1 false
585; CHECK:       else:
586; CHECK-NEXT:    ret i1 false
587;
588  %a.off = add i32 %a, -8
589  %cmp = icmp ugt i32 %a.off, 8
590  br i1 %cmp, label %then, label %else
591
592then:
593  %dead.1 = icmp eq i32 %a, 8
594  %dead.2 = icmp eq i32 %a, 16
595  %result = or i1 %dead.1, %dead.2
596  ret i1 %result
597
598else:
599  ret i1 false
600}
601
602define i1 @test14_uge(i32 %a) {
603; CHECK-LABEL: @test14_uge(
604; CHECK-NEXT:    [[A_OFF:%.*]] = add i32 [[A:%.*]], -8
605; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[A_OFF]], 8
606; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
607; CHECK:       then:
608; CHECK-NEXT:    [[ALIVE:%.*]] = icmp eq i32 [[A]], 16
609; CHECK-NEXT:    [[RESULT:%.*]] = or i1 false, [[ALIVE]]
610; CHECK-NEXT:    ret i1 [[RESULT]]
611; CHECK:       else:
612; CHECK-NEXT:    ret i1 false
613;
614  %a.off = add i32 %a, -8
615  %cmp = icmp uge i32 %a.off, 8
616  br i1 %cmp, label %then, label %else
617
618then:
619  %dead = icmp eq i32 %a, 8
620  %alive = icmp eq i32 %a, 16
621  %result = or i1 %dead, %alive
622  ret i1 %result
623
624else:
625  ret i1 false
626}
627
628define i1 @test14_ugt_and(i32 %a) {
629; CHECK-LABEL: @test14_ugt_and(
630; CHECK-NEXT:    [[A_OFF:%.*]] = add i32 [[A:%.*]], -8
631; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A_OFF]], 8
632; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
633; CHECK:       then:
634; CHECK-NEXT:    [[RESULT:%.*]] = and i1 false, false
635; CHECK-NEXT:    ret i1 false
636; CHECK:       else:
637; CHECK-NEXT:    ret i1 false
638;
639  %a.off = add i32 %a, -8
640  %cmp = icmp ugt i32 %a.off, 8
641  br i1 %cmp, label %then, label %else
642
643then:
644  %dead.1 = icmp eq i32 %a, 8
645  %dead.2 = icmp eq i32 %a, 16
646  %result = and i1 %dead.1, %dead.2
647  ret i1 %result
648
649else:
650  ret i1 false
651}
652
653@limit = external global i32
654define i1 @test15(i32 %a) {
655; CHECK-LABEL: @test15(
656; CHECK-NEXT:    [[LIMIT:%.*]] = load i32, i32* @limit, align 4, !range [[RNG4:![0-9]+]]
657; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], [[LIMIT]]
658; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
659; CHECK:       then:
660; CHECK-NEXT:    ret i1 false
661; CHECK:       else:
662; CHECK-NEXT:    ret i1 false
663;
664  %limit = load i32, i32* @limit, !range !{i32 0, i32 256}
665  %cmp = icmp ult i32 %a, %limit
666  br i1 %cmp, label %then, label %else
667
668then:
669  %result = icmp eq i32 %a, 255
670  ret i1 %result
671
672else:
673  ret i1 false
674}
675
676define i32 @test16(i8 %a) {
677; CHECK-LABEL: @test16(
678; CHECK-NEXT:  entry:
679; CHECK-NEXT:    [[B:%.*]] = zext i8 [[A:%.*]] to i32
680; CHECK-NEXT:    br label [[DISPATCH:%.*]]
681; CHECK:       dispatch:
682; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[A]], 93
683; CHECK-NEXT:    br i1 [[CMP]], label [[TARGET93:%.*]], label [[DISPATCH]]
684; CHECK:       target93:
685; CHECK-NEXT:    ret i32 93
686;
687entry:
688  %b = zext i8 %a to i32
689  br label %dispatch
690
691dispatch:
692  %cmp = icmp eq i8 %a, 93
693  br i1 %cmp, label %target93, label %dispatch
694
695target93:
696  ret i32 %b
697}
698
699define i32 @test16_i1(i1 %a) {
700; CHECK-LABEL: @test16_i1(
701; CHECK-NEXT:  entry:
702; CHECK-NEXT:    [[B:%.*]] = zext i1 [[A:%.*]] to i32
703; CHECK-NEXT:    br label [[DISPATCH:%.*]]
704; CHECK:       dispatch:
705; CHECK-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[DISPATCH]]
706; CHECK:       true:
707; CHECK-NEXT:    ret i32 1
708;
709entry:
710  %b = zext i1 %a to i32
711  br label %dispatch
712
713dispatch:
714  br i1 %a, label %true, label %dispatch
715
716true:
717  ret i32 %b
718}
719
720define i8 @test17(i8 %a) {
721; CHECK-LABEL: @test17(
722; CHECK-NEXT:  entry:
723; CHECK-NEXT:    [[C:%.*]] = add i8 [[A:%.*]], 3
724; CHECK-NEXT:    br label [[DISPATCH:%.*]]
725; CHECK:       dispatch:
726; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[A]], 93
727; CHECK-NEXT:    br i1 [[CMP]], label [[TARGET93:%.*]], label [[DISPATCH]]
728; CHECK:       target93:
729; CHECK-NEXT:    ret i8 96
730;
731entry:
732  %c = add i8 %a, 3
733  br label %dispatch
734
735dispatch:
736  %cmp = icmp eq i8 %a, 93
737  br i1 %cmp, label %target93, label %dispatch
738
739target93:
740  ret i8 %c
741}
742
743define i8 @test17_2(i8 %a) {
744; CHECK-LABEL: @test17_2(
745; CHECK-NEXT:  entry:
746; CHECK-NEXT:    [[C:%.*]] = add i8 [[A:%.*]], [[A]]
747; CHECK-NEXT:    br label [[DISPATCH:%.*]]
748; CHECK:       dispatch:
749; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[A]], 93
750; CHECK-NEXT:    br i1 [[CMP]], label [[TARGET93:%.*]], label [[DISPATCH]]
751; CHECK:       target93:
752; CHECK-NEXT:    ret i8 -70
753;
754entry:
755  %c = add i8 %a, %a
756  br label %dispatch
757
758dispatch:
759  %cmp = icmp eq i8 %a, 93
760  br i1 %cmp, label %target93, label %dispatch
761
762target93:
763  ret i8 %c
764}
765
766define i1 @test17_i1(i1 %a) {
767; CHECK-LABEL: @test17_i1(
768; CHECK-NEXT:  entry:
769; CHECK-NEXT:    br label [[DISPATCH:%.*]]
770; CHECK:       dispatch:
771; CHECK-NEXT:    br i1 [[A:%.*]], label [[TRUE:%.*]], label [[DISPATCH]]
772; CHECK:       true:
773; CHECK-NEXT:    ret i1 true
774;
775entry:
776  %c = and i1 %a, true
777  br label %dispatch
778
779dispatch:
780  br i1 %a, label %true, label %dispatch
781
782true:
783  ret i1 %c
784}
785
786define i32 @test18(i8 %a) {
787; CHECK-LABEL: @test18(
788; CHECK-NEXT:  entry:
789; CHECK-NEXT:    [[B:%.*]] = zext i8 [[A:%.*]] to i32
790; CHECK-NEXT:    br label [[DISPATCH:%.*]]
791; CHECK:       dispatch:
792; CHECK-NEXT:    switch i8 [[A]], label [[DISPATCH]] [
793; CHECK-NEXT:    i8 93, label [[TARGET93:%.*]]
794; CHECK-NEXT:    i8 -111, label [[DISPATCH]]
795; CHECK-NEXT:    ]
796; CHECK:       target93:
797; CHECK-NEXT:    ret i32 93
798;
799entry:
800  %b = zext i8 %a to i32
801  br label %dispatch
802
803dispatch:
804  switch i8 %a, label %dispatch [
805  i8 93, label %target93
806  i8 -111, label %dispatch
807  ]
808
809target93:
810  ret i32 %b
811}
812
813define i8 @test19(i8 %a) {
814; CHECK-LABEL: @test19(
815; CHECK-NEXT:  entry:
816; CHECK-NEXT:    [[C:%.*]] = add i8 [[A:%.*]], 3
817; CHECK-NEXT:    br label [[DISPATCH:%.*]]
818; CHECK:       dispatch:
819; CHECK-NEXT:    switch i8 [[A]], label [[DISPATCH]] [
820; CHECK-NEXT:    i8 93, label [[TARGET93:%.*]]
821; CHECK-NEXT:    i8 -111, label [[DISPATCH]]
822; CHECK-NEXT:    ]
823; CHECK:       target93:
824; CHECK-NEXT:    ret i8 96
825;
826entry:
827  %c = add i8 %a, 3
828  br label %dispatch
829
830dispatch:
831  switch i8 %a, label %dispatch [
832  i8 93, label %target93
833  i8 -111, label %dispatch
834  ]
835
836target93:
837  ret i8 %c
838}
839
840; Negative test. Shouldn't be incorrectly optimized to "ret i1 false".
841
842define i1 @test20(i64 %a) {
843; CHECK-LABEL: @test20(
844; CHECK-NEXT:  entry:
845; CHECK-NEXT:    [[B:%.*]] = and i64 [[A:%.*]], 7
846; CHECK-NEXT:    br label [[DISPATCH:%.*]]
847; CHECK:       dispatch:
848; CHECK-NEXT:    switch i64 [[A]], label [[DEFAULT:%.*]] [
849; CHECK-NEXT:    i64 0, label [[EXIT2:%.*]]
850; CHECK-NEXT:    i64 -2147483647, label [[EXIT2]]
851; CHECK-NEXT:    ]
852; CHECK:       default:
853; CHECK-NEXT:    [[C:%.*]] = icmp eq i64 [[B]], 0
854; CHECK-NEXT:    br label [[EXIT:%.*]]
855; CHECK:       exit:
856; CHECK-NEXT:    ret i1 [[C]]
857; CHECK:       exit2:
858; CHECK-NEXT:    ret i1 false
859;
860entry:
861  %b = and i64 %a, 7
862  br label %dispatch
863
864dispatch:
865  switch i64 %a, label %default [
866  i64 0, label %exit2
867  i64 -2147483647, label %exit2
868  ]
869
870default:
871  %c = icmp eq i64 %b, 0
872  br label %exit
873
874exit:
875  ret i1 %c
876
877exit2:
878  ret i1 false
879}
880
881define i1 @slt(i8 %a, i8 %b) {
882; CHECK-LABEL: @slt(
883; CHECK-NEXT:  entry:
884; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]
885; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
886; CHECK-NEXT:    ret i1 true
887;
888entry:
889  %cmp = icmp slt i8 %a, %b
890  call void @llvm.assume(i1 %cmp)
891  %res = icmp slt i8 %a, 127
892  ret i1 %res
893}
894
895define i1 @sgt(i8 %a, i8 %b) {
896; CHECK-LABEL: @sgt(
897; CHECK-NEXT:  entry:
898; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
899; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
900; CHECK-NEXT:    ret i1 true
901;
902entry:
903  %cmp = icmp sgt i8 %a, %b
904  call void @llvm.assume(i1 %cmp)
905  %res = icmp sgt i8 %a, -128
906  ret i1 %res
907}
908
909define i1 @ult(i8 %a, i8 %b) {
910; CHECK-LABEL: @ult(
911; CHECK-NEXT:  entry:
912; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
913; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
914; CHECK-NEXT:    ret i1 true
915;
916entry:
917  %cmp = icmp ult i8 %a, %b
918  call void @llvm.assume(i1 %cmp)
919  %res = icmp ult i8 %a, 255
920  ret i1 %res
921}
922
923define i1 @ugt(i8 %a, i8 %b) {
924; CHECK-LABEL: @ugt(
925; CHECK-NEXT:  entry:
926; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[A:%.*]], [[B:%.*]]
927; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
928; CHECK-NEXT:    ret i1 true
929;
930entry:
931  %cmp = icmp ugt i8 %a, %b
932  call void @llvm.assume(i1 %cmp)
933  %res = icmp ugt i8 %a, 0
934  ret i1 %res
935}
936
937define i1 @intrinsic_range(i16 %x) {
938; CHECK-LABEL: @intrinsic_range(
939; CHECK-NEXT:    [[CTLZ:%.*]] = call i16 @llvm.ctlz.i16(i16 [[X:%.*]], i1 false), !range [[RNG5:![0-9]+]]
940; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i16 [[CTLZ]] to i8
941; CHECK-NEXT:    ret i1 true
942;
943  %ctlz = call i16 @llvm.ctlz.i16(i16 %x, i1 false), !range !{i16 0, i16 8}
944  %trunc = trunc i16 %ctlz to i8
945  %res = icmp ult i8 %trunc, 8
946  ret i1 %res
947}
948
949declare i16 @llvm.ctlz.i16(i16, i1)
950declare void @llvm.assume(i1)
951