xref: /llvm-project/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll (revision 1ca64c5fb74270661ca2f9ebd821f47dcb3152b4)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
3; PR2581
4
5define i32 @test1(i1 %C) {
6; CHECK-LABEL: define range(i32 10, 12) i32 @test1
7; CHECK-SAME: (i1 [[C:%.*]]) {
8; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[BODY:%.*]]
9; CHECK:       body:
10; CHECK-NEXT:    ret i32 11
11; CHECK:       exit:
12; CHECK-NEXT:    ret i32 10
13;
14  br i1 %C, label %exit, label %body
15
16body:           ; preds = %0
17  %A = select i1 %C, i32 10, i32 11
18  ret i32 %A
19
20exit:           ; preds = %0
21  ret i32 10
22}
23
24; PR4420
25declare i1 @ext()
26define i1 @test2() {
27; CHECK-LABEL: define i1 @test2() {
28; CHECK-NEXT:  entry:
29; CHECK-NEXT:    [[COND:%.*]] = tail call i1 @ext()
30; CHECK-NEXT:    br i1 [[COND]], label [[BB1:%.*]], label [[BB2:%.*]]
31; CHECK:       bb1:
32; CHECK-NEXT:    [[COND2:%.*]] = tail call i1 @ext()
33; CHECK-NEXT:    br i1 [[COND2]], label [[BB3:%.*]], label [[BB2]]
34; CHECK:       bb2:
35; CHECK-NEXT:    ret i1 false
36; CHECK:       bb3:
37; CHECK-NEXT:    [[RES:%.*]] = tail call i1 @ext()
38; CHECK-NEXT:    ret i1 [[RES]]
39;
40entry:
41  %cond = tail call i1 @ext()
42  br i1 %cond, label %bb1, label %bb2
43
44bb1:
45  %cond2 = tail call i1 @ext()
46  br i1 %cond2, label %bb3, label %bb2
47
48bb2:
49  %cond_merge = phi i1 [ %cond, %entry ], [ false, %bb1 ]
50  ret i1 %cond_merge
51
52bb3:
53  %res = tail call i1 @ext()
54  ret i1 %res
55}
56
57; PR4855
58@gv = internal constant i8 7
59define i8 @test3(ptr %a) nounwind {
60; CHECK-LABEL: define i8 @test3
61; CHECK-SAME: (ptr [[A:%.*]]) #[[ATTR0:[0-9]+]] {
62; CHECK-NEXT:  entry:
63; CHECK-NEXT:    [[COND:%.*]] = icmp eq ptr [[A]], @gv
64; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB:%.*]]
65; CHECK:       bb:
66; CHECK-NEXT:    ret i8 0
67; CHECK:       bb2:
68; CHECK-NEXT:    [[SHOULD_BE_CONST:%.*]] = load i8, ptr [[A]], align 1
69; CHECK-NEXT:    ret i8 [[SHOULD_BE_CONST]]
70;
71entry:
72  %cond = icmp eq ptr %a, @gv
73  br i1 %cond, label %bb2, label %bb
74
75bb:
76  ret i8 0
77
78bb2:
79  %should_be_const = load i8, ptr %a
80  ret i8 %should_be_const
81}
82
83; PR1757
84define i32 @test4(i32) {
85; CHECK-LABEL: define range(i32 0, 3) i32 @test4
86; CHECK-SAME: (i32 [[TMP0:%.*]]) {
87; CHECK-NEXT:  EntryBlock:
88; CHECK-NEXT:    [[DOTDEMORGAN:%.*]] = icmp sgt i32 [[TMP0]], 2
89; CHECK-NEXT:    br i1 [[DOTDEMORGAN]], label [[GREATERTHANTWO:%.*]], label [[LESSTHANOREQUALTOTWO:%.*]]
90; CHECK:       GreaterThanTwo:
91; CHECK-NEXT:    br i1 false, label [[IMPOSSIBLE:%.*]], label [[NOTTWOANDGREATERTHANTWO:%.*]]
92; CHECK:       NotTwoAndGreaterThanTwo:
93; CHECK-NEXT:    ret i32 2
94; CHECK:       Impossible:
95; CHECK-NEXT:    ret i32 1
96; CHECK:       LessThanOrEqualToTwo:
97; CHECK-NEXT:    ret i32 0
98;
99EntryBlock:
100  %.demorgan = icmp sgt i32 %0, 2
101  br i1 %.demorgan, label %GreaterThanTwo, label %LessThanOrEqualToTwo
102
103GreaterThanTwo:
104  icmp eq i32 %0, 2
105  br i1 %1, label %Impossible, label %NotTwoAndGreaterThanTwo
106
107NotTwoAndGreaterThanTwo:
108  ret i32 2
109
110Impossible:
111  ret i32 1
112
113LessThanOrEqualToTwo:
114  ret i32 0
115}
116
117declare ptr @f(ptr)
118define void @test5(ptr %x, ptr %y) {
119; CHECK-LABEL: define void @test5
120; CHECK-SAME: (ptr [[X:%.*]], ptr [[Y:%.*]]) {
121; CHECK-NEXT:  entry:
122; CHECK-NEXT:    [[PRE:%.*]] = icmp eq ptr [[X]], null
123; CHECK-NEXT:    br i1 [[PRE]], label [[RETURN:%.*]], label [[LOOP:%.*]]
124; CHECK:       loop:
125; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[F:%.*]], [[LOOP]] ], [ [[X]], [[ENTRY:%.*]] ]
126; CHECK-NEXT:    [[F]] = tail call ptr @f(ptr [[PHI]])
127; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne ptr [[F]], [[Y]]
128; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], ptr [[F]], ptr null
129; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq ptr [[SEL]], null
130; CHECK-NEXT:    br i1 [[CMP2]], label [[RETURN]], label [[LOOP]]
131; CHECK:       return:
132; CHECK-NEXT:    ret void
133;
134entry:
135  %pre = icmp eq ptr %x, null
136  br i1 %pre, label %return, label %loop
137
138loop:
139  %phi = phi ptr [ %sel, %loop ], [ %x, %entry ]
140  %f = tail call ptr @f(ptr %phi)
141  %cmp1 = icmp ne ptr %f, %y
142  %sel = select i1 %cmp1, ptr %f, ptr null
143  %cmp2 = icmp eq ptr %sel, null
144  br i1 %cmp2, label %return, label %loop
145
146return:
147  ret void
148}
149
150; "false" case for CorrelatedValuePropagation
151define void @loop1(ptr %x, ptr %y) {
152; CHECK-LABEL: define void @loop1
153; CHECK-SAME: (ptr [[X:%.*]], ptr [[Y:%.*]]) {
154; CHECK-NEXT:  entry:
155; CHECK-NEXT:    br label [[LOOP:%.*]]
156; CHECK:       loop:
157; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[F:%.*]], [[LOOP]] ], [ [[X]], [[ENTRY:%.*]] ]
158; CHECK-NEXT:    [[F]] = tail call ptr @f(ptr [[PHI]])
159; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne ptr [[F]], [[Y]]
160; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], ptr [[F]], ptr null
161; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq ptr [[SEL]], null
162; CHECK-NEXT:    br i1 [[CMP2]], label [[RETURN:%.*]], label [[LOOP]]
163; CHECK:       return:
164; CHECK-NEXT:    ret void
165;
166entry:
167  br label %loop
168
169loop:
170  %phi = phi ptr [ %sel, %loop ], [ %x, %entry ]
171  %f = tail call ptr @f(ptr %phi)
172  %cmp1 = icmp ne ptr %f, %y
173  %sel = select i1 %cmp1, ptr %f, ptr null
174  %cmp2 = icmp eq ptr %sel, null
175  br i1 %cmp2, label %return, label %loop
176
177return:
178  ret void
179}
180
181; "true" case for CorrelatedValuePropagation
182define void @loop2(ptr %x, ptr %y) {
183; CHECK-LABEL: define void @loop2
184; CHECK-SAME: (ptr [[X:%.*]], ptr [[Y:%.*]]) {
185; CHECK-NEXT:  entry:
186; CHECK-NEXT:    br label [[LOOP:%.*]]
187; CHECK:       loop:
188; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[F:%.*]], [[LOOP]] ], [ [[X]], [[ENTRY:%.*]] ]
189; CHECK-NEXT:    [[F]] = tail call ptr @f(ptr [[PHI]])
190; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq ptr [[F]], [[Y]]
191; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], ptr null, ptr [[F]]
192; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq ptr [[SEL]], null
193; CHECK-NEXT:    br i1 [[CMP2]], label [[RETURN:%.*]], label [[LOOP]]
194; CHECK:       return:
195; CHECK-NEXT:    ret void
196;
197entry:
198  br label %loop
199
200loop:
201  %phi = phi ptr [ %sel, %loop ], [ %x, %entry ]
202  %f = tail call ptr @f(ptr %phi)
203  %cmp1 = icmp eq ptr %f, %y
204  %sel = select i1 %cmp1, ptr null, ptr %f
205  %cmp2 = icmp eq ptr %sel, null
206  br i1 %cmp2, label %return, label %loop
207
208return:
209  ret void
210}
211
212define i32 @switch1(i32 %s) {
213; CHECK-LABEL: define range(i32 -1, 2) i32 @switch1
214; CHECK-SAME: (i32 [[S:%.*]]) {
215; CHECK-NEXT:  entry:
216; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[S]], 0
217; CHECK-NEXT:    br i1 [[CMP]], label [[NEGATIVE:%.*]], label [[OUT:%.*]]
218; CHECK:       negative:
219; CHECK-NEXT:    switch i32 [[S]], label [[OUT]] [
220; CHECK-NEXT:      i32 -2, label [[NEXT:%.*]]
221; CHECK-NEXT:      i32 -1, label [[NEXT]]
222; CHECK-NEXT:    ]
223; CHECK:       out:
224; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ -1, [[NEGATIVE]] ]
225; CHECK-NEXT:    ret i32 [[P]]
226; CHECK:       next:
227; CHECK-NEXT:    ret i32 0
228;
229entry:
230  %cmp = icmp slt i32 %s, 0
231  br i1 %cmp, label %negative, label %out
232
233negative:
234  switch i32 %s, label %out [
235  i32 0, label %out
236  i32 1, label %out
237  i32 -1, label %next
238  i32 -2, label %next
239  i32 2, label %out
240  i32 3, label %out
241  ]
242
243out:
244  %p = phi i32 [ 1, %entry ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ]
245  ret i32 %p
246
247next:
248  %q = phi i32 [ 0, %negative ], [ 0, %negative ]
249  ret i32 %q
250}
251
252define i32 @switch2(i32 %s) {
253; CHECK-LABEL: define range(i32 -1, 2) i32 @switch2
254; CHECK-SAME: (i32 [[S:%.*]]) {
255; CHECK-NEXT:  entry:
256; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[S]], 0
257; CHECK-NEXT:    br i1 [[CMP]], label [[POSITIVE:%.*]], label [[OUT:%.*]]
258; CHECK:       positive:
259; CHECK-NEXT:    br label [[OUT]]
260; CHECK:       out:
261; CHECK-NEXT:    [[P:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 1, [[POSITIVE]] ]
262; CHECK-NEXT:    ret i32 [[P]]
263; CHECK:       next:
264; CHECK-NEXT:    ret i32 0
265;
266entry:
267  %cmp = icmp sgt i32 %s, 0
268  br i1 %cmp, label %positive, label %out
269
270positive:
271  switch i32 %s, label %out [
272  i32 0, label %out
273  i32 -1, label %next
274  i32 -2, label %next
275  ]
276
277out:
278  %p = phi i32 [ -1, %entry ], [ 1, %positive ], [ 1, %positive ]
279  ret i32 %p
280
281next:
282  %q = phi i32 [ 0, %positive ], [ 0, %positive ]
283  ret i32 %q
284}
285
286define i32 @switch3(i32 %s) {
287; CHECK-LABEL: define range(i32 -1, 2) i32 @switch3
288; CHECK-SAME: (i32 [[S:%.*]]) {
289; CHECK-NEXT:  entry:
290; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[S]], 0
291; CHECK-NEXT:    br i1 [[CMP]], label [[POSITIVE:%.*]], label [[OUT:%.*]]
292; CHECK:       positive:
293; CHECK-NEXT:    br label [[OUT]]
294; CHECK:       out:
295; CHECK-NEXT:    [[P:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 1, [[POSITIVE]] ]
296; CHECK-NEXT:    ret i32 [[P]]
297; CHECK:       next:
298; CHECK-NEXT:    ret i32 0
299;
300entry:
301  %cmp = icmp sgt i32 %s, 0
302  br i1 %cmp, label %positive, label %out
303
304positive:
305  switch i32 %s, label %out [
306  i32 -1, label %out
307  i32 -2, label %next
308  i32 -3, label %next
309  ]
310
311out:
312  %p = phi i32 [ -1, %entry ], [ 1, %positive ], [ 1, %positive ]
313  ret i32 %p
314
315next:
316  %q = phi i32 [ 0, %positive ], [ 0, %positive ]
317  ret i32 %q
318}
319
320define void @switch4(i32 %s) {
321; CHECK-LABEL: define void @switch4
322; CHECK-SAME: (i32 [[S:%.*]]) {
323; CHECK-NEXT:  entry:
324; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[S]], 0
325; CHECK-NEXT:    br i1 [[CMP]], label [[ZERO:%.*]], label [[OUT:%.*]]
326; CHECK:       zero:
327; CHECK-NEXT:    br label [[NEXT:%.*]]
328; CHECK:       out:
329; CHECK-NEXT:    ret void
330; CHECK:       next:
331; CHECK-NEXT:    ret void
332;
333entry:
334  %cmp = icmp eq i32 %s, 0
335  br i1 %cmp, label %zero, label %out
336
337zero:
338  switch i32 %s, label %out [
339  i32 0, label %next
340  i32 1, label %out
341  i32 -1, label %out
342  ]
343
344out:
345  ret void
346
347next:
348  ret void
349}
350
351define void @switch_nonzero_zext(i8 %s) {
352; CHECK-LABEL: define void @switch_nonzero_zext
353; CHECK-SAME: (i8 [[S:%.*]]) {
354; CHECK-NEXT:  entry:
355; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[S]], 0
356; CHECK-NEXT:    br i1 [[CMP]], label [[SWITCH:%.*]], label [[EXIT:%.*]]
357; CHECK:       switch:
358; CHECK-NEXT:    [[S_EXT:%.*]] = zext i8 [[S]] to i32
359; CHECK-NEXT:    br label [[EXIT]]
360; CHECK:       exit:
361; CHECK-NEXT:    ret void
362; CHECK:       unreachable:
363; CHECK-NEXT:    ret void
364;
365entry:
366  %cmp = icmp ne i8 %s, 0
367  br i1 %cmp, label %switch, label %exit
368
369switch:
370  %s.ext = zext i8 %s to i32
371  switch i32 %s.ext, label %exit [
372  i32 0, label %unreachable
373  i32 1, label %exit
374  i32 -1, label %exit
375  ]
376
377exit:
378  ret void
379
380unreachable:
381  ret void
382}
383
384define void @switch_assume_nonzero(i32 %s) {
385; CHECK-LABEL: define void @switch_assume_nonzero
386; CHECK-SAME: (i32 [[S:%.*]]) {
387; CHECK-NEXT:  entry:
388; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[S]], 0
389; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
390; CHECK-NEXT:    br label [[EXIT:%.*]]
391; CHECK:       exit:
392; CHECK-NEXT:    ret void
393; CHECK:       unreachable:
394; CHECK-NEXT:    ret void
395;
396entry:
397  %cmp = icmp ne i32 %s, 0
398  call void @llvm.assume(i1 %cmp)
399  switch i32 %s, label %exit [
400  i32 0, label %unreachable
401  i32 1, label %exit
402  i32 -1, label %exit
403  ]
404
405exit:
406  ret void
407
408unreachable:
409  ret void
410}
411
412define void @switch_nonzero_phi(i1 %cond) {
413; CHECK-LABEL: define void @switch_nonzero_phi
414; CHECK-SAME: (i1 [[COND:%.*]]) {
415; CHECK-NEXT:  entry:
416; CHECK-NEXT:    br i1 [[COND]], label [[IF:%.*]], label [[ELSE:%.*]]
417; CHECK:       if:
418; CHECK-NEXT:    br label [[SWITCH:%.*]]
419; CHECK:       else:
420; CHECK-NEXT:    br label [[SWITCH]]
421; CHECK:       switch:
422; CHECK-NEXT:    [[S:%.*]] = phi i32 [ 1, [[IF]] ], [ -1, [[ELSE]] ]
423; CHECK-NEXT:    br label [[EXIT:%.*]]
424; CHECK:       exit:
425; CHECK-NEXT:    ret void
426; CHECK:       unreachable:
427; CHECK-NEXT:    ret void
428;
429entry:
430  br i1 %cond, label %if, label %else
431
432if:
433  br label %switch
434
435else:
436  br label %switch
437
438switch:
439  %s = phi i32 [ 1, %if ], [ -1, %else ]
440  switch i32 %s, label %exit [
441  i32 0, label %unreachable
442  i32 1, label %exit
443  i32 -1, label %exit
444  ]
445
446exit:
447  ret void
448
449unreachable:
450  ret void
451}
452
453define i32 @switch_range(i32 %cond) {
454; CHECK-LABEL: define range(i32 1, 3) i32 @switch_range
455; CHECK-SAME: (i32 [[COND:%.*]]) {
456; CHECK-NEXT:  entry:
457; CHECK-NEXT:    [[S:%.*]] = urem i32 [[COND]], 3
458; CHECK-NEXT:    [[S1:%.*]] = add nuw nsw i32 [[S]], 1
459; CHECK-NEXT:    switch i32 [[S1]], label [[DEFAULT_UNREACHABLE:%.*]] [
460; CHECK-NEXT:      i32 1, label [[EXIT1:%.*]]
461; CHECK-NEXT:      i32 2, label [[EXIT2:%.*]]
462; CHECK-NEXT:      i32 3, label [[EXIT1]]
463; CHECK-NEXT:    ]
464; CHECK:       exit1:
465; CHECK-NEXT:    ret i32 1
466; CHECK:       exit2:
467; CHECK-NEXT:    ret i32 2
468; CHECK:       default.unreachable:
469; CHECK-NEXT:    unreachable
470; CHECK:       unreachable:
471; CHECK-NEXT:    ret i32 0
472;
473entry:
474  %s = urem i32 %cond, 3
475  %s1 = add i32 %s, 1
476  switch i32 %s1, label %unreachable [
477  i32 1, label %exit1
478  i32 2, label %exit2
479  i32 3, label %exit1
480  ]
481
482exit1:
483  ret i32 1
484exit2:
485  ret i32 2
486unreachable:
487  ret i32 0
488}
489
490; If the cases do not cover the entire range of the
491; switch condition, we should not change the default.
492
493define i32 @switch_range_not_full(i32 %cond) {
494; CHECK-LABEL: define range(i32 0, 3) i32 @switch_range_not_full
495; CHECK-SAME: (i32 [[COND:%.*]]) {
496; CHECK-NEXT:  entry:
497; CHECK-NEXT:    [[S:%.*]] = urem i32 [[COND]], 3
498; CHECK-NEXT:    [[S1:%.*]] = add nuw nsw i32 [[S]], 1
499; CHECK-NEXT:    switch i32 [[S1]], label [[UNREACHABLE:%.*]] [
500; CHECK-NEXT:      i32 1, label [[EXIT1:%.*]]
501; CHECK-NEXT:      i32 3, label [[EXIT2:%.*]]
502; CHECK-NEXT:    ]
503; CHECK:       exit1:
504; CHECK-NEXT:    ret i32 1
505; CHECK:       exit2:
506; CHECK-NEXT:    ret i32 2
507; CHECK:       unreachable:
508; CHECK-NEXT:    ret i32 0
509;
510entry:
511  %s = urem i32 %cond, 3
512  %s1 = add i32 %s, 1
513  switch i32 %s1, label %unreachable [
514  i32 1, label %exit1
515  i32 3, label %exit2
516  ]
517
518exit1:
519  ret i32 1
520exit2:
521  ret i32 2
522unreachable:
523  ret i32 0
524}
525
526; PR51531
527
528define i8 @switch_defaultdest_multipleuse(i8 %t0) {
529; CHECK-LABEL: define i8 @switch_defaultdest_multipleuse
530; CHECK-SAME: (i8 [[T0:%.*]]) {
531; CHECK-NEXT:  entry:
532; CHECK-NEXT:    [[O:%.*]] = or i8 [[T0]], 1
533; CHECK-NEXT:    [[R:%.*]] = srem i8 1, [[O]]
534; CHECK-NEXT:    br label [[EXIT:%.*]]
535; CHECK:       default.unreachable:
536; CHECK-NEXT:    unreachable
537; CHECK:       exit:
538; CHECK-NEXT:    ret i8 0
539;
540entry:
541  %o = or i8 %t0, 1
542  %r = srem i8 1, %o
543  switch i8 %r, label %exit [
544  i8 0, label %exit
545  i8 1, label %exit
546  ]
547
548exit:
549  ret i8 0
550}
551
552define i1 @arg_attribute(ptr nonnull %a) {
553; CHECK-LABEL: define i1 @arg_attribute
554; CHECK-SAME: (ptr nonnull [[A:%.*]]) {
555; CHECK-NEXT:    ret i1 false
556;
557  %cmp = icmp eq ptr %a, null
558  ret i1 %cmp
559}
560
561declare nonnull ptr @return_nonnull()
562define i1 @call_attribute() {
563; CHECK-LABEL: define i1 @call_attribute() {
564; CHECK-NEXT:    [[A:%.*]] = call ptr @return_nonnull()
565; CHECK-NEXT:    ret i1 false
566;
567  %a = call ptr @return_nonnull()
568  %cmp = icmp eq ptr %a, null
569  ret i1 %cmp
570}
571
572define i1 @umin(i32 %a, i32 %b) {
573; CHECK-LABEL: define i1 @umin
574; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
575; CHECK-NEXT:  entry:
576; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A]], 5
577; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
578; CHECK:       a_guard:
579; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[B]], 20
580; CHECK-NEXT:    br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]]
581; CHECK:       b_guard:
582; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp samesign ult i32 [[A]], [[B]]
583; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
584; CHECK-NEXT:    ret i1 false
585; CHECK:       out:
586; CHECK-NEXT:    ret i1 false
587;
588entry:
589  %cmp = icmp ult i32 %a, 5
590  br i1 %cmp, label %a_guard, label %out
591
592a_guard:
593  %cmp2 = icmp ult i32 %b, 20
594  br i1 %cmp2, label %b_guard, label %out
595
596b_guard:
597  %sel_cmp = icmp ult i32 %a, %b
598  %min = select i1 %sel_cmp, i32 %a, i32 %b
599  %res = icmp eq i32 %min, 7
600  ret i1 %res
601out:
602  ret i1 false
603}
604
605define i1 @smin(i32 %a, i32 %b) {
606; CHECK-LABEL: define i1 @smin
607; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
608; CHECK-NEXT:  entry:
609; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A]], 5
610; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
611; CHECK:       a_guard:
612; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[B]], 20
613; CHECK-NEXT:    br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]]
614; CHECK:       b_guard:
615; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp samesign ule i32 [[A]], [[B]]
616; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
617; CHECK-NEXT:    ret i1 false
618; CHECK:       out:
619; CHECK-NEXT:    ret i1 false
620;
621entry:
622  %cmp = icmp ult i32 %a, 5
623  br i1 %cmp, label %a_guard, label %out
624
625a_guard:
626  %cmp2 = icmp ult i32 %b, 20
627  br i1 %cmp2, label %b_guard, label %out
628
629b_guard:
630  %sel_cmp = icmp sle i32 %a, %b
631  %min = select i1 %sel_cmp, i32 %a, i32 %b
632  %res = icmp eq i32 %min, 7
633  ret i1 %res
634out:
635  ret i1 false
636}
637
638define i1 @smax(i32 %a, i32 %b) {
639; CHECK-LABEL: define i1 @smax
640; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
641; CHECK-NEXT:  entry:
642; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], 5
643; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
644; CHECK:       a_guard:
645; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[B]], 20
646; CHECK-NEXT:    br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]]
647; CHECK:       b_guard:
648; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp samesign uge i32 [[A]], [[B]]
649; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
650; CHECK-NEXT:    ret i1 false
651; CHECK:       out:
652; CHECK-NEXT:    ret i1 false
653;
654entry:
655  %cmp = icmp sgt i32 %a, 5
656  br i1 %cmp, label %a_guard, label %out
657
658a_guard:
659  %cmp2 = icmp sgt i32 %b, 20
660  br i1 %cmp2, label %b_guard, label %out
661
662b_guard:
663  %sel_cmp = icmp sge i32 %a, %b
664  %max = select i1 %sel_cmp, i32 %a, i32 %b
665  %res = icmp eq i32 %max, 7
666  ret i1 %res
667out:
668  ret i1 false
669}
670
671define i1 @umax(i32 %a, i32 %b) {
672; CHECK-LABEL: define i1 @umax
673; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
674; CHECK-NEXT:  entry:
675; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], 5
676; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
677; CHECK:       a_guard:
678; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[B]], 20
679; CHECK-NEXT:    br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]]
680; CHECK:       b_guard:
681; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp samesign uge i32 [[A]], [[B]]
682; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
683; CHECK-NEXT:    ret i1 false
684; CHECK:       out:
685; CHECK-NEXT:    ret i1 false
686;
687entry:
688  %cmp = icmp sgt i32 %a, 5
689  br i1 %cmp, label %a_guard, label %out
690
691a_guard:
692  %cmp2 = icmp sgt i32 %b, 20
693  br i1 %cmp2, label %b_guard, label %out
694
695b_guard:
696  %sel_cmp = icmp uge i32 %a, %b
697  %max = select i1 %sel_cmp, i32 %a, i32 %b
698  %res = icmp eq i32 %max, 7
699  ret i1 %res
700out:
701  ret i1 false
702}
703
704define i1 @umin_lhs_overdefined_rhs_const(i32 %a) {
705; CHECK-LABEL: define i1 @umin_lhs_overdefined_rhs_const
706; CHECK-SAME: (i32 [[A:%.*]]) {
707; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A]], 42
708; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[A]], i32 42
709; CHECK-NEXT:    ret i1 true
710;
711  %cmp = icmp ult i32 %a, 42
712  %sel = select i1 %cmp, i32 %a, i32 42
713  %cmp2 = icmp ule i32 %sel, 42
714  ret i1 %cmp2
715}
716
717define i1 @umin_rhs_overdefined_lhs_const(i32 %a) {
718; CHECK-LABEL: define i1 @umin_rhs_overdefined_lhs_const
719; CHECK-SAME: (i32 [[A:%.*]]) {
720; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[A]], 42
721; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 42, i32 [[A]]
722; CHECK-NEXT:    ret i1 true
723;
724  %cmp = icmp uge i32 %a, 42
725  %sel = select i1 %cmp, i32 42, i32 %a
726  %cmp2 = icmp ule i32 %sel, 42
727  ret i1 %cmp2
728}
729
730define i1 @umin_lhs_overdefined_rhs_range(i32 %a, i32 %b) {
731; CHECK-LABEL: define i1 @umin_lhs_overdefined_rhs_range
732; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
733; CHECK-NEXT:    [[ASSUME:%.*]] = icmp ult i32 [[B]], 42
734; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME]])
735; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A]], [[B]]
736; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[B]]
737; CHECK-NEXT:    ret i1 true
738;
739  %assume = icmp ult i32 %b, 42
740  call void @llvm.assume(i1 %assume)
741  %cmp = icmp ult i32 %a, %b
742  %sel = select i1 %cmp, i32 %a, i32 %b
743  %cmp2 = icmp ult i32 %sel, 42
744  ret i1 %cmp2
745}
746
747define i1 @umin_rhs_overdefined_lhs_range(i32 %a, i32 %b) {
748; CHECK-LABEL: define i1 @umin_rhs_overdefined_lhs_range
749; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
750; CHECK-NEXT:    [[ASSUME:%.*]] = icmp ult i32 [[B]], 42
751; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME]])
752; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[A]], [[B]]
753; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[B]], i32 [[A]]
754; CHECK-NEXT:    ret i1 true
755;
756  %assume = icmp ult i32 %b, 42
757  call void @llvm.assume(i1 %assume)
758  %cmp = icmp uge i32 %a, %b
759  %sel = select i1 %cmp, i32 %b, i32 %a
760  %cmp2 = icmp ult i32 %sel, 42
761  ret i1 %cmp2
762}
763
764define i1 @clamp_low1(i32 noundef %a) {
765; CHECK-LABEL: define i1 @clamp_low1
766; CHECK-SAME: (i32 noundef [[A:%.*]]) {
767; CHECK-NEXT:  entry:
768; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A]], 5
769; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
770; CHECK:       a_guard:
771; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5
772; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], -1
773; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]]
774; CHECK-NEXT:    ret i1 false
775; CHECK:       out:
776; CHECK-NEXT:    ret i1 false
777;
778entry:
779  %cmp = icmp sge i32 %a, 5
780  br i1 %cmp, label %a_guard, label %out
781
782a_guard:
783  %sel_cmp = icmp eq i32 %a, 5
784  %add = add i32 %a, -1
785  %sel = select i1 %sel_cmp, i32 5, i32 %add
786  %res = icmp eq i32 %sel, 4
787  ret i1 %res
788out:
789  ret i1 false
790}
791
792define i1 @clamp_low2(i32 noundef %a) {
793; CHECK-LABEL: define i1 @clamp_low2
794; CHECK-SAME: (i32 noundef [[A:%.*]]) {
795; CHECK-NEXT:  entry:
796; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A]], 5
797; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
798; CHECK:       a_guard:
799; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5
800; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], -1
801; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5
802; CHECK-NEXT:    ret i1 false
803; CHECK:       out:
804; CHECK-NEXT:    ret i1 false
805;
806entry:
807  %cmp = icmp sge i32 %a, 5
808  br i1 %cmp, label %a_guard, label %out
809
810a_guard:
811  %sel_cmp = icmp ne i32 %a, 5
812  %add = add i32 %a, -1
813  %sel = select i1 %sel_cmp, i32 %add, i32 5
814  %res = icmp eq i32 %sel, 4
815  ret i1 %res
816out:
817  ret i1 false
818}
819
820define i1 @clamp_low3(i32 noundef %a) {
821; CHECK-LABEL: define i1 @clamp_low3
822; CHECK-SAME: (i32 noundef [[A:%.*]]) {
823; CHECK-NEXT:  entry:
824; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A]], 5
825; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
826; CHECK:       a_guard:
827; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp samesign ugt i32 [[A]], 5
828; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], -1
829; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5
830; CHECK-NEXT:    ret i1 false
831; CHECK:       out:
832; CHECK-NEXT:    ret i1 false
833;
834entry:
835  %cmp = icmp sge i32 %a, 5
836  br i1 %cmp, label %a_guard, label %out
837
838a_guard:
839  %sel_cmp = icmp sgt i32 %a, 5
840  %add = add i32 %a, -1
841  %sel = select i1 %sel_cmp, i32 %add, i32 5
842  %res = icmp eq i32 %sel, 4
843  ret i1 %res
844out:
845  ret i1 false
846}
847
848define i1 @clamp_low4(i32 noundef %a) {
849; CHECK-LABEL: define i1 @clamp_low4
850; CHECK-SAME: (i32 noundef [[A:%.*]]) {
851; CHECK-NEXT:  entry:
852; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A]], 5
853; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
854; CHECK:       a_guard:
855; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp samesign ule i32 [[A]], 5
856; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], -1
857; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]]
858; CHECK-NEXT:    ret i1 false
859; CHECK:       out:
860; CHECK-NEXT:    ret i1 false
861;
862entry:
863  %cmp = icmp sge i32 %a, 5
864  br i1 %cmp, label %a_guard, label %out
865
866a_guard:
867  %sel_cmp = icmp sle i32 %a, 5
868  %add = add i32 %a, -1
869  %sel = select i1 %sel_cmp, i32 5, i32 %add
870  %res = icmp eq i32 %sel, 4
871  ret i1 %res
872out:
873  ret i1 false
874}
875
876define i1 @clamp_high1(i32 noundef %a) {
877; CHECK-LABEL: define i1 @clamp_high1
878; CHECK-SAME: (i32 noundef [[A:%.*]]) {
879; CHECK-NEXT:  entry:
880; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A]], 5
881; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
882; CHECK:       a_guard:
883; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5
884; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
885; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]]
886; CHECK-NEXT:    ret i1 false
887; CHECK:       out:
888; CHECK-NEXT:    ret i1 false
889;
890entry:
891  %cmp = icmp sle i32 %a, 5
892  br i1 %cmp, label %a_guard, label %out
893
894a_guard:
895  %sel_cmp = icmp eq i32 %a, 5
896  %add = add i32 %a, 1
897  %sel = select i1 %sel_cmp, i32 5, i32 %add
898  %res = icmp eq i32 %sel, 6
899  ret i1 %res
900out:
901  ret i1 false
902}
903
904define i1 @clamp_high1_or(i32 noundef %a) {
905; CHECK-LABEL: define i1 @clamp_high1_or
906; CHECK-SAME: (i32 noundef [[A:%.*]]) {
907; CHECK-NEXT:  entry:
908; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A]], 5
909; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
910; CHECK:       a_guard:
911; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5
912; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i32 [[A]], 1
913; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]]
914; CHECK-NEXT:    ret i1 false
915; CHECK:       out:
916; CHECK-NEXT:    ret i1 false
917;
918entry:
919  %cmp = icmp sle i32 %a, 5
920  br i1 %cmp, label %a_guard, label %out
921
922a_guard:
923  %sel_cmp = icmp eq i32 %a, 5
924  %add = or disjoint i32 %a, 1
925  %sel = select i1 %sel_cmp, i32 5, i32 %add
926  %res = icmp eq i32 %sel, 6
927  ret i1 %res
928out:
929  ret i1 false
930}
931
932define i1 @clamp_high2(i32 noundef %a) {
933; CHECK-LABEL: define i1 @clamp_high2
934; CHECK-SAME: (i32 noundef [[A:%.*]]) {
935; CHECK-NEXT:  entry:
936; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A]], 5
937; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
938; CHECK:       a_guard:
939; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5
940; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
941; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5
942; CHECK-NEXT:    ret i1 false
943; CHECK:       out:
944; CHECK-NEXT:    ret i1 false
945;
946entry:
947  %cmp = icmp sle i32 %a, 5
948  br i1 %cmp, label %a_guard, label %out
949
950a_guard:
951  %sel_cmp = icmp ne i32 %a, 5
952  %add = add i32 %a, 1
953  %sel = select i1 %sel_cmp, i32 %add, i32 5
954  %res = icmp eq i32 %sel, 6
955  ret i1 %res
956out:
957  ret i1 false
958}
959
960
961define i1 @clamp_high2_or_disjoint(i32 noundef %a) {
962; CHECK-LABEL: define i1 @clamp_high2_or_disjoint
963; CHECK-SAME: (i32 noundef [[A:%.*]]) {
964; CHECK-NEXT:  entry:
965; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A]], 5
966; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
967; CHECK:       a_guard:
968; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5
969; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i32 [[A]], 1
970; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5
971; CHECK-NEXT:    ret i1 false
972; CHECK:       out:
973; CHECK-NEXT:    ret i1 false
974;
975entry:
976  %cmp = icmp sle i32 %a, 5
977  br i1 %cmp, label %a_guard, label %out
978
979a_guard:
980  %sel_cmp = icmp ne i32 %a, 5
981  %add = or disjoint i32 %a, 1
982  %sel = select i1 %sel_cmp, i32 %add, i32 5
983  %res = icmp eq i32 %sel, 6
984  ret i1 %res
985out:
986  ret i1 false
987}
988
989
990define i1 @clamp_high3(i32 noundef %a) {
991; CHECK-LABEL: define i1 @clamp_high3
992; CHECK-SAME: (i32 noundef [[A:%.*]]) {
993; CHECK-NEXT:  entry:
994; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A]], 5
995; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
996; CHECK:       a_guard:
997; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp slt i32 [[A]], 5
998; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
999; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5
1000; CHECK-NEXT:    ret i1 false
1001; CHECK:       out:
1002; CHECK-NEXT:    ret i1 false
1003;
1004entry:
1005  %cmp = icmp sle i32 %a, 5
1006  br i1 %cmp, label %a_guard, label %out
1007
1008a_guard:
1009  %sel_cmp = icmp slt i32 %a, 5
1010  %add = add i32 %a, 1
1011  %sel = select i1 %sel_cmp, i32 %add, i32 5
1012  %res = icmp eq i32 %sel, 6
1013  ret i1 %res
1014out:
1015  ret i1 false
1016}
1017
1018define i1 @clamp_high4(i32 noundef %a) {
1019; CHECK-LABEL: define i1 @clamp_high4
1020; CHECK-SAME: (i32 noundef [[A:%.*]]) {
1021; CHECK-NEXT:  entry:
1022; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A]], 5
1023; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
1024; CHECK:       a_guard:
1025; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp sge i32 [[A]], 5
1026; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
1027; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]]
1028; CHECK-NEXT:    ret i1 false
1029; CHECK:       out:
1030; CHECK-NEXT:    ret i1 false
1031;
1032entry:
1033  %cmp = icmp sle i32 %a, 5
1034  br i1 %cmp, label %a_guard, label %out
1035
1036a_guard:
1037  %sel_cmp = icmp sge i32 %a, 5
1038  %add = add i32 %a, 1
1039  %sel = select i1 %sel_cmp, i32 5, i32 %add
1040  %res = icmp eq i32 %sel, 6
1041  ret i1 %res
1042out:
1043  ret i1 false
1044}
1045
1046; Just showing arbitrary constants work, not really a clamp
1047define i1 @not_clamp_high(i32 noundef %a) {
1048; CHECK-LABEL: define i1 @not_clamp_high
1049; CHECK-SAME: (i32 noundef [[A:%.*]]) {
1050; CHECK-NEXT:  entry:
1051; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A]], 5
1052; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
1053; CHECK:       a_guard:
1054; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5
1055; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 100
1056; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5
1057; CHECK-NEXT:    ret i1 false
1058; CHECK:       out:
1059; CHECK-NEXT:    ret i1 false
1060;
1061entry:
1062  %cmp = icmp sle i32 %a, 5
1063  br i1 %cmp, label %a_guard, label %out
1064
1065a_guard:
1066  %sel_cmp = icmp ne i32 %a, 5
1067  %add = add i32 %a, 100
1068  %sel = select i1 %sel_cmp, i32 %add, i32 5
1069  %res = icmp eq i32 %sel, 105
1070  ret i1 %res
1071out:
1072  ret i1 false
1073}
1074
1075define void @abs1(i32 %a, ptr %p) {
1076; CHECK-LABEL: define void @abs1
1077; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) {
1078; CHECK-NEXT:  entry:
1079; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A]], 10
1080; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[A]], -20
1081; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
1082; CHECK-NEXT:    br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1083; CHECK:       guard:
1084; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 0, [[A]]
1085; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], 0
1086; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[A]]
1087; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1088; CHECK-NEXT:    [[C2:%.*]] = icmp samesign ult i32 [[ABS]], 19
1089; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1090; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1091; CHECK-NEXT:    [[C4:%.*]] = icmp samesign uge i32 [[ABS]], 1
1092; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
1093; CHECK-NEXT:    br label [[EXIT]]
1094; CHECK:       exit:
1095; CHECK-NEXT:    ret void
1096;
1097entry:
1098  %cmp1 = icmp slt i32 %a, 10
1099  %cmp2 = icmp sgt i32 %a, -20
1100  %and = and i1 %cmp1, %cmp2
1101  br i1 %and, label %guard, label %exit
1102
1103guard:
1104  %sub = sub i32 0, %a
1105  %cmp = icmp slt i32 %a, 0
1106  %abs = select i1 %cmp, i32 %sub, i32 %a
1107  %c1 = icmp slt i32 %abs, 20
1108  store i1 %c1, ptr %p
1109  %c2 = icmp slt i32 %abs, 19
1110  store i1 %c2, ptr %p
1111  %c3 = icmp sge i32 %abs, 0
1112  store i1 %c3, ptr %p
1113  %c4 = icmp sge i32 %abs, 1
1114  store i1 %c4, ptr %p
1115  br label %exit
1116
1117exit:
1118  ret void
1119}
1120
1121define void @abs2(i32 %a, ptr %p) {
1122; CHECK-LABEL: define void @abs2
1123; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) {
1124; CHECK-NEXT:  entry:
1125; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A]], 10
1126; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[A]], -20
1127; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
1128; CHECK-NEXT:    br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1129; CHECK:       guard:
1130; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 0, [[A]]
1131; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A]], 0
1132; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[SUB]]
1133; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1134; CHECK-NEXT:    [[C2:%.*]] = icmp samesign ult i32 [[ABS]], 19
1135; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1136; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1137; CHECK-NEXT:    [[C4:%.*]] = icmp samesign uge i32 [[ABS]], 1
1138; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
1139; CHECK-NEXT:    br label [[EXIT]]
1140; CHECK:       exit:
1141; CHECK-NEXT:    ret void
1142;
1143entry:
1144  %cmp1 = icmp slt i32 %a, 10
1145  %cmp2 = icmp sgt i32 %a, -20
1146  %and = and i1 %cmp1, %cmp2
1147  br i1 %and, label %guard, label %exit
1148
1149guard:
1150  %sub = sub i32 0, %a
1151  %cmp = icmp sge i32 %a, 0
1152  %abs = select i1 %cmp, i32 %a, i32 %sub
1153  %c1 = icmp slt i32 %abs, 20
1154  store i1 %c1, ptr %p
1155  %c2 = icmp slt i32 %abs, 19
1156  store i1 %c2, ptr %p
1157  %c3 = icmp sge i32 %abs, 0
1158  store i1 %c3, ptr %p
1159  %c4 = icmp sge i32 %abs, 1
1160  store i1 %c4, ptr %p
1161  br label %exit
1162
1163exit:
1164  ret void
1165}
1166
1167define void @nabs1(i32 %a, ptr %p) {
1168; CHECK-LABEL: define void @nabs1
1169; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) {
1170; CHECK-NEXT:  entry:
1171; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A]], 10
1172; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[A]], -20
1173; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
1174; CHECK-NEXT:    br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1175; CHECK:       guard:
1176; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 0, [[A]]
1177; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], 0
1178; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[A]]
1179; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1180; CHECK-NEXT:    [[C2:%.*]] = icmp sgt i32 [[NABS]], -19
1181; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1182; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1183; CHECK-NEXT:    [[C4:%.*]] = icmp sle i32 [[NABS]], -1
1184; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
1185; CHECK-NEXT:    br label [[EXIT]]
1186; CHECK:       exit:
1187; CHECK-NEXT:    ret void
1188;
1189entry:
1190  %cmp1 = icmp slt i32 %a, 10
1191  %cmp2 = icmp sgt i32 %a, -20
1192  %and = and i1 %cmp1, %cmp2
1193  br i1 %and, label %guard, label %exit
1194
1195guard:
1196  %sub = sub i32 0, %a
1197  %cmp = icmp sgt i32 %a, 0
1198  %nabs = select i1 %cmp, i32 %sub, i32 %a
1199  %c1 = icmp sgt i32 %nabs, -20
1200  store i1 %c1, ptr %p
1201  %c2 = icmp sgt i32 %nabs, -19
1202  store i1 %c2, ptr %p
1203  %c3 = icmp sle i32 %nabs, 0
1204  store i1 %c3, ptr %p
1205  %c4 = icmp sle i32 %nabs, -1
1206  store i1 %c4, ptr %p
1207  br label %exit
1208
1209exit:
1210  ret void
1211}
1212
1213define void @nabs2(i32 %a, ptr %p) {
1214; CHECK-LABEL: define void @nabs2
1215; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) {
1216; CHECK-NEXT:  entry:
1217; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A]], 10
1218; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[A]], -20
1219; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
1220; CHECK-NEXT:    br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1221; CHECK:       guard:
1222; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 0, [[A]]
1223; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], 0
1224; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[SUB]]
1225; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1226; CHECK-NEXT:    [[C2:%.*]] = icmp sgt i32 [[NABS]], -19
1227; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1228; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1229; CHECK-NEXT:    [[C4:%.*]] = icmp sle i32 [[NABS]], -1
1230; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
1231; CHECK-NEXT:    br label [[EXIT]]
1232; CHECK:       exit:
1233; CHECK-NEXT:    ret void
1234;
1235entry:
1236  %cmp1 = icmp slt i32 %a, 10
1237  %cmp2 = icmp sgt i32 %a, -20
1238  %and = and i1 %cmp1, %cmp2
1239  br i1 %and, label %guard, label %exit
1240
1241guard:
1242  %sub = sub i32 0, %a
1243  %cmp = icmp slt i32 %a, 0
1244  %nabs = select i1 %cmp, i32 %a, i32 %sub
1245  %c1 = icmp sgt i32 %nabs, -20
1246  store i1 %c1, ptr %p
1247  %c2 = icmp sgt i32 %nabs, -19
1248  store i1 %c2, ptr %p
1249  %c3 = icmp sle i32 %nabs, 0
1250  store i1 %c3, ptr %p
1251  %c4 = icmp sle i32 %nabs, -1
1252  store i1 %c4, ptr %p
1253  br label %exit
1254
1255exit:
1256  ret void
1257}
1258
1259define i1 @zext_unknown(i8 %a) {
1260; CHECK-LABEL: define i1 @zext_unknown
1261; CHECK-SAME: (i8 [[A:%.*]]) {
1262; CHECK-NEXT:  entry:
1263; CHECK-NEXT:    [[A32:%.*]] = zext i8 [[A]] to i32
1264; CHECK-NEXT:    ret i1 true
1265;
1266entry:
1267  %a32 = zext i8 %a to i32
1268  %cmp = icmp sle i32 %a32, 256
1269  ret i1 %cmp
1270}
1271
1272define i1 @trunc_unknown(i32 %a) {
1273; CHECK-LABEL: define i1 @trunc_unknown
1274; CHECK-SAME: (i32 [[A:%.*]]) {
1275; CHECK-NEXT:  entry:
1276; CHECK-NEXT:    [[A8:%.*]] = trunc i32 [[A]] to i8
1277; CHECK-NEXT:    [[A32:%.*]] = sext i8 [[A8]] to i32
1278; CHECK-NEXT:    ret i1 true
1279;
1280entry:
1281  %a8 = trunc i32 %a to i8
1282  %a32 = sext i8 %a8 to i32
1283  %cmp = icmp sle i32 %a32, 128
1284  ret i1 %cmp
1285}
1286
1287define void @trunc_icmp_ule(i32 %x, ptr %p) {
1288; CHECK-LABEL: define void @trunc_icmp_ule
1289; CHECK-SAME: (i32 [[X:%.*]], ptr [[P:%.*]]) {
1290; CHECK-NEXT:    [[T:%.*]] = trunc i32 [[X]] to i8
1291; CHECK-NEXT:    [[C:%.*]] = icmp uge i8 [[T]], 5
1292; CHECK-NEXT:    br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]]
1293; CHECK:       true:
1294; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1295; CHECK-NEXT:    [[C2:%.*]] = icmp ugt i32 [[X]], 5
1296; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1297; CHECK-NEXT:    [[C3:%.*]] = icmp ule i32 [[X]], 5
1298; CHECK-NEXT:    store i1 [[C3]], ptr [[P]], align 1
1299; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1300; CHECK-NEXT:    ret void
1301; CHECK:       false:
1302; CHECK-NEXT:    [[C1_2:%.*]] = icmp uge i32 [[X]], 5
1303; CHECK-NEXT:    store i1 [[C1_2]], ptr [[P]], align 1
1304; CHECK-NEXT:    [[C2_2:%.*]] = icmp ugt i32 [[X]], 5
1305; CHECK-NEXT:    store i1 [[C2_2]], ptr [[P]], align 1
1306; CHECK-NEXT:    [[C3_2:%.*]] = icmp ule i32 [[X]], 5
1307; CHECK-NEXT:    store i1 [[C3_2]], ptr [[P]], align 1
1308; CHECK-NEXT:    [[C4_2:%.*]] = icmp ult i32 [[X]], 5
1309; CHECK-NEXT:    store i1 [[C4_2]], ptr [[P]], align 1
1310; CHECK-NEXT:    ret void
1311;
1312  %t = trunc i32 %x to i8
1313  %c = icmp uge i8 %t, 5
1314  br i1 %c, label %true, label %false
1315
1316true:
1317  %c1 = icmp uge i32 %x, 5
1318  store i1 %c1, ptr %p
1319  %c2 = icmp ugt i32 %x, 5
1320  store i1 %c2, ptr %p
1321  %c3 = icmp ule i32 %x, 5
1322  store i1 %c3, ptr %p
1323  %c4 = icmp ult i32 %x, 5
1324  store i1 %c4, ptr %p
1325  ret void
1326
1327false:
1328  %c1.2 = icmp uge i32 %x, 5
1329  store i1 %c1.2, ptr %p
1330  %c2.2 = icmp ugt i32 %x, 5
1331  store i1 %c2.2, ptr %p
1332  %c3.2 = icmp ule i32 %x, 5
1333  store i1 %c3.2, ptr %p
1334  %c4.2 = icmp ult i32 %x, 5
1335  store i1 %c4.2, ptr %p
1336  ret void
1337}
1338
1339define void @trunc_icmp_eq(i32 %x, ptr %p) {
1340; CHECK-LABEL: define void @trunc_icmp_eq
1341; CHECK-SAME: (i32 [[X:%.*]], ptr [[P:%.*]]) {
1342; CHECK-NEXT:    [[T:%.*]] = trunc i32 [[X]] to i8
1343; CHECK-NEXT:    [[C:%.*]] = icmp eq i8 [[T]], 5
1344; CHECK-NEXT:    br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]]
1345; CHECK:       true:
1346; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1347; CHECK-NEXT:    [[C2:%.*]] = icmp ugt i32 [[X]], 5
1348; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1349; CHECK-NEXT:    [[C3:%.*]] = icmp ule i32 [[X]], 5
1350; CHECK-NEXT:    store i1 [[C3]], ptr [[P]], align 1
1351; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1352; CHECK-NEXT:    ret void
1353; CHECK:       false:
1354; CHECK-NEXT:    [[C1_2:%.*]] = icmp uge i32 [[X]], 5
1355; CHECK-NEXT:    store i1 [[C1_2]], ptr [[P]], align 1
1356; CHECK-NEXT:    [[C2_2:%.*]] = icmp ugt i32 [[X]], 5
1357; CHECK-NEXT:    store i1 [[C2_2]], ptr [[P]], align 1
1358; CHECK-NEXT:    [[C3_2:%.*]] = icmp ule i32 [[X]], 5
1359; CHECK-NEXT:    store i1 [[C3_2]], ptr [[P]], align 1
1360; CHECK-NEXT:    [[C4_2:%.*]] = icmp ult i32 [[X]], 5
1361; CHECK-NEXT:    store i1 [[C4_2]], ptr [[P]], align 1
1362; CHECK-NEXT:    ret void
1363;
1364  %t = trunc i32 %x to i8
1365  %c = icmp eq i8 %t, 5
1366  br i1 %c, label %true, label %false
1367
1368true:
1369  %c1 = icmp uge i32 %x, 5
1370  store i1 %c1, ptr %p
1371  %c2 = icmp ugt i32 %x, 5
1372  store i1 %c2, ptr %p
1373  %c3 = icmp ule i32 %x, 5
1374  store i1 %c3, ptr %p
1375  %c4 = icmp ult i32 %x, 5
1376  store i1 %c4, ptr %p
1377  ret void
1378
1379false:
1380  %c1.2 = icmp uge i32 %x, 5
1381  store i1 %c1.2, ptr %p
1382  %c2.2 = icmp ugt i32 %x, 5
1383  store i1 %c2.2, ptr %p
1384  %c3.2 = icmp ule i32 %x, 5
1385  store i1 %c3.2, ptr %p
1386  %c4.2 = icmp ult i32 %x, 5
1387  store i1 %c4.2, ptr %p
1388  ret void
1389}
1390
1391; TODO: missed optimization
1392; Make sure we exercise non-integer inputs to unary operators (i.e. crash check).
1393define i1 @bitcast_unknown(float %a) {
1394; CHECK-LABEL: define i1 @bitcast_unknown
1395; CHECK-SAME: (float [[A:%.*]]) {
1396; CHECK-NEXT:  entry:
1397; CHECK-NEXT:    [[A32:%.*]] = bitcast float [[A]] to i32
1398; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A32]], 128
1399; CHECK-NEXT:    ret i1 [[CMP]]
1400;
1401entry:
1402  %a32 = bitcast float %a to i32
1403  %cmp = icmp sle i32 %a32, 128
1404  ret i1 %cmp
1405}
1406
1407define i1 @bitcast_unknown2(ptr %p) {
1408; CHECK-LABEL: define i1 @bitcast_unknown2
1409; CHECK-SAME: (ptr [[P:%.*]]) {
1410; CHECK-NEXT:  entry:
1411; CHECK-NEXT:    [[P64:%.*]] = ptrtoint ptr [[P]] to i64
1412; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i64 [[P64]], 128
1413; CHECK-NEXT:    ret i1 [[CMP]]
1414;
1415entry:
1416  %p64 = ptrtoint ptr %p to i64
1417  %cmp = icmp sle i64 %p64, 128
1418  ret i1 %cmp
1419}
1420
1421
1422define i1 @and_unknown(i32 %a) {
1423; CHECK-LABEL: define i1 @and_unknown
1424; CHECK-SAME: (i32 [[A:%.*]]) {
1425; CHECK-NEXT:  entry:
1426; CHECK-NEXT:    [[AND:%.*]] = and i32 [[A]], 128
1427; CHECK-NEXT:    ret i1 true
1428;
1429entry:
1430  %and = and i32 %a, 128
1431  %cmp = icmp sle i32 %and, 128
1432  ret i1 %cmp
1433}
1434
1435define i1 @lshr_unknown(i32 %a) {
1436; CHECK-LABEL: define i1 @lshr_unknown
1437; CHECK-SAME: (i32 [[A:%.*]]) {
1438; CHECK-NEXT:  entry:
1439; CHECK-NEXT:    [[AND:%.*]] = lshr i32 [[A]], 30
1440; CHECK-NEXT:    ret i1 true
1441;
1442entry:
1443  %and = lshr i32 %a, 30
1444  %cmp = icmp sle i32 %and, 128
1445  ret i1 %cmp
1446}
1447
1448define i1 @urem_unknown(i32 %a) {
1449; CHECK-LABEL: define i1 @urem_unknown
1450; CHECK-SAME: (i32 [[A:%.*]]) {
1451; CHECK-NEXT:  entry:
1452; CHECK-NEXT:    [[UREM:%.*]] = urem i32 [[A]], 30
1453; CHECK-NEXT:    ret i1 true
1454;
1455entry:
1456  %urem = urem i32 %a, 30
1457  %cmp = icmp ult i32 %urem, 30
1458  ret i1 %cmp
1459}
1460
1461define i1 @srem_unknown(i32 %a, i1 %arg) {
1462; CHECK-LABEL: define i1 @srem_unknown
1463; CHECK-SAME: (i32 [[A:%.*]], i1 [[ARG:%.*]]) {
1464; CHECK-NEXT:  entry:
1465; CHECK-NEXT:    [[SREM:%.*]] = srem i32 [[A]], 30
1466; CHECK-NEXT:    br i1 [[ARG]], label [[EXIT1:%.*]], label [[EXIT2:%.*]]
1467; CHECK:       exit1:
1468; CHECK-NEXT:    ret i1 true
1469; CHECK:       exit2:
1470; CHECK-NEXT:    ret i1 true
1471;
1472entry:
1473  %srem = srem i32 %a, 30
1474  %cmp1 = icmp slt i32 %srem, 30
1475  %cmp2 = icmp sgt i32 %srem, -30
1476  br i1 %arg, label %exit1, label %exit2
1477exit1:
1478  ret i1 %cmp1
1479exit2:
1480  ret i1 %cmp2
1481}
1482
1483define i1 @sdiv_unknown(i32 %a, i1 %arg) {
1484; CHECK-LABEL: define i1 @sdiv_unknown
1485; CHECK-SAME: (i32 [[A:%.*]], i1 [[ARG:%.*]]) {
1486; CHECK-NEXT:  entry:
1487; CHECK-NEXT:    [[SREM:%.*]] = sdiv i32 [[A]], 123
1488; CHECK-NEXT:    br i1 [[ARG]], label [[EXIT1:%.*]], label [[EXIT2:%.*]]
1489; CHECK:       exit1:
1490; CHECK-NEXT:    ret i1 true
1491; CHECK:       exit2:
1492; CHECK-NEXT:    ret i1 true
1493;
1494entry:
1495  %srem = sdiv i32 %a, 123
1496  %cmp1 = icmp slt i32 %srem, 17459217
1497  %cmp2 = icmp sgt i32 %srem, -17459217
1498  br i1 %arg, label %exit1, label %exit2
1499exit1:
1500  ret i1 %cmp1
1501exit2:
1502  ret i1 %cmp2
1503}
1504
1505define i1 @uadd_sat_unknown(i32 %a, i1 %arg) {
1506; CHECK-LABEL: define i1 @uadd_sat_unknown
1507; CHECK-SAME: (i32 [[A:%.*]], i1 [[ARG:%.*]]) {
1508; CHECK-NEXT:  entry:
1509; CHECK-NEXT:    [[VAL:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[A]], i32 100)
1510; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[VAL]], 100
1511; CHECK-NEXT:    br i1 [[ARG]], label [[EXIT1:%.*]], label [[EXIT2:%.*]]
1512; CHECK:       exit1:
1513; CHECK-NEXT:    ret i1 true
1514; CHECK:       exit2:
1515; CHECK-NEXT:    ret i1 [[CMP2]]
1516;
1517entry:
1518  %val = call i32 @llvm.uadd.sat.i32(i32 %a, i32 100)
1519  %cmp1 = icmp uge i32 %val, 100
1520  %cmp2 = icmp ugt i32 %val, 100
1521  br i1 %arg, label %exit1, label %exit2
1522exit1:
1523  ret i1 %cmp1
1524exit2:
1525  ret i1 %cmp2
1526}
1527
1528define i1 @usub_sat_unknown(i32 %a, i1 %arg) {
1529; CHECK-LABEL: define i1 @usub_sat_unknown
1530; CHECK-SAME: (i32 [[A:%.*]], i1 [[ARG:%.*]]) {
1531; CHECK-NEXT:  entry:
1532; CHECK-NEXT:    [[VAL:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A]], i32 100)
1533; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[VAL]], -101
1534; CHECK-NEXT:    br i1 [[ARG]], label [[EXIT1:%.*]], label [[EXIT2:%.*]]
1535; CHECK:       exit1:
1536; CHECK-NEXT:    ret i1 true
1537; CHECK:       exit2:
1538; CHECK-NEXT:    ret i1 [[CMP2]]
1539;
1540entry:
1541  %val = call i32 @llvm.usub.sat.i32(i32 %a, i32 100)
1542  %cmp1 = icmp ule i32 %val, 4294967195
1543  %cmp2 = icmp ult i32 %val, 4294967195
1544  br i1 %arg, label %exit1, label %exit2
1545exit1:
1546  ret i1 %cmp1
1547exit2:
1548  ret i1 %cmp2
1549}
1550
1551define i1 @sadd_sat_unknown(i32 %a, i1 %arg) {
1552; CHECK-LABEL: define i1 @sadd_sat_unknown
1553; CHECK-SAME: (i32 [[A:%.*]], i1 [[ARG:%.*]]) {
1554; CHECK-NEXT:  entry:
1555; CHECK-NEXT:    [[VAL:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[A]], i32 100)
1556; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[VAL]], -2147483548
1557; CHECK-NEXT:    br i1 [[ARG]], label [[EXIT1:%.*]], label [[EXIT2:%.*]]
1558; CHECK:       exit1:
1559; CHECK-NEXT:    ret i1 true
1560; CHECK:       exit2:
1561; CHECK-NEXT:    ret i1 [[CMP2]]
1562;
1563entry:
1564  %val = call i32 @llvm.sadd.sat.i32(i32 %a, i32 100)
1565  %cmp1 = icmp sge i32 %val, -2147483548
1566  %cmp2 = icmp sgt i32 %val, -2147483548
1567  br i1 %arg, label %exit1, label %exit2
1568exit1:
1569  ret i1 %cmp1
1570exit2:
1571  ret i1 %cmp2
1572}
1573
1574define i1 @ssub_sat_unknown(i32 %a, i1 %arg) {
1575; CHECK-LABEL: define i1 @ssub_sat_unknown
1576; CHECK-SAME: (i32 [[A:%.*]], i1 [[ARG:%.*]]) {
1577; CHECK-NEXT:  entry:
1578; CHECK-NEXT:    [[VAL:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[A]], i32 100)
1579; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[VAL]], 2147483547
1580; CHECK-NEXT:    br i1 [[ARG]], label [[EXIT1:%.*]], label [[EXIT2:%.*]]
1581; CHECK:       exit1:
1582; CHECK-NEXT:    ret i1 true
1583; CHECK:       exit2:
1584; CHECK-NEXT:    ret i1 [[CMP2]]
1585;
1586entry:
1587  %val = call i32 @llvm.ssub.sat.i32(i32 %a, i32 100)
1588  %cmp1 = icmp sle i32 %val, 2147483547
1589  %cmp2 = icmp slt i32 %val, 2147483547
1590  br i1 %arg, label %exit1, label %exit2
1591exit1:
1592  ret i1 %cmp1
1593exit2:
1594  ret i1 %cmp2
1595}
1596
1597define void @select_and(i32 %a, ptr %p) {
1598; CHECK-LABEL: define void @select_and
1599; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) {
1600; CHECK-NEXT:  entry:
1601; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 [[A]], -10
1602; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[A]], 10
1603; CHECK-NEXT:    [[AND:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 false
1604; CHECK-NEXT:    br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1605; CHECK:       guard:
1606; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1607; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1608; CHECK-NEXT:    br label [[EXIT]]
1609; CHECK:       exit:
1610; CHECK-NEXT:    ret void
1611;
1612entry:
1613  %cmp1 = icmp sgt i32 %a, -10
1614  %cmp2 = icmp slt i32 %a, 10
1615  %and = select i1 %cmp1, i1 %cmp2, i1 false
1616  br i1 %and, label %guard, label %exit
1617
1618guard:
1619  %c1 = icmp sgt i32 %a, 20
1620  store i1 %c1, ptr %p
1621  %c2 = icmp slt i32 %a, -20
1622  store i1 %c2, ptr %p
1623  br label %exit
1624
1625exit:
1626  ret void
1627}
1628
1629define void @select_and_wrong_const(i32 %a, ptr %p) {
1630; CHECK-LABEL: define void @select_and_wrong_const
1631; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) {
1632; CHECK-NEXT:  entry:
1633; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 [[A]], -10
1634; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[A]], 10
1635; CHECK-NEXT:    [[AND:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 true
1636; CHECK-NEXT:    br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1637; CHECK:       guard:
1638; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i32 [[A]], 20
1639; CHECK-NEXT:    store i1 [[C1]], ptr [[P]], align 1
1640; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[A]], -20
1641; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1642; CHECK-NEXT:    br label [[EXIT]]
1643; CHECK:       exit:
1644; CHECK-NEXT:    ret void
1645;
1646entry:
1647  %cmp1 = icmp sgt i32 %a, -10
1648  %cmp2 = icmp slt i32 %a, 10
1649  %and = select i1 %cmp1, i1 %cmp2, i1 true
1650  br i1 %and, label %guard, label %exit
1651
1652guard:
1653  %c1 = icmp sgt i32 %a, 20
1654  store i1 %c1, ptr %p
1655  %c2 = icmp slt i32 %a, -20
1656  store i1 %c2, ptr %p
1657  br label %exit
1658
1659exit:
1660  ret void
1661}
1662
1663define void @select_and_wrong_operand(i32 %a, ptr %p) {
1664; CHECK-LABEL: define void @select_and_wrong_operand
1665; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) {
1666; CHECK-NEXT:  entry:
1667; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 [[A]], -10
1668; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[A]], 10
1669; CHECK-NEXT:    [[AND:%.*]] = select i1 [[CMP1]], i1 false, i1 [[CMP2]]
1670; CHECK-NEXT:    br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1671; CHECK:       guard:
1672; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i32 [[A]], 20
1673; CHECK-NEXT:    store i1 [[C1]], ptr [[P]], align 1
1674; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[A]], -20
1675; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1676; CHECK-NEXT:    br label [[EXIT]]
1677; CHECK:       exit:
1678; CHECK-NEXT:    ret void
1679;
1680entry:
1681  %cmp1 = icmp sgt i32 %a, -10
1682  %cmp2 = icmp slt i32 %a, 10
1683  %and = select i1 %cmp1, i1 false, i1 %cmp2
1684  br i1 %and, label %guard, label %exit
1685
1686guard:
1687  %c1 = icmp sgt i32 %a, 20
1688  store i1 %c1, ptr %p
1689  %c2 = icmp slt i32 %a, -20
1690  store i1 %c2, ptr %p
1691  br label %exit
1692
1693exit:
1694  ret void
1695}
1696
1697define void @select_or(i32 %a, ptr %p) {
1698; CHECK-LABEL: define void @select_or
1699; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) {
1700; CHECK-NEXT:  entry:
1701; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A]], -10
1702; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[A]], 10
1703; CHECK-NEXT:    [[OR:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]]
1704; CHECK-NEXT:    br i1 [[OR]], label [[EXIT:%.*]], label [[GUARD:%.*]]
1705; CHECK:       guard:
1706; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1707; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1708; CHECK-NEXT:    br label [[EXIT]]
1709; CHECK:       exit:
1710; CHECK-NEXT:    ret void
1711;
1712entry:
1713  %cmp1 = icmp slt i32 %a, -10
1714  %cmp2 = icmp sgt i32 %a, 10
1715  %or = select i1 %cmp1, i1 true, i1 %cmp2
1716  br i1 %or, label %exit, label %guard
1717
1718guard:
1719  %c1 = icmp sgt i32 %a, 20
1720  store i1 %c1, ptr %p
1721  %c2 = icmp slt i32 %a, -20
1722  store i1 %c2, ptr %p
1723  br label %exit
1724
1725exit:
1726  ret void
1727}
1728
1729define void @select_or_wrong_const(i32 %a, ptr %p) {
1730; CHECK-LABEL: define void @select_or_wrong_const
1731; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) {
1732; CHECK-NEXT:  entry:
1733; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A]], -10
1734; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[A]], 10
1735; CHECK-NEXT:    [[OR:%.*]] = select i1 [[CMP1]], i1 false, i1 [[CMP2]]
1736; CHECK-NEXT:    br i1 [[OR]], label [[EXIT:%.*]], label [[GUARD:%.*]]
1737; CHECK:       guard:
1738; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i32 [[A]], 20
1739; CHECK-NEXT:    store i1 [[C1]], ptr [[P]], align 1
1740; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[A]], -20
1741; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1742; CHECK-NEXT:    br label [[EXIT]]
1743; CHECK:       exit:
1744; CHECK-NEXT:    ret void
1745;
1746entry:
1747  %cmp1 = icmp slt i32 %a, -10
1748  %cmp2 = icmp sgt i32 %a, 10
1749  %or = select i1 %cmp1, i1 false, i1 %cmp2
1750  br i1 %or, label %exit, label %guard
1751
1752guard:
1753  %c1 = icmp sgt i32 %a, 20
1754  store i1 %c1, ptr %p
1755  %c2 = icmp slt i32 %a, -20
1756  store i1 %c2, ptr %p
1757  br label %exit
1758
1759exit:
1760  ret void
1761}
1762
1763define void @select_or_wrong_operand(i32 %a, ptr %p) {
1764; CHECK-LABEL: define void @select_or_wrong_operand
1765; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) {
1766; CHECK-NEXT:  entry:
1767; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A]], -10
1768; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[A]], 10
1769; CHECK-NEXT:    [[OR:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 true
1770; CHECK-NEXT:    br i1 [[OR]], label [[EXIT:%.*]], label [[GUARD:%.*]]
1771; CHECK:       guard:
1772; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i32 [[A]], 20
1773; CHECK-NEXT:    store i1 [[C1]], ptr [[P]], align 1
1774; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[A]], -20
1775; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1776; CHECK-NEXT:    br label [[EXIT]]
1777; CHECK:       exit:
1778; CHECK-NEXT:    ret void
1779;
1780entry:
1781  %cmp1 = icmp slt i32 %a, -10
1782  %cmp2 = icmp sgt i32 %a, 10
1783  %or = select i1 %cmp1, i1 %cmp2, i1 true
1784  br i1 %or, label %exit, label %guard
1785
1786guard:
1787  %c1 = icmp sgt i32 %a, 20
1788  store i1 %c1, ptr %p
1789  %c2 = icmp slt i32 %a, -20
1790  store i1 %c2, ptr %p
1791  br label %exit
1792
1793exit:
1794  ret void
1795}
1796
1797define void @or_union(i32 %a, ptr %p) {
1798; CHECK-LABEL: define void @or_union
1799; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) {
1800; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A]], 10
1801; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[A]], 12
1802; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
1803; CHECK-NEXT:    br i1 [[OR]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1804; CHECK:       guard:
1805; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1806; CHECK-NEXT:    [[C2:%.*]] = icmp eq i32 [[A]], 10
1807; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1808; CHECK-NEXT:    [[C3:%.*]] = icmp eq i32 [[A]], 11
1809; CHECK-NEXT:    store i1 [[C3]], ptr [[P]], align 1
1810; CHECK-NEXT:    [[C4:%.*]] = icmp eq i32 [[A]], 12
1811; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
1812; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1813; CHECK-NEXT:    br label [[EXIT]]
1814; CHECK:       exit:
1815; CHECK-NEXT:    ret void
1816;
1817  %cmp1 = icmp eq i32 %a, 10
1818  %cmp2 = icmp eq i32 %a, 12
1819  %or = or i1 %cmp1, %cmp2
1820  br i1 %or, label %guard, label %exit
1821
1822guard:
1823  %c1 = icmp eq i32 %a, 9
1824  store i1 %c1, ptr %p
1825  %c2 = icmp eq i32 %a, 10
1826  store i1 %c2, ptr %p
1827  %c3 = icmp eq i32 %a, 11
1828  store i1 %c3, ptr %p
1829  %c4 = icmp eq i32 %a, 12
1830  store i1 %c4, ptr %p
1831  %c5 = icmp eq i32 %a, 13
1832  store i1 %c5, ptr %p
1833  br label %exit
1834
1835exit:
1836  ret void
1837}
1838
1839define i1 @or_union_unknown_cond(i32 %a, i1 %c) {
1840; CHECK-LABEL: define i1 @or_union_unknown_cond
1841; CHECK-SAME: (i32 [[A:%.*]], i1 [[C:%.*]]) {
1842; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A]], 10
1843; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[C]]
1844; CHECK-NEXT:    br i1 [[OR]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1845; CHECK:       guard:
1846; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[A]], 10
1847; CHECK-NEXT:    ret i1 [[CMP2]]
1848; CHECK:       exit:
1849; CHECK-NEXT:    ret i1 false
1850;
1851  %cmp1 = icmp eq i32 %a, 10
1852  %or = or i1 %cmp1, %c
1853  br i1 %or, label %guard, label %exit
1854
1855guard:
1856  %cmp2 = icmp eq i32 %a, 10
1857  ret i1 %cmp2
1858
1859exit:
1860  ret i1 false
1861}
1862
1863define void @and_union(i32 %a, ptr %p) {
1864; CHECK-LABEL: define void @and_union
1865; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) {
1866; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[A]], 10
1867; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[A]], 12
1868; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
1869; CHECK-NEXT:    br i1 [[AND]], label [[EXIT:%.*]], label [[GUARD:%.*]]
1870; CHECK:       guard:
1871; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1872; CHECK-NEXT:    [[C2:%.*]] = icmp eq i32 [[A]], 10
1873; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1874; CHECK-NEXT:    [[C3:%.*]] = icmp eq i32 [[A]], 11
1875; CHECK-NEXT:    store i1 [[C3]], ptr [[P]], align 1
1876; CHECK-NEXT:    [[C4:%.*]] = icmp eq i32 [[A]], 12
1877; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
1878; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1879; CHECK-NEXT:    br label [[EXIT]]
1880; CHECK:       exit:
1881; CHECK-NEXT:    ret void
1882;
1883  %cmp1 = icmp ne i32 %a, 10
1884  %cmp2 = icmp ne i32 %a, 12
1885  %and = and i1 %cmp1, %cmp2
1886  br i1 %and, label %exit, label %guard
1887
1888guard:
1889  %c1 = icmp eq i32 %a, 9
1890  store i1 %c1, ptr %p
1891  %c2 = icmp eq i32 %a, 10
1892  store i1 %c2, ptr %p
1893  %c3 = icmp eq i32 %a, 11
1894  store i1 %c3, ptr %p
1895  %c4 = icmp eq i32 %a, 12
1896  store i1 %c4, ptr %p
1897  %c5 = icmp eq i32 %a, 13
1898  store i1 %c5, ptr %p
1899  br label %exit
1900
1901exit:
1902  ret void
1903}
1904
1905define i1 @and_union_unknown_cond(i32 %a, i1 %c) {
1906; CHECK-LABEL: define i1 @and_union_unknown_cond
1907; CHECK-SAME: (i32 [[A:%.*]], i1 [[C:%.*]]) {
1908; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[A]], 10
1909; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[C]]
1910; CHECK-NEXT:    br i1 [[AND]], label [[EXIT:%.*]], label [[GUARD:%.*]]
1911; CHECK:       guard:
1912; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[A]], 10
1913; CHECK-NEXT:    ret i1 [[CMP2]]
1914; CHECK:       exit:
1915; CHECK-NEXT:    ret i1 false
1916;
1917  %cmp1 = icmp ne i32 %a, 10
1918  %and = and i1 %cmp1, %c
1919  br i1 %and, label %exit, label %guard
1920
1921guard:
1922  %cmp2 = icmp eq i32 %a, 10
1923  ret i1 %cmp2
1924
1925exit:
1926  ret i1 false
1927}
1928
1929define void @select_assume(i32 %a, i32 %b, i1 %c, ptr %p) {
1930; CHECK-LABEL: define void @select_assume
1931; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i1 [[C:%.*]], ptr [[P:%.*]]) {
1932; CHECK-NEXT:    [[C1:%.*]] = icmp ult i32 [[A]], 10
1933; CHECK-NEXT:    call void @llvm.assume(i1 [[C1]])
1934; CHECK-NEXT:    [[C2:%.*]] = icmp ult i32 [[B]], 20
1935; CHECK-NEXT:    call void @llvm.assume(i1 [[C2]])
1936; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i32 [[A]], i32 [[B]]
1937; CHECK-NEXT:    [[C3:%.*]] = icmp samesign ult i32 [[S]], 19
1938; CHECK-NEXT:    store i1 [[C3]], ptr [[P]], align 1
1939; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1940; CHECK-NEXT:    ret void
1941;
1942  %c1 = icmp ult i32 %a, 10
1943  call void @llvm.assume(i1 %c1)
1944  %c2 = icmp ult i32 %b, 20
1945  call void @llvm.assume(i1 %c2)
1946  %s = select i1 %c, i32 %a, i32 %b
1947  %c3 = icmp ult i32 %s, 19
1948  store i1 %c3, ptr %p
1949  %c4 = icmp ult i32 %s, 20
1950  store i1 %c4, ptr %p
1951  ret void
1952}
1953
1954define void @xor(i8 %a, ptr %p) {
1955; CHECK-LABEL: define void @xor
1956; CHECK-SAME: (i8 [[A:%.*]], ptr [[P:%.*]]) {
1957; CHECK-NEXT:    [[A_MASK:%.*]] = and i8 [[A]], 15
1958; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[A_MASK]], -86
1959; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1960; CHECK-NEXT:    [[C2:%.*]] = icmp samesign ugt i8 [[XOR]], -96
1961; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1962; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1963; CHECK-NEXT:    [[C4:%.*]] = icmp samesign ult i8 [[XOR]], -81
1964; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
1965; CHECK-NEXT:    ret void
1966;
1967  %a.mask = and i8 %a, 15 ; 0b0000????
1968  %xor = xor i8 %a.mask, 170 ; ^ 0b10101010 == 0b1010????
1969  %c1 = icmp uge i8 %xor, 160
1970  store i1 %c1, ptr %p
1971  %c2 = icmp ugt i8 %xor, 160
1972  store i1 %c2, ptr %p
1973  %c3 = icmp ule i8 %xor, 175
1974  store i1 %c3, ptr %p
1975  %c4 = icmp ult i8 %xor, 175
1976  store i1 %c4, ptr %p
1977  ret void
1978}
1979
1980define i1 @xor_neg_cond(i32 %a) {
1981; CHECK-LABEL: define i1 @xor_neg_cond
1982; CHECK-SAME: (i32 [[A:%.*]]) {
1983; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A]], 10
1984; CHECK-NEXT:    [[XOR:%.*]] = xor i1 [[CMP1]], true
1985; CHECK-NEXT:    br i1 [[XOR]], label [[EXIT:%.*]], label [[GUARD:%.*]]
1986; CHECK:       guard:
1987; CHECK-NEXT:    ret i1 true
1988; CHECK:       exit:
1989; CHECK-NEXT:    ret i1 false
1990;
1991  %cmp1 = icmp eq i32 %a, 10
1992  %xor = xor i1 %cmp1, true
1993  br i1 %xor, label %exit, label %guard
1994
1995guard:
1996  %cmp2 = icmp eq i32 %a, 10
1997  ret i1 %cmp2
1998
1999exit:
2000  ret i1 false
2001}
2002
2003define i1 @xor_approx(i32 %a) {
2004; CHECK-LABEL: define i1 @xor_approx
2005; CHECK-SAME: (i32 [[A:%.*]]) {
2006; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 [[A]], 2
2007; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[A]], 5
2008; CHECK-NEXT:    [[CMP3:%.*]] = icmp ugt i32 [[A]], 7
2009; CHECK-NEXT:    [[CMP4:%.*]] = icmp ult i32 [[A]], 9
2010; CHECK-NEXT:    [[AND1:%.*]] = and i1 [[CMP1]], [[CMP2]]
2011; CHECK-NEXT:    [[AND2:%.*]] = and i1 [[CMP3]], [[CMP4]]
2012; CHECK-NEXT:    [[OR:%.*]] = or i1 [[AND1]], [[AND2]]
2013; CHECK-NEXT:    [[XOR:%.*]] = xor i1 [[OR]], true
2014; CHECK-NEXT:    br i1 [[XOR]], label [[EXIT:%.*]], label [[GUARD:%.*]]
2015; CHECK:       guard:
2016; CHECK-NEXT:    [[CMP5:%.*]] = icmp eq i32 [[A]], 6
2017; CHECK-NEXT:    ret i1 [[CMP5]]
2018; CHECK:       exit:
2019; CHECK-NEXT:    ret i1 false
2020;
2021  %cmp1 = icmp ugt i32 %a, 2
2022  %cmp2 = icmp ult i32 %a, 5
2023  %cmp3 = icmp ugt i32 %a, 7
2024  %cmp4 = icmp ult i32 %a, 9
2025  %and1 = and i1 %cmp1, %cmp2
2026  %and2 = and i1 %cmp3, %cmp4
2027  %or = or i1 %and1, %and2
2028  %xor = xor i1 %or, true
2029  br i1 %xor, label %exit, label %guard
2030
2031guard:
2032  %cmp5 = icmp eq i32 %a, 6
2033  ret i1 %cmp5
2034
2035exit:
2036  ret i1 false
2037}
2038
2039define i1 @binop_eval_order(i32 %x) {
2040; CHECK-LABEL: define i1 @binop_eval_order
2041; CHECK-SAME: (i32 [[X:%.*]]) {
2042; CHECK-NEXT:    [[A:%.*]] = add nuw nsw i32 [[X]], 1
2043; CHECK-NEXT:    [[B:%.*]] = add nuw nsw i32 [[A]], 1
2044; CHECK-NEXT:    [[C:%.*]] = add nuw nsw i32 [[A]], [[B]]
2045; CHECK-NEXT:    ret i1 true
2046;
2047  %a = add nuw nsw i32 %x, 1
2048  %b = add nuw nsw i32 %a, 1
2049  %c = add nuw nsw i32 %a, %b
2050  %d = icmp ugt i32 %c, 2
2051  ret i1 %d
2052}
2053
2054define range(i32 0, 1024) i32 @range_larger(i8 %x) {
2055; CHECK-LABEL: define range(i32 0, 256) i32 @range_larger
2056; CHECK-SAME: (i8 [[X:%.*]]) {
2057; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[X]] to i32
2058; CHECK-NEXT:    ret i32 [[ZEXT]]
2059;
2060  %zext = zext i8 %x to i32
2061  ret i32 %zext
2062}
2063
2064define range(i32 0, 128) i32 @range_smaller(i8 %x) {
2065; CHECK-LABEL: define range(i32 0, 128) i32 @range_smaller
2066; CHECK-SAME: (i8 [[X:%.*]]) {
2067; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[X]] to i32
2068; CHECK-NEXT:    ret i32 [[ZEXT]]
2069;
2070  %zext = zext i8 %x to i32
2071  ret i32 %zext
2072}
2073
2074define range(i32 128, 512) i32 @range_intersect(i8 %x) {
2075; CHECK-LABEL: define range(i32 128, 256) i32 @range_intersect
2076; CHECK-SAME: (i8 [[X:%.*]]) {
2077; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[X]] to i32
2078; CHECK-NEXT:    ret i32 [[ZEXT]]
2079;
2080  %zext = zext i8 %x to i32
2081  ret i32 %zext
2082}
2083
2084define range(i32 512, 1024) i32 @range_non_overlapping(i8 %x) {
2085; CHECK-LABEL: define range(i32 512, 1024) i32 @range_non_overlapping
2086; CHECK-SAME: (i8 [[X:%.*]]) {
2087; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[X]] to i32
2088; CHECK-NEXT:    ret i32 [[ZEXT]]
2089;
2090  %zext = zext i8 %x to i32
2091  ret i32 %zext
2092}
2093
2094declare i32 @llvm.uadd.sat.i32(i32, i32)
2095declare i32 @llvm.usub.sat.i32(i32, i32)
2096declare i32 @llvm.sadd.sat.i32(i32, i32)
2097declare i32 @llvm.ssub.sat.i32(i32, i32)
2098declare void @llvm.assume(i1)
2099