1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -correlated-propagation -S | FileCheck %s
3; PR2581
4
5define i32 @test1(i1 %C) {
6; CHECK-LABEL: @test1(
7; CHECK-NEXT:    br i1 [[C:%.*]], label [[EXIT:%.*]], label [[BODY:%.*]]
8; CHECK:       body:
9; CHECK-NEXT:    ret i32 11
10; CHECK:       exit:
11; CHECK-NEXT:    ret i32 10
12;
13  br i1 %C, label %exit, label %body
14
15body:           ; preds = %0
16  %A = select i1 %C, i32 10, i32 11
17  ret i32 %A
18
19exit:           ; preds = %0
20  ret i32 10
21}
22
23; PR4420
24declare i1 @ext()
25define i1 @test2() {
26; CHECK-LABEL: @test2(
27; CHECK-NEXT:  entry:
28; CHECK-NEXT:    [[COND:%.*]] = tail call i1 @ext()
29; CHECK-NEXT:    br i1 [[COND]], label [[BB1:%.*]], label [[BB2:%.*]]
30; CHECK:       bb1:
31; CHECK-NEXT:    [[COND2:%.*]] = tail call i1 @ext()
32; CHECK-NEXT:    br i1 [[COND2]], label [[BB3:%.*]], label [[BB2]]
33; CHECK:       bb2:
34; CHECK-NEXT:    ret i1 false
35; CHECK:       bb3:
36; CHECK-NEXT:    [[RES:%.*]] = tail call i1 @ext()
37; CHECK-NEXT:    ret i1 [[RES]]
38;
39entry:
40  %cond = tail call i1 @ext()
41  br i1 %cond, label %bb1, label %bb2
42
43bb1:
44  %cond2 = tail call i1 @ext()
45  br i1 %cond2, label %bb3, label %bb2
46
47bb2:
48  %cond_merge = phi i1 [ %cond, %entry ], [ false, %bb1 ]
49  ret i1 %cond_merge
50
51bb3:
52  %res = tail call i1 @ext()
53  ret i1 %res
54}
55
56; PR4855
57@gv = internal constant i8 7
58define i8 @test3(i8* %a) nounwind {
59; CHECK-LABEL: @test3(
60; CHECK-NEXT:  entry:
61; CHECK-NEXT:    [[COND:%.*]] = icmp eq i8* [[A:%.*]], @gv
62; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB:%.*]]
63; CHECK:       bb:
64; CHECK-NEXT:    ret i8 0
65; CHECK:       bb2:
66; CHECK-NEXT:    [[SHOULD_BE_CONST:%.*]] = load i8, i8* @gv
67; CHECK-NEXT:    ret i8 [[SHOULD_BE_CONST]]
68;
69entry:
70  %cond = icmp eq i8* %a, @gv
71  br i1 %cond, label %bb2, label %bb
72
73bb:
74  ret i8 0
75
76bb2:
77  %should_be_const = load i8, i8* %a
78  ret i8 %should_be_const
79}
80
81; PR1757
82define i32 @test4(i32) {
83; CHECK-LABEL: @test4(
84; CHECK-NEXT:  EntryBlock:
85; CHECK-NEXT:    [[DOTDEMORGAN:%.*]] = icmp sgt i32 [[TMP0:%.*]], 2
86; CHECK-NEXT:    br i1 [[DOTDEMORGAN]], label [[GREATERTHANTWO:%.*]], label [[LESSTHANOREQUALTOTWO:%.*]]
87; CHECK:       GreaterThanTwo:
88; CHECK-NEXT:    br i1 false, label [[IMPOSSIBLE:%.*]], label [[NOTTWOANDGREATERTHANTWO:%.*]]
89; CHECK:       NotTwoAndGreaterThanTwo:
90; CHECK-NEXT:    ret i32 2
91; CHECK:       Impossible:
92; CHECK-NEXT:    ret i32 1
93; CHECK:       LessThanOrEqualToTwo:
94; CHECK-NEXT:    ret i32 0
95;
96EntryBlock:
97  %.demorgan = icmp sgt i32 %0, 2
98  br i1 %.demorgan, label %GreaterThanTwo, label %LessThanOrEqualToTwo
99
100GreaterThanTwo:
101  icmp eq i32 %0, 2
102  br i1 %1, label %Impossible, label %NotTwoAndGreaterThanTwo
103
104NotTwoAndGreaterThanTwo:
105  ret i32 2
106
107Impossible:
108  ret i32 1
109
110LessThanOrEqualToTwo:
111  ret i32 0
112}
113
114declare i32* @f(i32*)
115define void @test5(i32* %x, i32* %y) {
116; CHECK-LABEL: @test5(
117; CHECK-NEXT:  entry:
118; CHECK-NEXT:    [[PRE:%.*]] = icmp eq i32* [[X:%.*]], null
119; CHECK-NEXT:    br i1 [[PRE]], label [[RETURN:%.*]], label [[LOOP:%.*]]
120; CHECK:       loop:
121; CHECK-NEXT:    [[PHI:%.*]] = phi i32* [ [[F:%.*]], [[LOOP]] ], [ [[X]], [[ENTRY:%.*]] ]
122; CHECK-NEXT:    [[F]] = tail call i32* @f(i32* [[PHI]])
123; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32* [[F]], [[Y:%.*]]
124; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i32* [[F]], i32* null
125; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32* [[SEL]], null
126; CHECK-NEXT:    br i1 [[CMP2]], label [[RETURN]], label [[LOOP]]
127; CHECK:       return:
128; CHECK-NEXT:    ret void
129;
130entry:
131  %pre = icmp eq i32* %x, null
132  br i1 %pre, label %return, label %loop
133
134loop:
135  %phi = phi i32* [ %sel, %loop ], [ %x, %entry ]
136  %f = tail call i32* @f(i32* %phi)
137  %cmp1 = icmp ne i32* %f, %y
138  %sel = select i1 %cmp1, i32* %f, i32* null
139  %cmp2 = icmp eq i32* %sel, null
140  br i1 %cmp2, label %return, label %loop
141
142return:
143  ret void
144}
145
146define i32 @switch1(i32 %s) {
147; CHECK-LABEL: @switch1(
148; CHECK-NEXT:  entry:
149; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[S:%.*]], 0
150; CHECK-NEXT:    br i1 [[CMP]], label [[NEGATIVE:%.*]], label [[OUT:%.*]]
151; CHECK:       negative:
152; CHECK-NEXT:    switch i32 [[S]], label [[OUT]] [
153; CHECK-NEXT:    i32 -2, label [[NEXT:%.*]]
154; CHECK-NEXT:    i32 -1, label [[NEXT]]
155; CHECK-NEXT:    ]
156; CHECK:       out:
157; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ -1, [[NEGATIVE]] ]
158; CHECK-NEXT:    ret i32 [[P]]
159; CHECK:       next:
160; CHECK-NEXT:    ret i32 0
161;
162entry:
163  %cmp = icmp slt i32 %s, 0
164  br i1 %cmp, label %negative, label %out
165
166negative:
167  switch i32 %s, label %out [
168  i32 0, label %out
169  i32 1, label %out
170  i32 -1, label %next
171  i32 -2, label %next
172  i32 2, label %out
173  i32 3, label %out
174  ]
175
176out:
177  %p = phi i32 [ 1, %entry ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ]
178  ret i32 %p
179
180next:
181  %q = phi i32 [ 0, %negative ], [ 0, %negative ]
182  ret i32 %q
183}
184
185define i32 @switch2(i32 %s) {
186; CHECK-LABEL: @switch2(
187; CHECK-NEXT:  entry:
188; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[S:%.*]], 0
189; CHECK-NEXT:    br i1 [[CMP]], label [[POSITIVE:%.*]], label [[OUT:%.*]]
190; CHECK:       positive:
191; CHECK-NEXT:    br label [[OUT]]
192; CHECK:       out:
193; CHECK-NEXT:    [[P:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 1, [[POSITIVE]] ]
194; CHECK-NEXT:    ret i32 [[P]]
195; CHECK:       next:
196; CHECK-NEXT:    ret i32 0
197;
198entry:
199  %cmp = icmp sgt i32 %s, 0
200  br i1 %cmp, label %positive, label %out
201
202positive:
203  switch i32 %s, label %out [
204  i32 0, label %out
205  i32 -1, label %next
206  i32 -2, label %next
207  ]
208
209out:
210  %p = phi i32 [ -1, %entry ], [ 1, %positive ], [ 1, %positive ]
211  ret i32 %p
212
213next:
214  %q = phi i32 [ 0, %positive ], [ 0, %positive ]
215  ret i32 %q
216}
217
218define i32 @switch3(i32 %s) {
219; CHECK-LABEL: @switch3(
220; CHECK-NEXT:  entry:
221; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[S:%.*]], 0
222; CHECK-NEXT:    br i1 [[CMP]], label [[POSITIVE:%.*]], label [[OUT:%.*]]
223; CHECK:       positive:
224; CHECK-NEXT:    br label [[OUT]]
225; CHECK:       out:
226; CHECK-NEXT:    [[P:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 1, [[POSITIVE]] ]
227; CHECK-NEXT:    ret i32 [[P]]
228; CHECK:       next:
229; CHECK-NEXT:    ret i32 0
230;
231entry:
232  %cmp = icmp sgt i32 %s, 0
233  br i1 %cmp, label %positive, label %out
234
235positive:
236  switch i32 %s, label %out [
237  i32 -1, label %out
238  i32 -2, label %next
239  i32 -3, label %next
240  ]
241
242out:
243  %p = phi i32 [ -1, %entry ], [ 1, %positive ], [ 1, %positive ]
244  ret i32 %p
245
246next:
247  %q = phi i32 [ 0, %positive ], [ 0, %positive ]
248  ret i32 %q
249}
250
251define void @switch4(i32 %s) {
252; CHECK-LABEL: @switch4(
253; CHECK-NEXT:  entry:
254; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[S:%.*]], 0
255; CHECK-NEXT:    br i1 [[CMP]], label [[ZERO:%.*]], label [[OUT:%.*]]
256; CHECK:       zero:
257; CHECK-NEXT:    br label [[NEXT:%.*]]
258; CHECK:       out:
259; CHECK-NEXT:    ret void
260; CHECK:       next:
261; CHECK-NEXT:    ret void
262;
263entry:
264  %cmp = icmp eq i32 %s, 0
265  br i1 %cmp, label %zero, label %out
266
267zero:
268  switch i32 %s, label %out [
269  i32 0, label %next
270  i32 1, label %out
271  i32 -1, label %out
272  ]
273
274out:
275  ret void
276
277next:
278  ret void
279}
280
281define i1 @arg_attribute(i8* nonnull %a) {
282; CHECK-LABEL: @arg_attribute(
283; CHECK-NEXT:    br label [[EXIT:%.*]]
284; CHECK:       exit:
285; CHECK-NEXT:    ret i1 false
286;
287  %cmp = icmp eq i8* %a, null
288  br label %exit
289
290exit:
291  ret i1 %cmp
292}
293
294declare nonnull i8* @return_nonnull()
295define i1 @call_attribute() {
296; CHECK-LABEL: @call_attribute(
297; CHECK-NEXT:    [[A:%.*]] = call i8* @return_nonnull()
298; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8* [[A]], null
299; CHECK-NEXT:    br label [[EXIT:%.*]]
300; CHECK:       exit:
301; CHECK-NEXT:    ret i1 false
302;
303  %a = call i8* @return_nonnull()
304  %cmp = icmp eq i8* %a, null
305  br label %exit
306
307exit:
308  ret i1 %cmp
309}
310
311define i1 @umin(i32 %a, i32 %b) {
312; CHECK-LABEL: @umin(
313; CHECK-NEXT:  entry:
314; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 5
315; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
316; CHECK:       a_guard:
317; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[B:%.*]], 20
318; CHECK-NEXT:    br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]]
319; CHECK:       b_guard:
320; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ult i32 [[A]], [[B]]
321; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
322; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[MIN]], 7
323; CHECK-NEXT:    br label [[NEXT:%.*]]
324; CHECK:       next:
325; CHECK-NEXT:    ret i1 false
326; CHECK:       out:
327; CHECK-NEXT:    ret i1 false
328;
329entry:
330  %cmp = icmp ult i32 %a, 5
331  br i1 %cmp, label %a_guard, label %out
332
333a_guard:
334  %cmp2 = icmp ult i32 %b, 20
335  br i1 %cmp2, label %b_guard, label %out
336
337b_guard:
338  %sel_cmp = icmp ult i32 %a, %b
339  %min = select i1 %sel_cmp, i32 %a, i32 %b
340  %res = icmp eq i32 %min, 7
341  br label %next
342next:
343  ret i1 %res
344out:
345  ret i1 false
346}
347
348define i1 @smin(i32 %a, i32 %b) {
349; CHECK-LABEL: @smin(
350; CHECK-NEXT:  entry:
351; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 5
352; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
353; CHECK:       a_guard:
354; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[B:%.*]], 20
355; CHECK-NEXT:    br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]]
356; CHECK:       b_guard:
357; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp sle i32 [[A]], [[B]]
358; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
359; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[MIN]], 7
360; CHECK-NEXT:    br label [[NEXT:%.*]]
361; CHECK:       next:
362; CHECK-NEXT:    ret i1 false
363; CHECK:       out:
364; CHECK-NEXT:    ret i1 false
365;
366entry:
367  %cmp = icmp ult i32 %a, 5
368  br i1 %cmp, label %a_guard, label %out
369
370a_guard:
371  %cmp2 = icmp ult i32 %b, 20
372  br i1 %cmp2, label %b_guard, label %out
373
374b_guard:
375  %sel_cmp = icmp sle i32 %a, %b
376  %min = select i1 %sel_cmp, i32 %a, i32 %b
377  %res = icmp eq i32 %min, 7
378  br label %next
379next:
380  ret i1 %res
381out:
382  ret i1 false
383}
384
385define i1 @smax(i32 %a, i32 %b) {
386; CHECK-LABEL: @smax(
387; CHECK-NEXT:  entry:
388; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5
389; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
390; CHECK:       a_guard:
391; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[B:%.*]], 20
392; CHECK-NEXT:    br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]]
393; CHECK:       b_guard:
394; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp sge i32 [[A]], [[B]]
395; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
396; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[MAX]], 7
397; CHECK-NEXT:    br label [[NEXT:%.*]]
398; CHECK:       next:
399; CHECK-NEXT:    ret i1 false
400; CHECK:       out:
401; CHECK-NEXT:    ret i1 false
402;
403entry:
404  %cmp = icmp sgt i32 %a, 5
405  br i1 %cmp, label %a_guard, label %out
406
407a_guard:
408  %cmp2 = icmp sgt i32 %b, 20
409  br i1 %cmp2, label %b_guard, label %out
410
411b_guard:
412  %sel_cmp = icmp sge i32 %a, %b
413  %max = select i1 %sel_cmp, i32 %a, i32 %b
414  %res = icmp eq i32 %max, 7
415  br label %next
416next:
417  ret i1 %res
418out:
419  ret i1 false
420}
421
422define i1 @umax(i32 %a, i32 %b) {
423; CHECK-LABEL: @umax(
424; CHECK-NEXT:  entry:
425; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5
426; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
427; CHECK:       a_guard:
428; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[B:%.*]], 20
429; CHECK-NEXT:    br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]]
430; CHECK:       b_guard:
431; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp uge i32 [[A]], [[B]]
432; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
433; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[MAX]], 7
434; CHECK-NEXT:    br label [[NEXT:%.*]]
435; CHECK:       next:
436; CHECK-NEXT:    ret i1 false
437; CHECK:       out:
438; CHECK-NEXT:    ret i1 false
439;
440entry:
441  %cmp = icmp sgt i32 %a, 5
442  br i1 %cmp, label %a_guard, label %out
443
444a_guard:
445  %cmp2 = icmp sgt i32 %b, 20
446  br i1 %cmp2, label %b_guard, label %out
447
448b_guard:
449  %sel_cmp = icmp uge i32 %a, %b
450  %max = select i1 %sel_cmp, i32 %a, i32 %b
451  %res = icmp eq i32 %max, 7
452  br label %next
453next:
454  ret i1 %res
455out:
456  ret i1 false
457}
458
459define i1 @clamp_low1(i32 %a) {
460; CHECK-LABEL: @clamp_low1(
461; CHECK-NEXT:  entry:
462; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5
463; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
464; CHECK:       a_guard:
465; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5
466; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[A]], -1
467; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[A]]
468; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[SEL]], 4
469; CHECK-NEXT:    br label [[NEXT:%.*]]
470; CHECK:       next:
471; CHECK-NEXT:    ret i1 false
472; CHECK:       out:
473; CHECK-NEXT:    ret i1 false
474;
475entry:
476  %cmp = icmp sge i32 %a, 5
477  br i1 %cmp, label %a_guard, label %out
478
479a_guard:
480  %sel_cmp = icmp eq i32 %a, 5
481  %add = add i32 %a, -1
482  %sel = select i1 %sel_cmp, i32 5, i32 %a
483  %res = icmp eq i32 %sel, 4
484  br label %next
485next:
486  ret i1 %res
487out:
488  ret i1 false
489}
490
491define i1 @clamp_low2(i32 %a) {
492; CHECK-LABEL: @clamp_low2(
493; CHECK-NEXT:  entry:
494; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5
495; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
496; CHECK:       a_guard:
497; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5
498; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[A]], -1
499; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 5
500; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[SEL]], 4
501; CHECK-NEXT:    br label [[NEXT:%.*]]
502; CHECK:       next:
503; CHECK-NEXT:    ret i1 false
504; CHECK:       out:
505; CHECK-NEXT:    ret i1 false
506;
507entry:
508  %cmp = icmp sge i32 %a, 5
509  br i1 %cmp, label %a_guard, label %out
510
511a_guard:
512  %sel_cmp = icmp ne i32 %a, 5
513  %add = add i32 %a, -1
514  %sel = select i1 %sel_cmp, i32 %a, i32 5
515  %res = icmp eq i32 %sel, 4
516  br label %next
517next:
518  ret i1 %res
519out:
520  ret i1 false
521}
522
523define i1 @clamp_high1(i32 %a) {
524; CHECK-LABEL: @clamp_high1(
525; CHECK-NEXT:  entry:
526; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5
527; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
528; CHECK:       a_guard:
529; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5
530; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[A]], 1
531; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[A]]
532; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[SEL]], 6
533; CHECK-NEXT:    br label [[NEXT:%.*]]
534; CHECK:       next:
535; CHECK-NEXT:    ret i1 false
536; CHECK:       out:
537; CHECK-NEXT:    ret i1 false
538;
539entry:
540  %cmp = icmp sle i32 %a, 5
541  br i1 %cmp, label %a_guard, label %out
542
543a_guard:
544  %sel_cmp = icmp eq i32 %a, 5
545  %add = add i32 %a, 1
546  %sel = select i1 %sel_cmp, i32 5, i32 %a
547  %res = icmp eq i32 %sel, 6
548  br label %next
549next:
550  ret i1 %res
551out:
552  ret i1 false
553}
554
555define i1 @clamp_high2(i32 %a) {
556; CHECK-LABEL: @clamp_high2(
557; CHECK-NEXT:  entry:
558; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5
559; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
560; CHECK:       a_guard:
561; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5
562; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[A]], 1
563; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 5
564; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[SEL]], 6
565; CHECK-NEXT:    br label [[NEXT:%.*]]
566; CHECK:       next:
567; CHECK-NEXT:    ret i1 false
568; CHECK:       out:
569; CHECK-NEXT:    ret i1 false
570;
571entry:
572  %cmp = icmp sle i32 %a, 5
573  br i1 %cmp, label %a_guard, label %out
574
575a_guard:
576  %sel_cmp = icmp ne i32 %a, 5
577  %add = add i32 %a, 1
578  %sel = select i1 %sel_cmp, i32 %a, i32 5
579  %res = icmp eq i32 %sel, 6
580  br label %next
581next:
582  ret i1 %res
583out:
584  ret i1 false
585}
586
587; Just showing arbitrary constants work, not really a clamp
588define i1 @clamp_high3(i32 %a) {
589; CHECK-LABEL: @clamp_high3(
590; CHECK-NEXT:  entry:
591; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5
592; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
593; CHECK:       a_guard:
594; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5
595; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[A]], 100
596; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 5
597; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[SEL]], 105
598; CHECK-NEXT:    br label [[NEXT:%.*]]
599; CHECK:       next:
600; CHECK-NEXT:    ret i1 false
601; CHECK:       out:
602; CHECK-NEXT:    ret i1 false
603;
604entry:
605  %cmp = icmp sle i32 %a, 5
606  br i1 %cmp, label %a_guard, label %out
607
608a_guard:
609  %sel_cmp = icmp ne i32 %a, 5
610  %add = add i32 %a, 100
611  %sel = select i1 %sel_cmp, i32 %a, i32 5
612  %res = icmp eq i32 %sel, 105
613  br label %next
614next:
615  ret i1 %res
616out:
617  ret i1 false
618}
619
620define i1 @zext_unknown(i8 %a) {
621; CHECK-LABEL: @zext_unknown(
622; CHECK-NEXT:  entry:
623; CHECK-NEXT:    [[A32:%.*]] = zext i8 [[A:%.*]] to i32
624; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A32]], 256
625; CHECK-NEXT:    br label [[EXIT:%.*]]
626; CHECK:       exit:
627; CHECK-NEXT:    ret i1 true
628;
629entry:
630  %a32 = zext i8 %a to i32
631  %cmp = icmp sle i32 %a32, 256
632  br label %exit
633exit:
634  ret i1 %cmp
635}
636
637define i1 @trunc_unknown(i32 %a) {
638; CHECK-LABEL: @trunc_unknown(
639; CHECK-NEXT:  entry:
640; CHECK-NEXT:    [[A8:%.*]] = trunc i32 [[A:%.*]] to i8
641; CHECK-NEXT:    [[A32:%.*]] = sext i8 [[A8]] to i32
642; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A32]], 128
643; CHECK-NEXT:    br label [[EXIT:%.*]]
644; CHECK:       exit:
645; CHECK-NEXT:    ret i1 true
646;
647entry:
648  %a8 = trunc i32 %a to i8
649  %a32 = sext i8 %a8 to i32
650  %cmp = icmp sle i32 %a32, 128
651  br label %exit
652exit:
653  ret i1 %cmp
654}
655
656; TODO: missed optimization
657; Make sure we exercise non-integer inputs to unary operators (i.e. crash check).
658define i1 @bitcast_unknown(float %a) {
659; CHECK-LABEL: @bitcast_unknown(
660; CHECK-NEXT:  entry:
661; CHECK-NEXT:    [[A32:%.*]] = bitcast float [[A:%.*]] to i32
662; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A32]], 128
663; CHECK-NEXT:    br label [[EXIT:%.*]]
664; CHECK:       exit:
665; CHECK-NEXT:    ret i1 [[CMP]]
666;
667entry:
668  %a32 = bitcast float %a to i32
669  %cmp = icmp sle i32 %a32, 128
670  br label %exit
671exit:
672  ret i1 %cmp
673}
674
675define i1 @bitcast_unknown2(i8* %p) {
676; CHECK-LABEL: @bitcast_unknown2(
677; CHECK-NEXT:  entry:
678; CHECK-NEXT:    [[P64:%.*]] = ptrtoint i8* [[P:%.*]] to i64
679; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i64 [[P64]], 128
680; CHECK-NEXT:    br label [[EXIT:%.*]]
681; CHECK:       exit:
682; CHECK-NEXT:    ret i1 [[CMP]]
683;
684entry:
685  %p64 = ptrtoint i8* %p to i64
686  %cmp = icmp sle i64 %p64, 128
687  br label %exit
688exit:
689  ret i1 %cmp
690}
691
692
693define i1 @and_unknown(i32 %a) {
694; CHECK-LABEL: @and_unknown(
695; CHECK-NEXT:  entry:
696; CHECK-NEXT:    [[AND:%.*]] = and i32 [[A:%.*]], 128
697; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[AND]], 128
698; CHECK-NEXT:    br label [[EXIT:%.*]]
699; CHECK:       exit:
700; CHECK-NEXT:    ret i1 true
701;
702entry:
703  %and = and i32 %a, 128
704  %cmp = icmp sle i32 %and, 128
705  br label %exit
706exit:
707  ret i1 %cmp
708}
709
710define i1 @lshr_unknown(i32 %a) {
711; CHECK-LABEL: @lshr_unknown(
712; CHECK-NEXT:  entry:
713; CHECK-NEXT:    [[AND:%.*]] = lshr i32 [[A:%.*]], 30
714; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[AND]], 128
715; CHECK-NEXT:    br label [[EXIT:%.*]]
716; CHECK:       exit:
717; CHECK-NEXT:    ret i1 true
718;
719entry:
720  %and = lshr i32 %a, 30
721  %cmp = icmp sle i32 %and, 128
722  br label %exit
723exit:
724  ret i1 %cmp
725}
726