[CVP] Don't try to fold load/store operands to constant (#73338)
[llvm-project.git] / llvm / test / Transforms / CorrelatedValuePropagation / basic.ll
blob9fcf7c320f62dd54b21d037a872c086fa6188846
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
3 ; PR2581
5 define 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
13   br i1 %C, label %exit, label %body
15 body:           ; preds = %0
16   %A = select i1 %C, i32 10, i32 11
17   ret i32 %A
19 exit:           ; preds = %0
20   ret i32 10
23 ; PR4420
24 declare i1 @ext()
25 define 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]]
39 entry:
40   %cond = tail call i1 @ext()
41   br i1 %cond, label %bb1, label %bb2
43 bb1:
44   %cond2 = tail call i1 @ext()
45   br i1 %cond2, label %bb3, label %bb2
47 bb2:
48   %cond_merge = phi i1 [ %cond, %entry ], [ false, %bb1 ]
49   ret i1 %cond_merge
51 bb3:
52   %res = tail call i1 @ext()
53   ret i1 %res
56 ; PR4855
57 @gv = internal constant i8 7
58 define i8 @test3(ptr %a) nounwind {
59 ; CHECK-LABEL: @test3(
60 ; CHECK-NEXT:  entry:
61 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq ptr [[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, ptr [[A]], align 1
67 ; CHECK-NEXT:    ret i8 [[SHOULD_BE_CONST]]
69 entry:
70   %cond = icmp eq ptr %a, @gv
71   br i1 %cond, label %bb2, label %bb
73 bb:
74   ret i8 0
76 bb2:
77   %should_be_const = load i8, ptr %a
78   ret i8 %should_be_const
81 ; PR1757
82 define 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
96 EntryBlock:
97   %.demorgan = icmp sgt i32 %0, 2
98   br i1 %.demorgan, label %GreaterThanTwo, label %LessThanOrEqualToTwo
100 GreaterThanTwo:
101   icmp eq i32 %0, 2
102   br i1 %1, label %Impossible, label %NotTwoAndGreaterThanTwo
104 NotTwoAndGreaterThanTwo:
105   ret i32 2
107 Impossible:
108   ret i32 1
110 LessThanOrEqualToTwo:
111   ret i32 0
114 declare ptr @f(ptr)
115 define void @test5(ptr %x, ptr %y) {
116 ; CHECK-LABEL: @test5(
117 ; CHECK-NEXT:  entry:
118 ; CHECK-NEXT:    [[PRE:%.*]] = icmp eq ptr [[X:%.*]], null
119 ; CHECK-NEXT:    br i1 [[PRE]], label [[RETURN:%.*]], label [[LOOP:%.*]]
120 ; CHECK:       loop:
121 ; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[F:%.*]], [[LOOP]] ], [ [[X]], [[ENTRY:%.*]] ]
122 ; CHECK-NEXT:    [[F]] = tail call ptr @f(ptr [[PHI]])
123 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne ptr [[F]], [[Y:%.*]]
124 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], ptr [[F]], ptr null
125 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq ptr [[SEL]], null
126 ; CHECK-NEXT:    br i1 [[CMP2]], label [[RETURN]], label [[LOOP]]
127 ; CHECK:       return:
128 ; CHECK-NEXT:    ret void
130 entry:
131   %pre = icmp eq ptr %x, null
132   br i1 %pre, label %return, label %loop
134 loop:
135   %phi = phi ptr [ %sel, %loop ], [ %x, %entry ]
136   %f = tail call ptr @f(ptr %phi)
137   %cmp1 = icmp ne ptr %f, %y
138   %sel = select i1 %cmp1, ptr %f, ptr null
139   %cmp2 = icmp eq ptr %sel, null
140   br i1 %cmp2, label %return, label %loop
142 return:
143   ret void
146 ; "false" case for CorrelatedValuePropagation
147 define void @loop1(ptr %x, ptr %y) {
148 ; CHECK-LABEL: @loop1(
149 ; CHECK-NEXT:  entry:
150 ; CHECK-NEXT:    br label [[LOOP:%.*]]
151 ; CHECK:       loop:
152 ; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[F:%.*]], [[LOOP]] ], [ [[X:%.*]], [[ENTRY:%.*]] ]
153 ; CHECK-NEXT:    [[F]] = tail call ptr @f(ptr [[PHI]])
154 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne ptr [[F]], [[Y:%.*]]
155 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], ptr [[F]], ptr null
156 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq ptr [[SEL]], null
157 ; CHECK-NEXT:    br i1 [[CMP2]], label [[RETURN:%.*]], label [[LOOP]]
158 ; CHECK:       return:
159 ; CHECK-NEXT:    ret void
161 entry:
162   br label %loop
164 loop:
165   %phi = phi ptr [ %sel, %loop ], [ %x, %entry ]
166   %f = tail call ptr @f(ptr %phi)
167   %cmp1 = icmp ne ptr %f, %y
168   %sel = select i1 %cmp1, ptr %f, ptr null
169   %cmp2 = icmp eq ptr %sel, null
170   br i1 %cmp2, label %return, label %loop
172 return:
173   ret void
176 ; "true" case for CorrelatedValuePropagation
177 define void @loop2(ptr %x, ptr %y) {
178 ; CHECK-LABEL: @loop2(
179 ; CHECK-NEXT:  entry:
180 ; CHECK-NEXT:    br label [[LOOP:%.*]]
181 ; CHECK:       loop:
182 ; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[F:%.*]], [[LOOP]] ], [ [[X:%.*]], [[ENTRY:%.*]] ]
183 ; CHECK-NEXT:    [[F]] = tail call ptr @f(ptr [[PHI]])
184 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq ptr [[F]], [[Y:%.*]]
185 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], ptr null, ptr [[F]]
186 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq ptr [[SEL]], null
187 ; CHECK-NEXT:    br i1 [[CMP2]], label [[RETURN:%.*]], label [[LOOP]]
188 ; CHECK:       return:
189 ; CHECK-NEXT:    ret void
191 entry:
192   br label %loop
194 loop:
195   %phi = phi ptr [ %sel, %loop ], [ %x, %entry ]
196   %f = tail call ptr @f(ptr %phi)
197   %cmp1 = icmp eq ptr %f, %y
198   %sel = select i1 %cmp1, ptr null, ptr %f
199   %cmp2 = icmp eq ptr %sel, null
200   br i1 %cmp2, label %return, label %loop
202 return:
203   ret void
206 define i32 @switch1(i32 %s) {
207 ; CHECK-LABEL: @switch1(
208 ; CHECK-NEXT:  entry:
209 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[S:%.*]], 0
210 ; CHECK-NEXT:    br i1 [[CMP]], label [[NEGATIVE:%.*]], label [[OUT:%.*]]
211 ; CHECK:       negative:
212 ; CHECK-NEXT:    switch i32 [[S]], label [[OUT]] [
213 ; CHECK-NEXT:      i32 -2, label [[NEXT:%.*]]
214 ; CHECK-NEXT:      i32 -1, label [[NEXT]]
215 ; CHECK-NEXT:    ]
216 ; CHECK:       out:
217 ; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ -1, [[NEGATIVE]] ]
218 ; CHECK-NEXT:    ret i32 [[P]]
219 ; CHECK:       next:
220 ; CHECK-NEXT:    ret i32 0
222 entry:
223   %cmp = icmp slt i32 %s, 0
224   br i1 %cmp, label %negative, label %out
226 negative:
227   switch i32 %s, label %out [
228   i32 0, label %out
229   i32 1, label %out
230   i32 -1, label %next
231   i32 -2, label %next
232   i32 2, label %out
233   i32 3, label %out
234   ]
236 out:
237   %p = phi i32 [ 1, %entry ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ]
238   ret i32 %p
240 next:
241   %q = phi i32 [ 0, %negative ], [ 0, %negative ]
242   ret i32 %q
245 define i32 @switch2(i32 %s) {
246 ; CHECK-LABEL: @switch2(
247 ; CHECK-NEXT:  entry:
248 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[S:%.*]], 0
249 ; CHECK-NEXT:    br i1 [[CMP]], label [[POSITIVE:%.*]], label [[OUT:%.*]]
250 ; CHECK:       positive:
251 ; CHECK-NEXT:    br label [[OUT]]
252 ; CHECK:       out:
253 ; CHECK-NEXT:    [[P:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 1, [[POSITIVE]] ]
254 ; CHECK-NEXT:    ret i32 [[P]]
255 ; CHECK:       next:
256 ; CHECK-NEXT:    ret i32 0
258 entry:
259   %cmp = icmp sgt i32 %s, 0
260   br i1 %cmp, label %positive, label %out
262 positive:
263   switch i32 %s, label %out [
264   i32 0, label %out
265   i32 -1, label %next
266   i32 -2, label %next
267   ]
269 out:
270   %p = phi i32 [ -1, %entry ], [ 1, %positive ], [ 1, %positive ]
271   ret i32 %p
273 next:
274   %q = phi i32 [ 0, %positive ], [ 0, %positive ]
275   ret i32 %q
278 define i32 @switch3(i32 %s) {
279 ; CHECK-LABEL: @switch3(
280 ; CHECK-NEXT:  entry:
281 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[S:%.*]], 0
282 ; CHECK-NEXT:    br i1 [[CMP]], label [[POSITIVE:%.*]], label [[OUT:%.*]]
283 ; CHECK:       positive:
284 ; CHECK-NEXT:    br label [[OUT]]
285 ; CHECK:       out:
286 ; CHECK-NEXT:    [[P:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 1, [[POSITIVE]] ]
287 ; CHECK-NEXT:    ret i32 [[P]]
288 ; CHECK:       next:
289 ; CHECK-NEXT:    ret i32 0
291 entry:
292   %cmp = icmp sgt i32 %s, 0
293   br i1 %cmp, label %positive, label %out
295 positive:
296   switch i32 %s, label %out [
297   i32 -1, label %out
298   i32 -2, label %next
299   i32 -3, label %next
300   ]
302 out:
303   %p = phi i32 [ -1, %entry ], [ 1, %positive ], [ 1, %positive ]
304   ret i32 %p
306 next:
307   %q = phi i32 [ 0, %positive ], [ 0, %positive ]
308   ret i32 %q
311 define void @switch4(i32 %s) {
312 ; CHECK-LABEL: @switch4(
313 ; CHECK-NEXT:  entry:
314 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[S:%.*]], 0
315 ; CHECK-NEXT:    br i1 [[CMP]], label [[ZERO:%.*]], label [[OUT:%.*]]
316 ; CHECK:       zero:
317 ; CHECK-NEXT:    br label [[NEXT:%.*]]
318 ; CHECK:       out:
319 ; CHECK-NEXT:    ret void
320 ; CHECK:       next:
321 ; CHECK-NEXT:    ret void
323 entry:
324   %cmp = icmp eq i32 %s, 0
325   br i1 %cmp, label %zero, label %out
327 zero:
328   switch i32 %s, label %out [
329   i32 0, label %next
330   i32 1, label %out
331   i32 -1, label %out
332   ]
334 out:
335   ret void
337 next:
338   ret void
341 define void @switch_nonzero_zext(i8 %s) {
342 ; CHECK-LABEL: @switch_nonzero_zext(
343 ; CHECK-NEXT:  entry:
344 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[S:%.*]], 0
345 ; CHECK-NEXT:    br i1 [[CMP]], label [[SWITCH:%.*]], label [[EXIT:%.*]]
346 ; CHECK:       switch:
347 ; CHECK-NEXT:    [[S_EXT:%.*]] = zext i8 [[S]] to i32
348 ; CHECK-NEXT:    br label [[EXIT]]
349 ; CHECK:       exit:
350 ; CHECK-NEXT:    ret void
351 ; CHECK:       unreachable:
352 ; CHECK-NEXT:    ret void
354 entry:
355   %cmp = icmp ne i8 %s, 0
356   br i1 %cmp, label %switch, label %exit
358 switch:
359   %s.ext = zext i8 %s to i32
360   switch i32 %s.ext, label %exit [
361   i32 0, label %unreachable
362   i32 1, label %exit
363   i32 -1, label %exit
364   ]
366 exit:
367   ret void
369 unreachable:
370   ret void
373 define void @switch_assume_nonzero(i32 %s) {
374 ; CHECK-LABEL: @switch_assume_nonzero(
375 ; CHECK-NEXT:  entry:
376 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[S:%.*]], 0
377 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
378 ; CHECK-NEXT:    br label [[EXIT:%.*]]
379 ; CHECK:       exit:
380 ; CHECK-NEXT:    ret void
381 ; CHECK:       unreachable:
382 ; CHECK-NEXT:    ret void
384 entry:
385   %cmp = icmp ne i32 %s, 0
386   call void @llvm.assume(i1 %cmp)
387   switch i32 %s, label %exit [
388   i32 0, label %unreachable
389   i32 1, label %exit
390   i32 -1, label %exit
391   ]
393 exit:
394   ret void
396 unreachable:
397   ret void
400 define void @switch_nonzero_phi(i1 %cond) {
401 ; CHECK-LABEL: @switch_nonzero_phi(
402 ; CHECK-NEXT:  entry:
403 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
404 ; CHECK:       if:
405 ; CHECK-NEXT:    br label [[SWITCH:%.*]]
406 ; CHECK:       else:
407 ; CHECK-NEXT:    br label [[SWITCH]]
408 ; CHECK:       switch:
409 ; CHECK-NEXT:    [[S:%.*]] = phi i32 [ 1, [[IF]] ], [ -1, [[ELSE]] ]
410 ; CHECK-NEXT:    br label [[EXIT:%.*]]
411 ; CHECK:       exit:
412 ; CHECK-NEXT:    ret void
413 ; CHECK:       unreachable:
414 ; CHECK-NEXT:    ret void
416 entry:
417   br i1 %cond, label %if, label %else
420   br label %switch
422 else:
423   br label %switch
425 switch:
426   %s = phi i32 [ 1, %if ], [ -1, %else ]
427   switch i32 %s, label %exit [
428   i32 0, label %unreachable
429   i32 1, label %exit
430   i32 -1, label %exit
431   ]
433 exit:
434   ret void
436 unreachable:
437   ret void
440 define i32 @switch_range(i32 %cond) {
441 ; CHECK-LABEL: @switch_range(
442 ; CHECK-NEXT:  entry:
443 ; CHECK-NEXT:    [[S:%.*]] = urem i32 [[COND:%.*]], 3
444 ; CHECK-NEXT:    [[S1:%.*]] = add nuw nsw i32 [[S]], 1
445 ; CHECK-NEXT:    switch i32 [[S1]], label [[UNREACHABLE:%.*]] [
446 ; CHECK-NEXT:      i32 1, label [[EXIT1:%.*]]
447 ; CHECK-NEXT:      i32 2, label [[EXIT2:%.*]]
448 ; CHECK-NEXT:      i32 3, label [[EXIT1]]
449 ; CHECK-NEXT:    ]
450 ; CHECK:       exit1:
451 ; CHECK-NEXT:    ret i32 1
452 ; CHECK:       exit2:
453 ; CHECK-NEXT:    ret i32 2
454 ; CHECK:       unreachable:
455 ; CHECK-NEXT:    ret i32 0
457 entry:
458   %s = urem i32 %cond, 3
459   %s1 = add i32 %s, 1
460   switch i32 %s1, label %unreachable [
461   i32 1, label %exit1
462   i32 2, label %exit2
463   i32 3, label %exit1
464   ]
466 exit1:
467   ret i32 1
468 exit2:
469   ret i32 2
470 unreachable:
471   ret i32 0
474 ; If the cases do not cover the entire range of the
475 ; switch condition, we should not change the default.
477 define i32 @switch_range_not_full(i32 %cond) {
478 ; CHECK-LABEL: @switch_range_not_full(
479 ; CHECK-NEXT:  entry:
480 ; CHECK-NEXT:    [[S:%.*]] = urem i32 [[COND:%.*]], 3
481 ; CHECK-NEXT:    [[S1:%.*]] = add nuw nsw i32 [[S]], 1
482 ; CHECK-NEXT:    switch i32 [[S1]], label [[UNREACHABLE:%.*]] [
483 ; CHECK-NEXT:      i32 1, label [[EXIT1:%.*]]
484 ; CHECK-NEXT:      i32 3, label [[EXIT2:%.*]]
485 ; CHECK-NEXT:    ]
486 ; CHECK:       exit1:
487 ; CHECK-NEXT:    ret i32 1
488 ; CHECK:       exit2:
489 ; CHECK-NEXT:    ret i32 2
490 ; CHECK:       unreachable:
491 ; CHECK-NEXT:    ret i32 0
493 entry:
494   %s = urem i32 %cond, 3
495   %s1 = add i32 %s, 1
496   switch i32 %s1, label %unreachable [
497   i32 1, label %exit1
498   i32 3, label %exit2
499   ]
501 exit1:
502   ret i32 1
503 exit2:
504   ret i32 2
505 unreachable:
506   ret i32 0
509 ; PR51531
511 define i8 @switch_defaultdest_multipleuse(i8 %t0) {
512 ; CHECK-LABEL: @switch_defaultdest_multipleuse(
513 ; CHECK-NEXT:  entry:
514 ; CHECK-NEXT:    [[O:%.*]] = or i8 [[T0:%.*]], 1
515 ; CHECK-NEXT:    [[R:%.*]] = srem i8 1, [[O]]
516 ; CHECK-NEXT:    switch i8 [[R]], label [[EXIT:%.*]] [
517 ; CHECK-NEXT:      i8 0, label [[EXIT]]
518 ; CHECK-NEXT:      i8 1, label [[EXIT]]
519 ; CHECK-NEXT:    ]
520 ; CHECK:       exit:
521 ; CHECK-NEXT:    ret i8 0
523 entry:
524   %o = or i8 %t0, 1
525   %r = srem i8 1, %o
526   switch i8 %r, label %exit [
527   i8 0, label %exit
528   i8 1, label %exit
529   ]
531 exit:
532   ret i8 0
535 define i1 @arg_attribute(ptr nonnull %a) {
536 ; CHECK-LABEL: @arg_attribute(
537 ; CHECK-NEXT:    ret i1 false
539   %cmp = icmp eq i8* %a, null
540   ret i1 %cmp
543 declare nonnull ptr @return_nonnull()
544 define i1 @call_attribute() {
545 ; CHECK-LABEL: @call_attribute(
546 ; CHECK-NEXT:    [[A:%.*]] = call ptr @return_nonnull()
547 ; CHECK-NEXT:    ret i1 false
549   %a = call i8* @return_nonnull()
550   %cmp = icmp eq ptr %a, null
551   ret i1 %cmp
554 define i1 @umin(i32 %a, i32 %b) {
555 ; CHECK-LABEL: @umin(
556 ; CHECK-NEXT:  entry:
557 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 5
558 ; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
559 ; CHECK:       a_guard:
560 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[B:%.*]], 20
561 ; CHECK-NEXT:    br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]]
562 ; CHECK:       b_guard:
563 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ult i32 [[A]], [[B]]
564 ; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
565 ; CHECK-NEXT:    ret i1 false
566 ; CHECK:       out:
567 ; CHECK-NEXT:    ret i1 false
569 entry:
570   %cmp = icmp ult i32 %a, 5
571   br i1 %cmp, label %a_guard, label %out
573 a_guard:
574   %cmp2 = icmp ult i32 %b, 20
575   br i1 %cmp2, label %b_guard, label %out
577 b_guard:
578   %sel_cmp = icmp ult i32 %a, %b
579   %min = select i1 %sel_cmp, i32 %a, i32 %b
580   %res = icmp eq i32 %min, 7
581   ret i1 %res
582 out:
583   ret i1 false
586 define i1 @smin(i32 %a, i32 %b) {
587 ; CHECK-LABEL: @smin(
588 ; CHECK-NEXT:  entry:
589 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 5
590 ; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
591 ; CHECK:       a_guard:
592 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[B:%.*]], 20
593 ; CHECK-NEXT:    br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]]
594 ; CHECK:       b_guard:
595 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ule i32 [[A]], [[B]]
596 ; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
597 ; CHECK-NEXT:    ret i1 false
598 ; CHECK:       out:
599 ; CHECK-NEXT:    ret i1 false
601 entry:
602   %cmp = icmp ult i32 %a, 5
603   br i1 %cmp, label %a_guard, label %out
605 a_guard:
606   %cmp2 = icmp ult i32 %b, 20
607   br i1 %cmp2, label %b_guard, label %out
609 b_guard:
610   %sel_cmp = icmp sle i32 %a, %b
611   %min = select i1 %sel_cmp, i32 %a, i32 %b
612   %res = icmp eq i32 %min, 7
613   ret i1 %res
614 out:
615   ret i1 false
618 define i1 @smax(i32 %a, i32 %b) {
619 ; CHECK-LABEL: @smax(
620 ; CHECK-NEXT:  entry:
621 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5
622 ; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
623 ; CHECK:       a_guard:
624 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[B:%.*]], 20
625 ; CHECK-NEXT:    br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]]
626 ; CHECK:       b_guard:
627 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp uge i32 [[A]], [[B]]
628 ; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
629 ; CHECK-NEXT:    ret i1 false
630 ; CHECK:       out:
631 ; CHECK-NEXT:    ret i1 false
633 entry:
634   %cmp = icmp sgt i32 %a, 5
635   br i1 %cmp, label %a_guard, label %out
637 a_guard:
638   %cmp2 = icmp sgt i32 %b, 20
639   br i1 %cmp2, label %b_guard, label %out
641 b_guard:
642   %sel_cmp = icmp sge i32 %a, %b
643   %max = select i1 %sel_cmp, i32 %a, i32 %b
644   %res = icmp eq i32 %max, 7
645   ret i1 %res
646 out:
647   ret i1 false
650 define i1 @umax(i32 %a, i32 %b) {
651 ; CHECK-LABEL: @umax(
652 ; CHECK-NEXT:  entry:
653 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5
654 ; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
655 ; CHECK:       a_guard:
656 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[B:%.*]], 20
657 ; CHECK-NEXT:    br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]]
658 ; CHECK:       b_guard:
659 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp uge i32 [[A]], [[B]]
660 ; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
661 ; CHECK-NEXT:    ret i1 false
662 ; CHECK:       out:
663 ; CHECK-NEXT:    ret i1 false
665 entry:
666   %cmp = icmp sgt i32 %a, 5
667   br i1 %cmp, label %a_guard, label %out
669 a_guard:
670   %cmp2 = icmp sgt i32 %b, 20
671   br i1 %cmp2, label %b_guard, label %out
673 b_guard:
674   %sel_cmp = icmp uge i32 %a, %b
675   %max = select i1 %sel_cmp, i32 %a, i32 %b
676   %res = icmp eq i32 %max, 7
677   ret i1 %res
678 out:
679   ret i1 false
682 define i1 @umin_lhs_overdefined_rhs_const(i32 %a) {
683 ; CHECK-LABEL: @umin_lhs_overdefined_rhs_const(
684 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 42
685 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[A]], i32 42
686 ; CHECK-NEXT:    ret i1 true
688   %cmp = icmp ult i32 %a, 42
689   %sel = select i1 %cmp, i32 %a, i32 42
690   %cmp2 = icmp ule i32 %sel, 42
691   ret i1 %cmp2
694 define i1 @umin_rhs_overdefined_lhs_const(i32 %a) {
695 ; CHECK-LABEL: @umin_rhs_overdefined_lhs_const(
696 ; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[A:%.*]], 42
697 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 42, i32 [[A]]
698 ; CHECK-NEXT:    ret i1 true
700   %cmp = icmp uge i32 %a, 42
701   %sel = select i1 %cmp, i32 42, i32 %a
702   %cmp2 = icmp ule i32 %sel, 42
703   ret i1 %cmp2
706 define i1 @umin_lhs_overdefined_rhs_range(i32 %a, i32 %b) {
707 ; CHECK-LABEL: @umin_lhs_overdefined_rhs_range(
708 ; CHECK-NEXT:    [[ASSUME:%.*]] = icmp ult i32 [[B:%.*]], 42
709 ; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME]])
710 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], [[B]]
711 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[B]]
712 ; CHECK-NEXT:    ret i1 true
714   %assume = icmp ult i32 %b, 42
715   call void @llvm.assume(i1 %assume)
716   %cmp = icmp ult i32 %a, %b
717   %sel = select i1 %cmp, i32 %a, i32 %b
718   %cmp2 = icmp ult i32 %sel, 42
719   ret i1 %cmp2
722 define i1 @umin_rhs_overdefined_lhs_range(i32 %a, i32 %b) {
723 ; CHECK-LABEL: @umin_rhs_overdefined_lhs_range(
724 ; CHECK-NEXT:    [[ASSUME:%.*]] = icmp ult i32 [[B:%.*]], 42
725 ; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME]])
726 ; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[A:%.*]], [[B]]
727 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[B]], i32 [[A]]
728 ; CHECK-NEXT:    ret i1 true
730   %assume = icmp ult i32 %b, 42
731   call void @llvm.assume(i1 %assume)
732   %cmp = icmp uge i32 %a, %b
733   %sel = select i1 %cmp, i32 %b, i32 %a
734   %cmp2 = icmp ult i32 %sel, 42
735   ret i1 %cmp2
738 define i1 @clamp_low1(i32 noundef %a) {
739 ; CHECK-LABEL: @clamp_low1(
740 ; CHECK-NEXT:  entry:
741 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5
742 ; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
743 ; CHECK:       a_guard:
744 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5
745 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], -1
746 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]]
747 ; CHECK-NEXT:    ret i1 false
748 ; CHECK:       out:
749 ; CHECK-NEXT:    ret i1 false
751 entry:
752   %cmp = icmp sge i32 %a, 5
753   br i1 %cmp, label %a_guard, label %out
755 a_guard:
756   %sel_cmp = icmp eq i32 %a, 5
757   %add = add i32 %a, -1
758   %sel = select i1 %sel_cmp, i32 5, i32 %add
759   %res = icmp eq i32 %sel, 4
760   ret i1 %res
761 out:
762   ret i1 false
765 define i1 @clamp_low2(i32 noundef %a) {
766 ; CHECK-LABEL: @clamp_low2(
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 ne i32 [[A]], 5
772 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], -1
773 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5
774 ; CHECK-NEXT:    ret i1 false
775 ; CHECK:       out:
776 ; CHECK-NEXT:    ret i1 false
778 entry:
779   %cmp = icmp sge i32 %a, 5
780   br i1 %cmp, label %a_guard, label %out
782 a_guard:
783   %sel_cmp = icmp ne i32 %a, 5
784   %add = add i32 %a, -1
785   %sel = select i1 %sel_cmp, i32 %add, i32 5
786   %res = icmp eq i32 %sel, 4
787   ret i1 %res
788 out:
789   ret i1 false
792 define i1 @clamp_low3(i32 noundef %a) {
793 ; CHECK-LABEL: @clamp_low3(
794 ; CHECK-NEXT:  entry:
795 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5
796 ; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
797 ; CHECK:       a_guard:
798 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ugt i32 [[A]], 5
799 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], -1
800 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5
801 ; CHECK-NEXT:    ret i1 false
802 ; CHECK:       out:
803 ; CHECK-NEXT:    ret i1 false
805 entry:
806   %cmp = icmp sge i32 %a, 5
807   br i1 %cmp, label %a_guard, label %out
809 a_guard:
810   %sel_cmp = icmp sgt i32 %a, 5
811   %add = add i32 %a, -1
812   %sel = select i1 %sel_cmp, i32 %add, i32 5
813   %res = icmp eq i32 %sel, 4
814   ret i1 %res
815 out:
816   ret i1 false
819 define i1 @clamp_low4(i32 noundef %a) {
820 ; CHECK-LABEL: @clamp_low4(
821 ; CHECK-NEXT:  entry:
822 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5
823 ; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
824 ; CHECK:       a_guard:
825 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ule i32 [[A]], 5
826 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], -1
827 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]]
828 ; CHECK-NEXT:    ret i1 false
829 ; CHECK:       out:
830 ; CHECK-NEXT:    ret i1 false
832 entry:
833   %cmp = icmp sge i32 %a, 5
834   br i1 %cmp, label %a_guard, label %out
836 a_guard:
837   %sel_cmp = icmp sle i32 %a, 5
838   %add = add i32 %a, -1
839   %sel = select i1 %sel_cmp, i32 5, i32 %add
840   %res = icmp eq i32 %sel, 4
841   ret i1 %res
842 out:
843   ret i1 false
846 define i1 @clamp_high1(i32 noundef %a) {
847 ; CHECK-LABEL: @clamp_high1(
848 ; CHECK-NEXT:  entry:
849 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5
850 ; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
851 ; CHECK:       a_guard:
852 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5
853 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
854 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]]
855 ; CHECK-NEXT:    ret i1 false
856 ; CHECK:       out:
857 ; CHECK-NEXT:    ret i1 false
859 entry:
860   %cmp = icmp sle i32 %a, 5
861   br i1 %cmp, label %a_guard, label %out
863 a_guard:
864   %sel_cmp = icmp eq i32 %a, 5
865   %add = add i32 %a, 1
866   %sel = select i1 %sel_cmp, i32 5, i32 %add
867   %res = icmp eq i32 %sel, 6
868   ret i1 %res
869 out:
870   ret i1 false
873 define i1 @clamp_high2(i32 noundef %a) {
874 ; CHECK-LABEL: @clamp_high2(
875 ; CHECK-NEXT:  entry:
876 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5
877 ; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
878 ; CHECK:       a_guard:
879 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5
880 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
881 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5
882 ; CHECK-NEXT:    ret i1 false
883 ; CHECK:       out:
884 ; CHECK-NEXT:    ret i1 false
886 entry:
887   %cmp = icmp sle i32 %a, 5
888   br i1 %cmp, label %a_guard, label %out
890 a_guard:
891   %sel_cmp = icmp ne i32 %a, 5
892   %add = add i32 %a, 1
893   %sel = select i1 %sel_cmp, i32 %add, i32 5
894   %res = icmp eq i32 %sel, 6
895   ret i1 %res
896 out:
897   ret i1 false
900 define i1 @clamp_high3(i32 noundef %a) {
901 ; CHECK-LABEL: @clamp_high3(
902 ; CHECK-NEXT:  entry:
903 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5
904 ; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
905 ; CHECK:       a_guard:
906 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp slt i32 [[A]], 5
907 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
908 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5
909 ; CHECK-NEXT:    ret i1 false
910 ; CHECK:       out:
911 ; CHECK-NEXT:    ret i1 false
913 entry:
914   %cmp = icmp sle i32 %a, 5
915   br i1 %cmp, label %a_guard, label %out
917 a_guard:
918   %sel_cmp = icmp slt i32 %a, 5
919   %add = add i32 %a, 1
920   %sel = select i1 %sel_cmp, i32 %add, i32 5
921   %res = icmp eq i32 %sel, 6
922   ret i1 %res
923 out:
924   ret i1 false
927 define i1 @clamp_high4(i32 noundef %a) {
928 ; CHECK-LABEL: @clamp_high4(
929 ; CHECK-NEXT:  entry:
930 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5
931 ; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
932 ; CHECK:       a_guard:
933 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp sge i32 [[A]], 5
934 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
935 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]]
936 ; CHECK-NEXT:    ret i1 false
937 ; CHECK:       out:
938 ; CHECK-NEXT:    ret i1 false
940 entry:
941   %cmp = icmp sle i32 %a, 5
942   br i1 %cmp, label %a_guard, label %out
944 a_guard:
945   %sel_cmp = icmp sge i32 %a, 5
946   %add = add i32 %a, 1
947   %sel = select i1 %sel_cmp, i32 5, i32 %add
948   %res = icmp eq i32 %sel, 6
949   ret i1 %res
950 out:
951   ret i1 false
954 ; Just showing arbitrary constants work, not really a clamp
955 define i1 @not_clamp_high(i32 noundef %a) {
956 ; CHECK-LABEL: @not_clamp_high(
957 ; CHECK-NEXT:  entry:
958 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5
959 ; CHECK-NEXT:    br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]]
960 ; CHECK:       a_guard:
961 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5
962 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 100
963 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5
964 ; CHECK-NEXT:    ret i1 false
965 ; CHECK:       out:
966 ; CHECK-NEXT:    ret i1 false
968 entry:
969   %cmp = icmp sle i32 %a, 5
970   br i1 %cmp, label %a_guard, label %out
972 a_guard:
973   %sel_cmp = icmp ne i32 %a, 5
974   %add = add i32 %a, 100
975   %sel = select i1 %sel_cmp, i32 %add, i32 5
976   %res = icmp eq i32 %sel, 105
977   ret i1 %res
978 out:
979   ret i1 false
982 define void @abs1(i32 %a, ptr %p) {
983 ; CHECK-LABEL: @abs1(
984 ; CHECK-NEXT:  entry:
985 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A:%.*]], 10
986 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[A]], -20
987 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
988 ; CHECK-NEXT:    br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]]
989 ; CHECK:       guard:
990 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 0, [[A]]
991 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], 0
992 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[A]]
993 ; CHECK-NEXT:    store i1 true, ptr [[P:%.*]], align 1
994 ; CHECK-NEXT:    [[C2:%.*]] = icmp ult i32 [[ABS]], 19
995 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
996 ; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
997 ; CHECK-NEXT:    [[C4:%.*]] = icmp uge i32 [[ABS]], 1
998 ; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
999 ; CHECK-NEXT:    br label [[EXIT]]
1000 ; CHECK:       exit:
1001 ; CHECK-NEXT:    ret void
1003 entry:
1004   %cmp1 = icmp slt i32 %a, 10
1005   %cmp2 = icmp sgt i32 %a, -20
1006   %and = and i1 %cmp1, %cmp2
1007   br i1 %and, label %guard, label %exit
1009 guard:
1010   %sub = sub i32 0, %a
1011   %cmp = icmp slt i32 %a, 0
1012   %abs = select i1 %cmp, i32 %sub, i32 %a
1013   %c1 = icmp slt i32 %abs, 20
1014   store i1 %c1, ptr %p
1015   %c2 = icmp slt i32 %abs, 19
1016   store i1 %c2, ptr %p
1017   %c3 = icmp sge i32 %abs, 0
1018   store i1 %c3, ptr %p
1019   %c4 = icmp sge i32 %abs, 1
1020   store i1 %c4, ptr %p
1021   br label %exit
1023 exit:
1024   ret void
1027 define void @abs2(i32 %a, ptr %p) {
1028 ; CHECK-LABEL: @abs2(
1029 ; CHECK-NEXT:  entry:
1030 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A:%.*]], 10
1031 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[A]], -20
1032 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
1033 ; CHECK-NEXT:    br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1034 ; CHECK:       guard:
1035 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 0, [[A]]
1036 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A]], 0
1037 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[SUB]]
1038 ; CHECK-NEXT:    store i1 true, ptr [[P:%.*]], align 1
1039 ; CHECK-NEXT:    [[C2:%.*]] = icmp ult i32 [[ABS]], 19
1040 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1041 ; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1042 ; CHECK-NEXT:    [[C4:%.*]] = icmp uge i32 [[ABS]], 1
1043 ; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
1044 ; CHECK-NEXT:    br label [[EXIT]]
1045 ; CHECK:       exit:
1046 ; CHECK-NEXT:    ret void
1048 entry:
1049   %cmp1 = icmp slt i32 %a, 10
1050   %cmp2 = icmp sgt i32 %a, -20
1051   %and = and i1 %cmp1, %cmp2
1052   br i1 %and, label %guard, label %exit
1054 guard:
1055   %sub = sub i32 0, %a
1056   %cmp = icmp sge i32 %a, 0
1057   %abs = select i1 %cmp, i32 %a, i32 %sub
1058   %c1 = icmp slt i32 %abs, 20
1059   store i1 %c1, ptr %p
1060   %c2 = icmp slt i32 %abs, 19
1061   store i1 %c2, ptr %p
1062   %c3 = icmp sge i32 %abs, 0
1063   store i1 %c3, ptr %p
1064   %c4 = icmp sge i32 %abs, 1
1065   store i1 %c4, ptr %p
1066   br label %exit
1068 exit:
1069   ret void
1072 define void @nabs1(i32 %a, ptr %p) {
1073 ; CHECK-LABEL: @nabs1(
1074 ; CHECK-NEXT:  entry:
1075 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A:%.*]], 10
1076 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[A]], -20
1077 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
1078 ; CHECK-NEXT:    br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1079 ; CHECK:       guard:
1080 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 0, [[A]]
1081 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], 0
1082 ; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[A]]
1083 ; CHECK-NEXT:    store i1 true, ptr [[P:%.*]], align 1
1084 ; CHECK-NEXT:    [[C2:%.*]] = icmp sgt i32 [[NABS]], -19
1085 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1086 ; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1087 ; CHECK-NEXT:    [[C4:%.*]] = icmp sle i32 [[NABS]], -1
1088 ; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
1089 ; CHECK-NEXT:    br label [[EXIT]]
1090 ; CHECK:       exit:
1091 ; CHECK-NEXT:    ret void
1093 entry:
1094   %cmp1 = icmp slt i32 %a, 10
1095   %cmp2 = icmp sgt i32 %a, -20
1096   %and = and i1 %cmp1, %cmp2
1097   br i1 %and, label %guard, label %exit
1099 guard:
1100   %sub = sub i32 0, %a
1101   %cmp = icmp sgt i32 %a, 0
1102   %nabs = select i1 %cmp, i32 %sub, i32 %a
1103   %c1 = icmp sgt i32 %nabs, -20
1104   store i1 %c1, ptr %p
1105   %c2 = icmp sgt i32 %nabs, -19
1106   store i1 %c2, ptr %p
1107   %c3 = icmp sle i32 %nabs, 0
1108   store i1 %c3, ptr %p
1109   %c4 = icmp sle i32 %nabs, -1
1110   store i1 %c4, ptr %p
1111   br label %exit
1113 exit:
1114   ret void
1117 define void @nabs2(i32 %a, ptr %p) {
1118 ; CHECK-LABEL: @nabs2(
1119 ; CHECK-NEXT:  entry:
1120 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A:%.*]], 10
1121 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[A]], -20
1122 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
1123 ; CHECK-NEXT:    br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1124 ; CHECK:       guard:
1125 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 0, [[A]]
1126 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], 0
1127 ; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[SUB]]
1128 ; CHECK-NEXT:    store i1 true, ptr [[P:%.*]], align 1
1129 ; CHECK-NEXT:    [[C2:%.*]] = icmp sgt i32 [[NABS]], -19
1130 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1131 ; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1132 ; CHECK-NEXT:    [[C4:%.*]] = icmp sle i32 [[NABS]], -1
1133 ; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
1134 ; CHECK-NEXT:    br label [[EXIT]]
1135 ; CHECK:       exit:
1136 ; CHECK-NEXT:    ret void
1138 entry:
1139   %cmp1 = icmp slt i32 %a, 10
1140   %cmp2 = icmp sgt i32 %a, -20
1141   %and = and i1 %cmp1, %cmp2
1142   br i1 %and, label %guard, label %exit
1144 guard:
1145   %sub = sub i32 0, %a
1146   %cmp = icmp slt i32 %a, 0
1147   %nabs = select i1 %cmp, i32 %a, i32 %sub
1148   %c1 = icmp sgt i32 %nabs, -20
1149   store i1 %c1, ptr %p
1150   %c2 = icmp sgt i32 %nabs, -19
1151   store i1 %c2, ptr %p
1152   %c3 = icmp sle i32 %nabs, 0
1153   store i1 %c3, ptr %p
1154   %c4 = icmp sle i32 %nabs, -1
1155   store i1 %c4, ptr %p
1156   br label %exit
1158 exit:
1159   ret void
1162 define i1 @zext_unknown(i8 %a) {
1163 ; CHECK-LABEL: @zext_unknown(
1164 ; CHECK-NEXT:  entry:
1165 ; CHECK-NEXT:    [[A32:%.*]] = zext i8 [[A:%.*]] to i32
1166 ; CHECK-NEXT:    ret i1 true
1168 entry:
1169   %a32 = zext i8 %a to i32
1170   %cmp = icmp sle i32 %a32, 256
1171   ret i1 %cmp
1174 define i1 @trunc_unknown(i32 %a) {
1175 ; CHECK-LABEL: @trunc_unknown(
1176 ; CHECK-NEXT:  entry:
1177 ; CHECK-NEXT:    [[A8:%.*]] = trunc i32 [[A:%.*]] to i8
1178 ; CHECK-NEXT:    [[A32:%.*]] = sext i8 [[A8]] to i32
1179 ; CHECK-NEXT:    ret i1 true
1181 entry:
1182   %a8 = trunc i32 %a to i8
1183   %a32 = sext i8 %a8 to i32
1184   %cmp = icmp sle i32 %a32, 128
1185   ret i1 %cmp
1188 define void @trunc_icmp_ule(i32 %x, ptr %p) {
1189 ; CHECK-LABEL: @trunc_icmp_ule(
1190 ; CHECK-NEXT:    [[T:%.*]] = trunc i32 [[X:%.*]] to i8
1191 ; CHECK-NEXT:    [[C:%.*]] = icmp uge i8 [[T]], 5
1192 ; CHECK-NEXT:    br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]]
1193 ; CHECK:       true:
1194 ; CHECK-NEXT:    store i1 true, ptr [[P:%.*]], align 1
1195 ; CHECK-NEXT:    [[C2:%.*]] = icmp ugt i32 [[X]], 5
1196 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1197 ; CHECK-NEXT:    [[C3:%.*]] = icmp ule i32 [[X]], 5
1198 ; CHECK-NEXT:    store i1 [[C3]], ptr [[P]], align 1
1199 ; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1200 ; CHECK-NEXT:    ret void
1201 ; CHECK:       false:
1202 ; CHECK-NEXT:    [[C1_2:%.*]] = icmp uge i32 [[X]], 5
1203 ; CHECK-NEXT:    store i1 [[C1_2]], ptr [[P]], align 1
1204 ; CHECK-NEXT:    [[C2_2:%.*]] = icmp ugt i32 [[X]], 5
1205 ; CHECK-NEXT:    store i1 [[C2_2]], ptr [[P]], align 1
1206 ; CHECK-NEXT:    [[C3_2:%.*]] = icmp ule i32 [[X]], 5
1207 ; CHECK-NEXT:    store i1 [[C3_2]], ptr [[P]], align 1
1208 ; CHECK-NEXT:    [[C4_2:%.*]] = icmp ult i32 [[X]], 5
1209 ; CHECK-NEXT:    store i1 [[C4_2]], ptr [[P]], align 1
1210 ; CHECK-NEXT:    ret void
1212   %t = trunc i32 %x to i8
1213   %c = icmp uge i8 %t, 5
1214   br i1 %c, label %true, label %false
1216 true:
1217   %c1 = icmp uge i32 %x, 5
1218   store i1 %c1, ptr %p
1219   %c2 = icmp ugt i32 %x, 5
1220   store i1 %c2, ptr %p
1221   %c3 = icmp ule i32 %x, 5
1222   store i1 %c3, ptr %p
1223   %c4 = icmp ult i32 %x, 5
1224   store i1 %c4, ptr %p
1225   ret void
1227 false:
1228   %c1.2 = icmp uge i32 %x, 5
1229   store i1 %c1.2, ptr %p
1230   %c2.2 = icmp ugt i32 %x, 5
1231   store i1 %c2.2, ptr %p
1232   %c3.2 = icmp ule i32 %x, 5
1233   store i1 %c3.2, ptr %p
1234   %c4.2 = icmp ult i32 %x, 5
1235   store i1 %c4.2, ptr %p
1236   ret void
1239 define void @trunc_icmp_eq(i32 %x, ptr %p) {
1240 ; CHECK-LABEL: @trunc_icmp_eq(
1241 ; CHECK-NEXT:    [[T:%.*]] = trunc i32 [[X:%.*]] to i8
1242 ; CHECK-NEXT:    [[C:%.*]] = icmp eq i8 [[T]], 5
1243 ; CHECK-NEXT:    br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]]
1244 ; CHECK:       true:
1245 ; CHECK-NEXT:    store i1 true, ptr [[P:%.*]], align 1
1246 ; CHECK-NEXT:    [[C2:%.*]] = icmp ugt i32 [[X]], 5
1247 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1248 ; CHECK-NEXT:    [[C3:%.*]] = icmp ule i32 [[X]], 5
1249 ; CHECK-NEXT:    store i1 [[C3]], ptr [[P]], align 1
1250 ; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1251 ; CHECK-NEXT:    ret void
1252 ; CHECK:       false:
1253 ; CHECK-NEXT:    [[C1_2:%.*]] = icmp uge i32 [[X]], 5
1254 ; CHECK-NEXT:    store i1 [[C1_2]], ptr [[P]], align 1
1255 ; CHECK-NEXT:    [[C2_2:%.*]] = icmp ugt i32 [[X]], 5
1256 ; CHECK-NEXT:    store i1 [[C2_2]], ptr [[P]], align 1
1257 ; CHECK-NEXT:    [[C3_2:%.*]] = icmp ule i32 [[X]], 5
1258 ; CHECK-NEXT:    store i1 [[C3_2]], ptr [[P]], align 1
1259 ; CHECK-NEXT:    [[C4_2:%.*]] = icmp ult i32 [[X]], 5
1260 ; CHECK-NEXT:    store i1 [[C4_2]], ptr [[P]], align 1
1261 ; CHECK-NEXT:    ret void
1263   %t = trunc i32 %x to i8
1264   %c = icmp eq i8 %t, 5
1265   br i1 %c, label %true, label %false
1267 true:
1268   %c1 = icmp uge i32 %x, 5
1269   store i1 %c1, ptr %p
1270   %c2 = icmp ugt i32 %x, 5
1271   store i1 %c2, ptr %p
1272   %c3 = icmp ule i32 %x, 5
1273   store i1 %c3, ptr %p
1274   %c4 = icmp ult i32 %x, 5
1275   store i1 %c4, ptr %p
1276   ret void
1278 false:
1279   %c1.2 = icmp uge i32 %x, 5
1280   store i1 %c1.2, ptr %p
1281   %c2.2 = icmp ugt i32 %x, 5
1282   store i1 %c2.2, ptr %p
1283   %c3.2 = icmp ule i32 %x, 5
1284   store i1 %c3.2, ptr %p
1285   %c4.2 = icmp ult i32 %x, 5
1286   store i1 %c4.2, ptr %p
1287   ret void
1290 ; TODO: missed optimization
1291 ; Make sure we exercise non-integer inputs to unary operators (i.e. crash check).
1292 define i1 @bitcast_unknown(float %a) {
1293 ; CHECK-LABEL: @bitcast_unknown(
1294 ; CHECK-NEXT:  entry:
1295 ; CHECK-NEXT:    [[A32:%.*]] = bitcast float [[A:%.*]] to i32
1296 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A32]], 128
1297 ; CHECK-NEXT:    ret i1 [[CMP]]
1299 entry:
1300   %a32 = bitcast float %a to i32
1301   %cmp = icmp sle i32 %a32, 128
1302   ret i1 %cmp
1305 define i1 @bitcast_unknown2(ptr %p) {
1306 ; CHECK-LABEL: @bitcast_unknown2(
1307 ; CHECK-NEXT:  entry:
1308 ; CHECK-NEXT:    [[P64:%.*]] = ptrtoint ptr [[P:%.*]] to i64
1309 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i64 [[P64]], 128
1310 ; CHECK-NEXT:    ret i1 [[CMP]]
1312 entry:
1313   %p64 = ptrtoint ptr %p to i64
1314   %cmp = icmp sle i64 %p64, 128
1315   ret i1 %cmp
1319 define i1 @and_unknown(i32 %a) {
1320 ; CHECK-LABEL: @and_unknown(
1321 ; CHECK-NEXT:  entry:
1322 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[A:%.*]], 128
1323 ; CHECK-NEXT:    ret i1 true
1325 entry:
1326   %and = and i32 %a, 128
1327   %cmp = icmp sle i32 %and, 128
1328   ret i1 %cmp
1331 define i1 @lshr_unknown(i32 %a) {
1332 ; CHECK-LABEL: @lshr_unknown(
1333 ; CHECK-NEXT:  entry:
1334 ; CHECK-NEXT:    [[AND:%.*]] = lshr i32 [[A:%.*]], 30
1335 ; CHECK-NEXT:    ret i1 true
1337 entry:
1338   %and = lshr i32 %a, 30
1339   %cmp = icmp sle i32 %and, 128
1340   ret i1 %cmp
1343 define i1 @urem_unknown(i32 %a) {
1344 ; CHECK-LABEL: @urem_unknown(
1345 ; CHECK-NEXT:  entry:
1346 ; CHECK-NEXT:    [[UREM:%.*]] = urem i32 [[A:%.*]], 30
1347 ; CHECK-NEXT:    ret i1 true
1349 entry:
1350   %urem = urem i32 %a, 30
1351   %cmp = icmp ult i32 %urem, 30
1352   ret i1 %cmp
1355 define i1 @srem_unknown(i32 %a) {
1356 ; CHECK-LABEL: @srem_unknown(
1357 ; CHECK-NEXT:  entry:
1358 ; CHECK-NEXT:    [[SREM:%.*]] = srem i32 [[A:%.*]], 30
1359 ; CHECK-NEXT:    br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]]
1360 ; CHECK:       exit1:
1361 ; CHECK-NEXT:    ret i1 true
1362 ; CHECK:       exit2:
1363 ; CHECK-NEXT:    ret i1 true
1365 entry:
1366   %srem = srem i32 %a, 30
1367   %cmp1 = icmp slt i32 %srem, 30
1368   %cmp2 = icmp sgt i32 %srem, -30
1369   br i1 undef, label %exit1, label %exit2
1370 exit1:
1371   ret i1 %cmp1
1372 exit2:
1373   ret i1 %cmp2
1376 define i1 @sdiv_unknown(i32 %a) {
1377 ; CHECK-LABEL: @sdiv_unknown(
1378 ; CHECK-NEXT:  entry:
1379 ; CHECK-NEXT:    [[SREM:%.*]] = sdiv i32 [[A:%.*]], 123
1380 ; CHECK-NEXT:    br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]]
1381 ; CHECK:       exit1:
1382 ; CHECK-NEXT:    ret i1 true
1383 ; CHECK:       exit2:
1384 ; CHECK-NEXT:    ret i1 true
1386 entry:
1387   %srem = sdiv i32 %a, 123
1388   %cmp1 = icmp slt i32 %srem, 17459217
1389   %cmp2 = icmp sgt i32 %srem, -17459217
1390   br i1 undef, label %exit1, label %exit2
1391 exit1:
1392   ret i1 %cmp1
1393 exit2:
1394   ret i1 %cmp2
1397 define i1 @uadd_sat_unknown(i32 %a) {
1398 ; CHECK-LABEL: @uadd_sat_unknown(
1399 ; CHECK-NEXT:  entry:
1400 ; CHECK-NEXT:    [[VAL:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[A:%.*]], i32 100)
1401 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[VAL]], 100
1402 ; CHECK-NEXT:    br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]]
1403 ; CHECK:       exit1:
1404 ; CHECK-NEXT:    ret i1 true
1405 ; CHECK:       exit2:
1406 ; CHECK-NEXT:    ret i1 [[CMP2]]
1408 entry:
1409   %val = call i32 @llvm.uadd.sat.i32(i32 %a, i32 100)
1410   %cmp1 = icmp uge i32 %val, 100
1411   %cmp2 = icmp ugt i32 %val, 100
1412   br i1 undef, label %exit1, label %exit2
1413 exit1:
1414   ret i1 %cmp1
1415 exit2:
1416   ret i1 %cmp2
1419 define i1 @usub_sat_unknown(i32 %a) {
1420 ; CHECK-LABEL: @usub_sat_unknown(
1421 ; CHECK-NEXT:  entry:
1422 ; CHECK-NEXT:    [[VAL:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 100)
1423 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[VAL]], -101
1424 ; CHECK-NEXT:    br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]]
1425 ; CHECK:       exit1:
1426 ; CHECK-NEXT:    ret i1 true
1427 ; CHECK:       exit2:
1428 ; CHECK-NEXT:    ret i1 [[CMP2]]
1430 entry:
1431   %val = call i32 @llvm.usub.sat.i32(i32 %a, i32 100)
1432   %cmp1 = icmp ule i32 %val, 4294967195
1433   %cmp2 = icmp ult i32 %val, 4294967195
1434   br i1 undef, label %exit1, label %exit2
1435 exit1:
1436   ret i1 %cmp1
1437 exit2:
1438   ret i1 %cmp2
1441 define i1 @sadd_sat_unknown(i32 %a) {
1442 ; CHECK-LABEL: @sadd_sat_unknown(
1443 ; CHECK-NEXT:  entry:
1444 ; CHECK-NEXT:    [[VAL:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[A:%.*]], i32 100)
1445 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[VAL]], -2147483548
1446 ; CHECK-NEXT:    br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]]
1447 ; CHECK:       exit1:
1448 ; CHECK-NEXT:    ret i1 true
1449 ; CHECK:       exit2:
1450 ; CHECK-NEXT:    ret i1 [[CMP2]]
1452 entry:
1453   %val = call i32 @llvm.sadd.sat.i32(i32 %a, i32 100)
1454   %cmp1 = icmp sge i32 %val, -2147483548
1455   %cmp2 = icmp sgt i32 %val, -2147483548
1456   br i1 undef, label %exit1, label %exit2
1457 exit1:
1458   ret i1 %cmp1
1459 exit2:
1460   ret i1 %cmp2
1463 define i1 @ssub_sat_unknown(i32 %a) {
1464 ; CHECK-LABEL: @ssub_sat_unknown(
1465 ; CHECK-NEXT:  entry:
1466 ; CHECK-NEXT:    [[VAL:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[A:%.*]], i32 100)
1467 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[VAL]], 2147483547
1468 ; CHECK-NEXT:    br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]]
1469 ; CHECK:       exit1:
1470 ; CHECK-NEXT:    ret i1 true
1471 ; CHECK:       exit2:
1472 ; CHECK-NEXT:    ret i1 [[CMP2]]
1474 entry:
1475   %val = call i32 @llvm.ssub.sat.i32(i32 %a, i32 100)
1476   %cmp1 = icmp sle i32 %val, 2147483547
1477   %cmp2 = icmp slt i32 %val, 2147483547
1478   br i1 undef, label %exit1, label %exit2
1479 exit1:
1480   ret i1 %cmp1
1481 exit2:
1482   ret i1 %cmp2
1485 define void @select_and(i32 %a, ptr %p) {
1486 ; CHECK-LABEL: @select_and(
1487 ; CHECK-NEXT:  entry:
1488 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 [[A:%.*]], -10
1489 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[A]], 10
1490 ; CHECK-NEXT:    [[AND:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 false
1491 ; CHECK-NEXT:    br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1492 ; CHECK:       guard:
1493 ; CHECK-NEXT:    store i1 false, ptr [[P:%.*]], align 1
1494 ; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1495 ; CHECK-NEXT:    br label [[EXIT]]
1496 ; CHECK:       exit:
1497 ; CHECK-NEXT:    ret void
1499 entry:
1500   %cmp1 = icmp sgt i32 %a, -10
1501   %cmp2 = icmp slt i32 %a, 10
1502   %and = select i1 %cmp1, i1 %cmp2, i1 false
1503   br i1 %and, label %guard, label %exit
1505 guard:
1506   %c1 = icmp sgt i32 %a, 20
1507   store i1 %c1, ptr %p
1508   %c2 = icmp slt i32 %a, -20
1509   store i1 %c2, ptr %p
1510   br label %exit
1512 exit:
1513   ret void
1516 define void @select_and_wrong_const(i32 %a, ptr %p) {
1517 ; CHECK-LABEL: @select_and_wrong_const(
1518 ; CHECK-NEXT:  entry:
1519 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 [[A:%.*]], -10
1520 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[A]], 10
1521 ; CHECK-NEXT:    [[AND:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 true
1522 ; CHECK-NEXT:    br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1523 ; CHECK:       guard:
1524 ; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i32 [[A]], 20
1525 ; CHECK-NEXT:    store i1 [[C1]], ptr [[P:%.*]], align 1
1526 ; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[A]], -20
1527 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1528 ; CHECK-NEXT:    br label [[EXIT]]
1529 ; CHECK:       exit:
1530 ; CHECK-NEXT:    ret void
1532 entry:
1533   %cmp1 = icmp sgt i32 %a, -10
1534   %cmp2 = icmp slt i32 %a, 10
1535   %and = select i1 %cmp1, i1 %cmp2, i1 true
1536   br i1 %and, label %guard, label %exit
1538 guard:
1539   %c1 = icmp sgt i32 %a, 20
1540   store i1 %c1, ptr %p
1541   %c2 = icmp slt i32 %a, -20
1542   store i1 %c2, ptr %p
1543   br label %exit
1545 exit:
1546   ret void
1549 define void @select_and_wrong_operand(i32 %a, ptr %p) {
1550 ; CHECK-LABEL: @select_and_wrong_operand(
1551 ; CHECK-NEXT:  entry:
1552 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 [[A:%.*]], -10
1553 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[A]], 10
1554 ; CHECK-NEXT:    [[AND:%.*]] = select i1 [[CMP1]], i1 false, i1 [[CMP2]]
1555 ; CHECK-NEXT:    br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1556 ; CHECK:       guard:
1557 ; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i32 [[A]], 20
1558 ; CHECK-NEXT:    store i1 [[C1]], ptr [[P:%.*]], align 1
1559 ; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[A]], -20
1560 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1561 ; CHECK-NEXT:    br label [[EXIT]]
1562 ; CHECK:       exit:
1563 ; CHECK-NEXT:    ret void
1565 entry:
1566   %cmp1 = icmp sgt i32 %a, -10
1567   %cmp2 = icmp slt i32 %a, 10
1568   %and = select i1 %cmp1, i1 false, i1 %cmp2
1569   br i1 %and, label %guard, label %exit
1571 guard:
1572   %c1 = icmp sgt i32 %a, 20
1573   store i1 %c1, ptr %p
1574   %c2 = icmp slt i32 %a, -20
1575   store i1 %c2, ptr %p
1576   br label %exit
1578 exit:
1579   ret void
1582 define void @select_or(i32 %a, ptr %p) {
1583 ; CHECK-LABEL: @select_or(
1584 ; CHECK-NEXT:  entry:
1585 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A:%.*]], -10
1586 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[A]], 10
1587 ; CHECK-NEXT:    [[OR:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]]
1588 ; CHECK-NEXT:    br i1 [[OR]], label [[EXIT:%.*]], label [[GUARD:%.*]]
1589 ; CHECK:       guard:
1590 ; CHECK-NEXT:    store i1 false, ptr [[P:%.*]], align 1
1591 ; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1592 ; CHECK-NEXT:    br label [[EXIT]]
1593 ; CHECK:       exit:
1594 ; CHECK-NEXT:    ret void
1596 entry:
1597   %cmp1 = icmp slt i32 %a, -10
1598   %cmp2 = icmp sgt i32 %a, 10
1599   %or = select i1 %cmp1, i1 true, i1 %cmp2
1600   br i1 %or, label %exit, label %guard
1602 guard:
1603   %c1 = icmp sgt i32 %a, 20
1604   store i1 %c1, ptr %p
1605   %c2 = icmp slt i32 %a, -20
1606   store i1 %c2, ptr %p
1607   br label %exit
1609 exit:
1610   ret void
1613 define void @select_or_wrong_const(i32 %a, ptr %p) {
1614 ; CHECK-LABEL: @select_or_wrong_const(
1615 ; CHECK-NEXT:  entry:
1616 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A:%.*]], -10
1617 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[A]], 10
1618 ; CHECK-NEXT:    [[OR:%.*]] = select i1 [[CMP1]], i1 false, i1 [[CMP2]]
1619 ; CHECK-NEXT:    br i1 [[OR]], label [[EXIT:%.*]], label [[GUARD:%.*]]
1620 ; CHECK:       guard:
1621 ; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i32 [[A]], 20
1622 ; CHECK-NEXT:    store i1 [[C1]], ptr [[P:%.*]], align 1
1623 ; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[A]], -20
1624 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1625 ; CHECK-NEXT:    br label [[EXIT]]
1626 ; CHECK:       exit:
1627 ; CHECK-NEXT:    ret void
1629 entry:
1630   %cmp1 = icmp slt i32 %a, -10
1631   %cmp2 = icmp sgt i32 %a, 10
1632   %or = select i1 %cmp1, i1 false, i1 %cmp2
1633   br i1 %or, label %exit, label %guard
1635 guard:
1636   %c1 = icmp sgt i32 %a, 20
1637   store i1 %c1, ptr %p
1638   %c2 = icmp slt i32 %a, -20
1639   store i1 %c2, ptr %p
1640   br label %exit
1642 exit:
1643   ret void
1646 define void @select_or_wrong_operand(i32 %a, ptr %p) {
1647 ; CHECK-LABEL: @select_or_wrong_operand(
1648 ; CHECK-NEXT:  entry:
1649 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A:%.*]], -10
1650 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[A]], 10
1651 ; CHECK-NEXT:    [[OR:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 true
1652 ; CHECK-NEXT:    br i1 [[OR]], label [[EXIT:%.*]], label [[GUARD:%.*]]
1653 ; CHECK:       guard:
1654 ; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i32 [[A]], 20
1655 ; CHECK-NEXT:    store i1 [[C1]], ptr [[P:%.*]], align 1
1656 ; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[A]], -20
1657 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1658 ; CHECK-NEXT:    br label [[EXIT]]
1659 ; CHECK:       exit:
1660 ; CHECK-NEXT:    ret void
1662 entry:
1663   %cmp1 = icmp slt i32 %a, -10
1664   %cmp2 = icmp sgt i32 %a, 10
1665   %or = select i1 %cmp1, i1 %cmp2, i1 true
1666   br i1 %or, label %exit, label %guard
1668 guard:
1669   %c1 = icmp sgt i32 %a, 20
1670   store i1 %c1, ptr %p
1671   %c2 = icmp slt i32 %a, -20
1672   store i1 %c2, ptr %p
1673   br label %exit
1675 exit:
1676   ret void
1679 define void @or_union(i32 %a, ptr %p) {
1680 ; CHECK-LABEL: @or_union(
1681 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 10
1682 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[A]], 12
1683 ; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
1684 ; CHECK-NEXT:    br i1 [[OR]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1685 ; CHECK:       guard:
1686 ; CHECK-NEXT:    store i1 false, ptr [[P:%.*]], align 1
1687 ; CHECK-NEXT:    [[C2:%.*]] = icmp eq i32 [[A]], 10
1688 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1689 ; CHECK-NEXT:    [[C3:%.*]] = icmp eq i32 [[A]], 11
1690 ; CHECK-NEXT:    store i1 [[C3]], ptr [[P]], align 1
1691 ; CHECK-NEXT:    [[C4:%.*]] = icmp eq i32 [[A]], 12
1692 ; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
1693 ; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1694 ; CHECK-NEXT:    br label [[EXIT]]
1695 ; CHECK:       exit:
1696 ; CHECK-NEXT:    ret void
1698   %cmp1 = icmp eq i32 %a, 10
1699   %cmp2 = icmp eq i32 %a, 12
1700   %or = or i1 %cmp1, %cmp2
1701   br i1 %or, label %guard, label %exit
1703 guard:
1704   %c1 = icmp eq i32 %a, 9
1705   store i1 %c1, ptr %p
1706   %c2 = icmp eq i32 %a, 10
1707   store i1 %c2, ptr %p
1708   %c3 = icmp eq i32 %a, 11
1709   store i1 %c3, ptr %p
1710   %c4 = icmp eq i32 %a, 12
1711   store i1 %c4, ptr %p
1712   %c5 = icmp eq i32 %a, 13
1713   store i1 %c5, ptr %p
1714   br label %exit
1716 exit:
1717   ret void
1720 define i1 @or_union_unknown_cond(i32 %a, i1 %c) {
1721 ; CHECK-LABEL: @or_union_unknown_cond(
1722 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 10
1723 ; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[C:%.*]]
1724 ; CHECK-NEXT:    br i1 [[OR]], label [[GUARD:%.*]], label [[EXIT:%.*]]
1725 ; CHECK:       guard:
1726 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[A]], 10
1727 ; CHECK-NEXT:    ret i1 [[CMP2]]
1728 ; CHECK:       exit:
1729 ; CHECK-NEXT:    ret i1 false
1731   %cmp1 = icmp eq i32 %a, 10
1732   %or = or i1 %cmp1, %c
1733   br i1 %or, label %guard, label %exit
1735 guard:
1736   %cmp2 = icmp eq i32 %a, 10
1737   ret i1 %cmp2
1739 exit:
1740   ret i1 false
1743 define void @and_union(i32 %a, ptr %p) {
1744 ; CHECK-LABEL: @and_union(
1745 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 10
1746 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[A]], 12
1747 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
1748 ; CHECK-NEXT:    br i1 [[AND]], label [[EXIT:%.*]], label [[GUARD:%.*]]
1749 ; CHECK:       guard:
1750 ; CHECK-NEXT:    store i1 false, ptr [[P:%.*]], align 1
1751 ; CHECK-NEXT:    [[C2:%.*]] = icmp eq i32 [[A]], 10
1752 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1753 ; CHECK-NEXT:    [[C3:%.*]] = icmp eq i32 [[A]], 11
1754 ; CHECK-NEXT:    store i1 [[C3]], ptr [[P]], align 1
1755 ; CHECK-NEXT:    [[C4:%.*]] = icmp eq i32 [[A]], 12
1756 ; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
1757 ; CHECK-NEXT:    store i1 false, ptr [[P]], align 1
1758 ; CHECK-NEXT:    br label [[EXIT]]
1759 ; CHECK:       exit:
1760 ; CHECK-NEXT:    ret void
1762   %cmp1 = icmp ne i32 %a, 10
1763   %cmp2 = icmp ne i32 %a, 12
1764   %and = and i1 %cmp1, %cmp2
1765   br i1 %and, label %exit, label %guard
1767 guard:
1768   %c1 = icmp eq i32 %a, 9
1769   store i1 %c1, ptr %p
1770   %c2 = icmp eq i32 %a, 10
1771   store i1 %c2, ptr %p
1772   %c3 = icmp eq i32 %a, 11
1773   store i1 %c3, ptr %p
1774   %c4 = icmp eq i32 %a, 12
1775   store i1 %c4, ptr %p
1776   %c5 = icmp eq i32 %a, 13
1777   store i1 %c5, ptr %p
1778   br label %exit
1780 exit:
1781   ret void
1784 define i1 @and_union_unknown_cond(i32 %a, i1 %c) {
1785 ; CHECK-LABEL: @and_union_unknown_cond(
1786 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 10
1787 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[C:%.*]]
1788 ; CHECK-NEXT:    br i1 [[AND]], label [[EXIT:%.*]], label [[GUARD:%.*]]
1789 ; CHECK:       guard:
1790 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[A]], 10
1791 ; CHECK-NEXT:    ret i1 [[CMP2]]
1792 ; CHECK:       exit:
1793 ; CHECK-NEXT:    ret i1 false
1795   %cmp1 = icmp ne i32 %a, 10
1796   %and = and i1 %cmp1, %c
1797   br i1 %and, label %exit, label %guard
1799 guard:
1800   %cmp2 = icmp eq i32 %a, 10
1801   ret i1 %cmp2
1803 exit:
1804   ret i1 false
1807 define void @select_assume(i32 %a, i32 %b, i1 %c, ptr %p) {
1808 ; CHECK-LABEL: @select_assume(
1809 ; CHECK-NEXT:    [[C1:%.*]] = icmp ult i32 [[A:%.*]], 10
1810 ; CHECK-NEXT:    call void @llvm.assume(i1 [[C1]])
1811 ; CHECK-NEXT:    [[C2:%.*]] = icmp ult i32 [[B:%.*]], 20
1812 ; CHECK-NEXT:    call void @llvm.assume(i1 [[C2]])
1813 ; CHECK-NEXT:    [[S:%.*]] = select i1 [[C:%.*]], i32 [[A]], i32 [[B]]
1814 ; CHECK-NEXT:    [[C3:%.*]] = icmp ult i32 [[S]], 19
1815 ; CHECK-NEXT:    store i1 [[C3]], ptr [[P:%.*]], align 1
1816 ; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1817 ; CHECK-NEXT:    ret void
1819   %c1 = icmp ult i32 %a, 10
1820   call void @llvm.assume(i1 %c1)
1821   %c2 = icmp ult i32 %b, 20
1822   call void @llvm.assume(i1 %c2)
1823   %s = select i1 %c, i32 %a, i32 %b
1824   %c3 = icmp ult i32 %s, 19
1825   store i1 %c3, ptr %p
1826   %c4 = icmp ult i32 %s, 20
1827   store i1 %c4, ptr %p
1828   ret void
1831 define void @xor(i8 %a, ptr %p) {
1832 ; CHECK-LABEL: @xor(
1833 ; CHECK-NEXT:    [[A_MASK:%.*]] = and i8 [[A:%.*]], 15
1834 ; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[A_MASK]], -86
1835 ; CHECK-NEXT:    store i1 true, ptr [[P:%.*]], align 1
1836 ; CHECK-NEXT:    [[C2:%.*]] = icmp ugt i8 [[XOR]], -96
1837 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
1838 ; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
1839 ; CHECK-NEXT:    [[C4:%.*]] = icmp ult i8 [[XOR]], -81
1840 ; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
1841 ; CHECK-NEXT:    ret void
1843   %a.mask = and i8 %a, 15 ; 0b0000????
1844   %xor = xor i8 %a.mask, 170 ; ^ 0b10101010 == 0b1010????
1845   %c1 = icmp uge i8 %xor, 160
1846   store i1 %c1, ptr %p
1847   %c2 = icmp ugt i8 %xor, 160
1848   store i1 %c2, ptr %p
1849   %c3 = icmp ule i8 %xor, 175
1850   store i1 %c3, ptr %p
1851   %c4 = icmp ult i8 %xor, 175
1852   store i1 %c4, ptr %p
1853   ret void
1856 define i1 @xor_neg_cond(i32 %a) {
1857 ; CHECK-LABEL: @xor_neg_cond(
1858 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 10
1859 ; CHECK-NEXT:    [[XOR:%.*]] = xor i1 [[CMP1]], true
1860 ; CHECK-NEXT:    br i1 [[XOR]], label [[EXIT:%.*]], label [[GUARD:%.*]]
1861 ; CHECK:       guard:
1862 ; CHECK-NEXT:    ret i1 true
1863 ; CHECK:       exit:
1864 ; CHECK-NEXT:    ret i1 false
1866   %cmp1 = icmp eq i32 %a, 10
1867   %xor = xor i1 %cmp1, true
1868   br i1 %xor, label %exit, label %guard
1870 guard:
1871   %cmp2 = icmp eq i32 %a, 10
1872   ret i1 %cmp2
1874 exit:
1875   ret i1 false
1878 define i1 @xor_approx(i32 %a) {
1879 ; CHECK-LABEL: @xor_approx(
1880 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 2
1881 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[A]], 5
1882 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp ugt i32 [[A]], 7
1883 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp ult i32 [[A]], 9
1884 ; CHECK-NEXT:    [[AND1:%.*]] = and i1 [[CMP1]], [[CMP2]]
1885 ; CHECK-NEXT:    [[AND2:%.*]] = and i1 [[CMP3]], [[CMP4]]
1886 ; CHECK-NEXT:    [[OR:%.*]] = or i1 [[AND1]], [[AND2]]
1887 ; CHECK-NEXT:    [[XOR:%.*]] = xor i1 [[OR]], true
1888 ; CHECK-NEXT:    br i1 [[XOR]], label [[EXIT:%.*]], label [[GUARD:%.*]]
1889 ; CHECK:       guard:
1890 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp eq i32 [[A]], 6
1891 ; CHECK-NEXT:    ret i1 [[CMP5]]
1892 ; CHECK:       exit:
1893 ; CHECK-NEXT:    ret i1 false
1895   %cmp1 = icmp ugt i32 %a, 2
1896   %cmp2 = icmp ult i32 %a, 5
1897   %cmp3 = icmp ugt i32 %a, 7
1898   %cmp4 = icmp ult i32 %a, 9
1899   %and1 = and i1 %cmp1, %cmp2
1900   %and2 = and i1 %cmp3, %cmp4
1901   %or = or i1 %and1, %and2
1902   %xor = xor i1 %or, true
1903   br i1 %xor, label %exit, label %guard
1905 guard:
1906   %cmp5 = icmp eq i32 %a, 6
1907   ret i1 %cmp5
1909 exit:
1910   ret i1 false
1913 declare i32 @llvm.uadd.sat.i32(i32, i32)
1914 declare i32 @llvm.usub.sat.i32(i32, i32)
1915 declare i32 @llvm.sadd.sat.i32(i32, i32)
1916 declare i32 @llvm.ssub.sat.i32(i32, i32)
1917 declare void @llvm.assume(i1)