1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
4 ; Fold icmp with a constant operand.
6 define i1 @tautological_ule(i8 %x) {
7 ; CHECK-LABEL: @tautological_ule(
8 ; CHECK-NEXT: ret i1 true
10 %cmp = icmp ule i8 %x, 255
14 define <2 x i1> @tautological_ule_vec(<2 x i8> %x) {
15 ; CHECK-LABEL: @tautological_ule_vec(
16 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
18 %cmp = icmp ule <2 x i8> %x, <i8 255, i8 255>
22 define <2 x i1> @tautological_ule_vec_partial_undef(<2 x i8> %x) {
23 ; CHECK-LABEL: @tautological_ule_vec_partial_undef(
24 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
26 %cmp = icmp ule <2 x i8> %x, <i8 255, i8 undef>
30 define i1 @tautological_ugt(i8 %x) {
31 ; CHECK-LABEL: @tautological_ugt(
32 ; CHECK-NEXT: ret i1 false
34 %cmp = icmp ugt i8 %x, 255
38 define <2 x i1> @tautological_ugt_vec(<2 x i8> %x) {
39 ; CHECK-LABEL: @tautological_ugt_vec(
40 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
42 %cmp = icmp ugt <2 x i8> %x, <i8 255, i8 255>
46 define <2 x i1> @tautological_ugt_vec_partial_undef(<2 x i8> %x) {
47 ; CHECK-LABEL: @tautological_ugt_vec_partial_undef(
48 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
50 %cmp = icmp ugt <2 x i8> %x, <i8 undef, i8 255>
54 ; 'urem x, C2' produces [0, C2)
55 define i1 @urem3(i32 %X) {
56 ; CHECK-LABEL: @urem3(
57 ; CHECK-NEXT: ret i1 true
60 %B = icmp ult i32 %A, 15
64 define <2 x i1> @urem3_vec(<2 x i32> %X) {
65 ; CHECK-LABEL: @urem3_vec(
66 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
68 %A = urem <2 x i32> %X, <i32 10, i32 10>
69 %B = icmp ult <2 x i32> %A, <i32 15, i32 15>
73 define <2 x i1> @urem3_vec_partial_undef(<2 x i32> %X) {
74 ; CHECK-LABEL: @urem3_vec_partial_undef(
75 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
77 %A = urem <2 x i32> %X, <i32 10, i32 10>
78 %B = icmp ult <2 x i32> %A, <i32 undef, i32 15>
82 ;'srem x, C2' produces (-|C2|, |C2|)
83 define i1 @srem1(i32 %X) {
84 ; CHECK-LABEL: @srem1(
85 ; CHECK-NEXT: ret i1 false
88 %B = icmp sgt i32 %A, 5
92 define <2 x i1> @srem1_vec(<2 x i32> %X) {
93 ; CHECK-LABEL: @srem1_vec(
94 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
96 %A = srem <2 x i32> %X, <i32 -5, i32 -5>
97 %B = icmp sgt <2 x i32> %A, <i32 5, i32 5>
101 define <2 x i1> @srem1_vec_partial_undef(<2 x i32> %X) {
102 ; CHECK-LABEL: @srem1_vec_partial_undef(
103 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
105 %A = srem <2 x i32> %X, <i32 -5, i32 -5>
106 %B = icmp sgt <2 x i32> %A, <i32 5, i32 undef>
110 ;'udiv C2, x' produces [0, C2]
111 define i1 @udiv5(i32 %X) {
112 ; CHECK-LABEL: @udiv5(
113 ; CHECK-NEXT: ret i1 false
115 %A = udiv i32 123, %X
116 %C = icmp ugt i32 %A, 124
120 define <2 x i1> @udiv5_vec(<2 x i32> %X) {
121 ; CHECK-LABEL: @udiv5_vec(
122 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
124 %A = udiv <2 x i32> <i32 123, i32 123>, %X
125 %C = icmp ugt <2 x i32> %A, <i32 124, i32 124>
129 ; 'udiv x, C2' produces [0, UINT_MAX / C2]
130 define i1 @udiv1(i32 %X) {
131 ; CHECK-LABEL: @udiv1(
132 ; CHECK-NEXT: ret i1 true
134 %A = udiv i32 %X, 1000000
135 %B = icmp ult i32 %A, 5000
139 define <2 x i1> @udiv1_vec(<2 x i32> %X) {
140 ; CHECK-LABEL: @udiv1_vec(
141 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
143 %A = udiv <2 x i32> %X, <i32 1000000, i32 1000000>
144 %B = icmp ult <2 x i32> %A, <i32 5000, i32 5000>
148 ; 'sdiv C2, x' produces [-|C2|, |C2|]
149 define i1 @compare_dividend(i32 %a) {
150 ; CHECK-LABEL: @compare_dividend(
151 ; CHECK-NEXT: ret i1 false
153 %div = sdiv i32 2, %a
154 %cmp = icmp eq i32 %div, 3
158 define <2 x i1> @compare_dividend_vec(<2 x i32> %a) {
159 ; CHECK-LABEL: @compare_dividend_vec(
160 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
162 %div = sdiv <2 x i32> <i32 2, i32 2>, %a
163 %cmp = icmp eq <2 x i32> %div, <i32 3, i32 3>
167 ; 'sdiv x, C2' produces [INT_MIN / C2, INT_MAX / C2]
168 ; where C2 != -1 and C2 != 0 and C2 != 1
169 define i1 @sdiv1(i32 %X) {
170 ; CHECK-LABEL: @sdiv1(
171 ; CHECK-NEXT: ret i1 true
173 %A = sdiv i32 %X, 1000000
174 %B = icmp slt i32 %A, 3000
178 define <2 x i1> @sdiv1_vec(<2 x i32> %X) {
179 ; CHECK-LABEL: @sdiv1_vec(
180 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
182 %A = sdiv <2 x i32> %X, <i32 1000000, i32 1000000>
183 %B = icmp slt <2 x i32> %A, <i32 3000, i32 3000>
187 ; 'shl nuw C2, x' produces [C2, C2 << CLZ(C2)]
188 define i1 @shl5(i32 %X) {
189 ; CHECK-LABEL: @shl5(
190 ; CHECK-NEXT: ret i1 true
192 %sub = shl nuw i32 4, %X
193 %cmp = icmp ugt i32 %sub, 3
197 define <2 x i1> @shl5_vec(<2 x i32> %X) {
198 ; CHECK-LABEL: @shl5_vec(
199 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
201 %sub = shl nuw <2 x i32> <i32 4, i32 4>, %X
202 %cmp = icmp ugt <2 x i32> %sub, <i32 3, i32 3>
206 define <2 x i1> @shl5_vec_partial_undef(<2 x i32> %X) {
207 ; CHECK-LABEL: @shl5_vec_partial_undef(
208 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
210 %sub = shl nuw <2 x i32> <i32 4, i32 4>, %X
211 %cmp = icmp ugt <2 x i32> %sub, <i32 undef, i32 3>
215 ; 'shl nsw C2, x' produces [C2 << CLO(C2)-1, C2]
216 define i1 @shl2(i32 %X) {
217 ; CHECK-LABEL: @shl2(
218 ; CHECK-NEXT: ret i1 false
220 %sub = shl nsw i32 -1, %X
221 %cmp = icmp eq i32 %sub, 31
225 define <2 x i1> @shl2_vec(<2 x i32> %X) {
226 ; CHECK-LABEL: @shl2_vec(
227 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
229 %sub = shl nsw <2 x i32> <i32 -1, i32 -1>, %X
230 %cmp = icmp eq <2 x i32> %sub, <i32 31, i32 31>
234 ; 'shl nsw C2, x' produces [C2 << CLO(C2)-1, C2]
235 define i1 @shl4(i32 %X) {
236 ; CHECK-LABEL: @shl4(
237 ; CHECK-NEXT: ret i1 true
239 %sub = shl nsw i32 -1, %X
240 %cmp = icmp sle i32 %sub, -1
244 define <2 x i1> @shl4_vec(<2 x i32> %X) {
245 ; CHECK-LABEL: @shl4_vec(
246 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
248 %sub = shl nsw <2 x i32> <i32 -1, i32 -1>, %X
249 %cmp = icmp sle <2 x i32> %sub, <i32 -1, i32 -1>
253 ; 'shl nsw C2, x' produces [C2, C2 << CLZ(C2)-1]
254 define i1 @icmp_shl_nsw_1(i64 %a) {
255 ; CHECK-LABEL: @icmp_shl_nsw_1(
256 ; CHECK-NEXT: ret i1 true
258 %shl = shl nsw i64 1, %a
259 %cmp = icmp sge i64 %shl, 0
263 define <2 x i1> @icmp_shl_nsw_1_vec(<2 x i64> %a) {
264 ; CHECK-LABEL: @icmp_shl_nsw_1_vec(
265 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
267 %shl = shl nsw <2 x i64> <i64 1, i64 1>, %a
268 %cmp = icmp sge <2 x i64> %shl, zeroinitializer
272 ; 'shl nsw C2, x' produces [C2 << CLO(C2)-1, C2]
273 define i1 @icmp_shl_nsw_neg1(i64 %a) {
274 ; CHECK-LABEL: @icmp_shl_nsw_neg1(
275 ; CHECK-NEXT: ret i1 false
277 %shl = shl nsw i64 -1, %a
278 %cmp = icmp sge i64 %shl, 3
282 define <2 x i1> @icmp_shl_nsw_neg1_vec(<2 x i64> %a) {
283 ; CHECK-LABEL: @icmp_shl_nsw_neg1_vec(
284 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
286 %shl = shl nsw <2 x i64> <i64 -1, i64 -1>, %a
287 %cmp = icmp sge <2 x i64> %shl, <i64 3, i64 3>
291 ; 'lshr x, C2' produces [0, UINT_MAX >> C2]
292 define i1 @lshr2(i32 %x) {
293 ; CHECK-LABEL: @lshr2(
294 ; CHECK-NEXT: ret i1 false
297 %c = icmp ugt i32 %s, 8
301 define <2 x i1> @lshr2_vec(<2 x i32> %x) {
302 ; CHECK-LABEL: @lshr2_vec(
303 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
305 %s = lshr <2 x i32> %x, <i32 30, i32 30>
306 %c = icmp ugt <2 x i32> %s, <i32 8, i32 8>
310 ; 'lshr C2, x' produces [C2 >> (Width-1), C2]
311 define i1 @exact_lshr_ugt_false(i32 %a) {
312 ; CHECK-LABEL: @exact_lshr_ugt_false(
313 ; CHECK-NEXT: ret i1 false
315 %shr = lshr exact i32 30, %a
316 %cmp = icmp ult i32 %shr, 15
320 define <2 x i1> @exact_lshr_ugt_false_vec(<2 x i32> %a) {
321 ; CHECK-LABEL: @exact_lshr_ugt_false_vec(
322 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
324 %shr = lshr exact <2 x i32> <i32 30, i32 30>, %a
325 %cmp = icmp ult <2 x i32> %shr, <i32 15, i32 15>
329 ; 'lshr C2, x' produces [C2 >> (Width-1), C2]
330 define i1 @lshr_sgt_false(i32 %a) {
331 ; CHECK-LABEL: @lshr_sgt_false(
332 ; CHECK-NEXT: ret i1 false
334 %shr = lshr i32 1, %a
335 %cmp = icmp sgt i32 %shr, 1
339 define <2 x i1> @lshr_sgt_false_vec(<2 x i32> %a) {
340 ; CHECK-LABEL: @lshr_sgt_false_vec(
341 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
343 %shr = lshr <2 x i32> <i32 1, i32 1>, %a
344 %cmp = icmp sgt <2 x i32> %shr, <i32 1, i32 1>
348 ; 'ashr x, C2' produces [INT_MIN >> C2, INT_MAX >> C2]
349 define i1 @ashr2(i32 %x) {
350 ; CHECK-LABEL: @ashr2(
351 ; CHECK-NEXT: ret i1 false
354 %c = icmp slt i32 %s, -5
358 define <2 x i1> @ashr2_vec(<2 x i32> %x) {
359 ; CHECK-LABEL: @ashr2_vec(
360 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
362 %s = ashr <2 x i32> %x, <i32 30, i32 30>
363 %c = icmp slt <2 x i32> %s, <i32 -5, i32 -5>
367 ; 'ashr C2, x' produces [C2, C2 >> (Width-1)]
368 define i1 @ashr_sgt_false(i32 %a) {
369 ; CHECK-LABEL: @ashr_sgt_false(
370 ; CHECK-NEXT: ret i1 false
372 %shr = ashr i32 -30, %a
373 %cmp = icmp sgt i32 %shr, -1
377 define <2 x i1> @ashr_sgt_false_vec(<2 x i32> %a) {
378 ; CHECK-LABEL: @ashr_sgt_false_vec(
379 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
381 %shr = ashr <2 x i32> <i32 -30, i32 -30>, %a
382 %cmp = icmp sgt <2 x i32> %shr, <i32 -1, i32 -1>
386 ; 'ashr C2, x' produces [C2, C2 >> (Width-1)]
387 define i1 @exact_ashr_sgt_false(i32 %a) {
388 ; CHECK-LABEL: @exact_ashr_sgt_false(
389 ; CHECK-NEXT: ret i1 false
391 %shr = ashr exact i32 -30, %a
392 %cmp = icmp sgt i32 %shr, -15
396 define <2 x i1> @exact_ashr_sgt_false_vec(<2 x i32> %a) {
397 ; CHECK-LABEL: @exact_ashr_sgt_false_vec(
398 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
400 %shr = ashr exact <2 x i32> <i32 -30, i32 -30>, %a
401 %cmp = icmp sgt <2 x i32> %shr, <i32 -15, i32 -15>
405 ; 'or x, C2' produces [C2, UINT_MAX]
406 define i1 @or1(i32 %X) {
408 ; CHECK-NEXT: ret i1 false
411 %B = icmp ult i32 %A, 50
415 define <2 x i1> @or1_vec(<2 x i32> %X) {
416 ; CHECK-LABEL: @or1_vec(
417 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
419 %A = or <2 x i32> %X, <i32 62, i32 62>
420 %B = icmp ult <2 x i32> %A, <i32 50, i32 50>
424 define <2 x i1> @or1_vec_partial_undef(<2 x i32> %X) {
425 ; CHECK-LABEL: @or1_vec_partial_undef(
426 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
428 %A = or <2 x i32> %X, <i32 62, i32 62>
429 %B = icmp ult <2 x i32> %A, <i32 undef, i32 50>
434 define i1 @or2_true(i8 %x) {
435 ; CHECK-LABEL: @or2_true(
436 ; CHECK-NEXT: [[Y:%.*]] = or i8 [[X:%.*]], 64
437 ; CHECK-NEXT: [[Z:%.*]] = icmp sge i8 [[Y]], -64
438 ; CHECK-NEXT: ret i1 [[Z]]
441 %z = icmp sge i8 %y, -64
445 define i1 @or2_unknown(i8 %x) {
446 ; CHECK-LABEL: @or2_unknown(
447 ; CHECK-NEXT: [[Y:%.*]] = or i8 [[X:%.*]], 64
448 ; CHECK-NEXT: [[Z:%.*]] = icmp sgt i8 [[Y]], -64
449 ; CHECK-NEXT: ret i1 [[Z]]
452 %z = icmp sgt i8 %y, -64
457 ; 78 = 0b01001110; -50 = 0b11001110
458 define i1 @or3_true(i8 %x) {
459 ; CHECK-LABEL: @or3_true(
460 ; CHECK-NEXT: [[Y:%.*]] = or i8 [[X:%.*]], 78
461 ; CHECK-NEXT: [[Z:%.*]] = icmp sge i8 [[Y]], -50
462 ; CHECK-NEXT: ret i1 [[Z]]
465 %z = icmp sge i8 %y, -50
469 define i1 @or3_unknown(i8 %x) {
470 ; CHECK-LABEL: @or3_unknown(
471 ; CHECK-NEXT: [[Y:%.*]] = or i8 [[X:%.*]], 78
472 ; CHECK-NEXT: [[Z:%.*]] = icmp sgt i8 [[Y]], -50
473 ; CHECK-NEXT: ret i1 [[Z]]
476 %z = icmp sgt i8 %y, -50
481 define i1 @or4_true(i8 %x) {
482 ; CHECK-LABEL: @or4_true(
483 ; CHECK-NEXT: ret i1 true
486 %z = icmp sge i8 %y, -64
490 define i1 @or4_unknown(i8 %x) {
491 ; CHECK-LABEL: @or4_unknown(
492 ; CHECK-NEXT: [[Y:%.*]] = or i8 [[X:%.*]], -64
493 ; CHECK-NEXT: [[Z:%.*]] = icmp sgt i8 [[Y]], -64
494 ; CHECK-NEXT: ret i1 [[Z]]
497 %z = icmp sgt i8 %y, -64
501 ; If sign bit is set, signed & unsigned ranges are the same.
502 define i1 @or5_true(i8 %x) {
503 ; CHECK-LABEL: @or5_true(
504 ; CHECK-NEXT: ret i1 true
507 %z = icmp uge i8 %y, -64
511 define i1 @or5_unknown(i8 %x) {
512 ; CHECK-LABEL: @or5_unknown(
513 ; CHECK-NEXT: [[Y:%.*]] = or i8 [[X:%.*]], -64
514 ; CHECK-NEXT: [[Z:%.*]] = icmp ugt i8 [[Y]], -64
515 ; CHECK-NEXT: ret i1 [[Z]]
518 %z = icmp ugt i8 %y, -64
522 ; 'and x, C2' produces [0, C2]
523 define i1 @and1(i32 %X) {
524 ; CHECK-LABEL: @and1(
525 ; CHECK-NEXT: ret i1 false
528 %B = icmp ugt i32 %A, 70
532 define <2 x i1> @and1_vec(<2 x i32> %X) {
533 ; CHECK-LABEL: @and1_vec(
534 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
536 %A = and <2 x i32> %X, <i32 62, i32 62>
537 %B = icmp ugt <2 x i32> %A, <i32 70, i32 70>
541 ; If the sign bit is not set, signed and unsigned ranges are the same.
542 define i1 @and2(i32 %X) {
543 ; CHECK-LABEL: @and2(
544 ; CHECK-NEXT: ret i1 false
547 %B = icmp sgt i32 %A, 70
551 ; -75 = 0b10110101, 53 = 0b00110101
552 define i1 @and3_true1(i8 %x) {
553 ; CHECK-LABEL: @and3_true1(
554 ; CHECK-NEXT: [[Y:%.*]] = and i8 [[X:%.*]], -75
555 ; CHECK-NEXT: [[Z:%.*]] = icmp sge i8 [[Y]], -75
556 ; CHECK-NEXT: ret i1 [[Z]]
559 %z = icmp sge i8 %y, -75
563 define i1 @and3_unknown1(i8 %x) {
564 ; CHECK-LABEL: @and3_unknown1(
565 ; CHECK-NEXT: [[Y:%.*]] = and i8 [[X:%.*]], -75
566 ; CHECK-NEXT: [[Z:%.*]] = icmp sgt i8 [[Y]], -75
567 ; CHECK-NEXT: ret i1 [[Z]]
570 %z = icmp sgt i8 %y, -75
574 define i1 @and3_true2(i8 %x) {
575 ; CHECK-LABEL: @and3_true2(
576 ; CHECK-NEXT: [[Y:%.*]] = and i8 [[X:%.*]], -75
577 ; CHECK-NEXT: [[Z:%.*]] = icmp sle i8 [[Y]], 53
578 ; CHECK-NEXT: ret i1 [[Z]]
581 %z = icmp sle i8 %y, 53
585 define i1 @and3_unknown2(i8 %x) {
586 ; CHECK-LABEL: @and3_unknown2(
587 ; CHECK-NEXT: [[Y:%.*]] = and i8 [[X:%.*]], -75
588 ; CHECK-NEXT: [[Z:%.*]] = icmp slt i8 [[Y]], 53
589 ; CHECK-NEXT: ret i1 [[Z]]
592 %z = icmp slt i8 %y, 53
596 ; 'add nuw x, C2' produces [C2, UINT_MAX]
597 define i1 @tautological9(i32 %x) {
598 ; CHECK-LABEL: @tautological9(
599 ; CHECK-NEXT: ret i1 true
601 %add = add nuw i32 %x, 13
602 %cmp = icmp ne i32 %add, 12
606 define <2 x i1> @tautological9_vec(<2 x i32> %x) {
607 ; CHECK-LABEL: @tautological9_vec(
608 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
610 %add = add nuw <2 x i32> %x, <i32 13, i32 13>
611 %cmp = icmp ne <2 x i32> %add, <i32 12, i32 12>
615 ; The upper bound of the 'add' is 0.
617 define i1 @add_nsw_neg_const1(i32 %x) {
618 ; CHECK-LABEL: @add_nsw_neg_const1(
619 ; CHECK-NEXT: ret i1 false
621 %add = add nsw i32 %x, -2147483647
622 %cmp = icmp sgt i32 %add, 0
626 define i1 @add_nsw_sgt(i8 %x) {
627 ; CHECK-LABEL: @add_nsw_sgt(
628 ; CHECK-NEXT: ret i1 true
630 %add = add nsw i8 %x, 5
631 %cmp = icmp sgt i8 %add, -124
635 ; nuw should not inhibit the fold.
637 define i1 @add_nsw_nuw_sgt(i8 %x) {
638 ; CHECK-LABEL: @add_nsw_nuw_sgt(
639 ; CHECK-NEXT: ret i1 true
641 %add = add nsw nuw i8 %x, 5
642 %cmp = icmp sgt i8 %add, -124
646 ; negative test - minimum x is -128, so add could be -124.
648 define i1 @add_nsw_sgt_limit(i8 %x) {
649 ; CHECK-LABEL: @add_nsw_sgt_limit(
650 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[X:%.*]], 4
651 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[ADD]], -124
652 ; CHECK-NEXT: ret i1 [[CMP]]
654 %add = add nsw i8 %x, 4
655 %cmp = icmp sgt i8 %add, -124
659 define i1 @add_nsw_slt(i8 %x) {
660 ; CHECK-LABEL: @add_nsw_slt(
661 ; CHECK-NEXT: ret i1 false
663 %add = add nsw i8 %x, 5
664 %cmp = icmp slt i8 %add, -123
668 ; nuw should not inhibit the fold.
670 define i1 @add_nsw_nuw_slt(i8 %x) {
671 ; CHECK-LABEL: @add_nsw_nuw_slt(
672 ; CHECK-NEXT: ret i1 false
674 %add = add nsw nuw i8 %x, 5
675 %cmp = icmp slt i8 %add, -123
679 ; negative test - minimum x is -128, so add could be -123.
681 define i1 @add_nsw_slt_limit(i8 %x) {
682 ; CHECK-LABEL: @add_nsw_slt_limit(
683 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[X:%.*]], 5
684 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[ADD]], -122
685 ; CHECK-NEXT: ret i1 [[CMP]]
687 %add = add nsw i8 %x, 5
688 %cmp = icmp slt i8 %add, -122
692 ; InstCombine can fold this, but not InstSimplify.
694 define i1 @add_nsw_neg_const2(i32 %x) {
695 ; CHECK-LABEL: @add_nsw_neg_const2(
696 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], -2147483647
697 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD]], -1
698 ; CHECK-NEXT: ret i1 [[CMP]]
700 %add = add nsw i32 %x, -2147483647
701 %cmp = icmp sgt i32 %add, -1
705 ; The upper bound of the 'add' is 1 (move the constants to prove we're doing range-based analysis).
707 define i1 @add_nsw_neg_const3(i32 %x) {
708 ; CHECK-LABEL: @add_nsw_neg_const3(
709 ; CHECK-NEXT: ret i1 false
711 %add = add nsw i32 %x, -2147483646
712 %cmp = icmp sgt i32 %add, 1
716 ; InstCombine can fold this, but not InstSimplify.
718 define i1 @add_nsw_neg_const4(i32 %x) {
719 ; CHECK-LABEL: @add_nsw_neg_const4(
720 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], -2147483646
721 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD]], 0
722 ; CHECK-NEXT: ret i1 [[CMP]]
724 %add = add nsw i32 %x, -2147483646
725 %cmp = icmp sgt i32 %add, 0
729 ; The upper bound of the 'add' is 2147483647 - 42 = 2147483605 (move the constants again and try a different cmp predicate).
731 define i1 @add_nsw_neg_const5(i32 %x) {
732 ; CHECK-LABEL: @add_nsw_neg_const5(
733 ; CHECK-NEXT: ret i1 true
735 %add = add nsw i32 %x, -42
736 %cmp = icmp ne i32 %add, 2147483606
740 ; InstCombine can fold this, but not InstSimplify.
742 define i1 @add_nsw_neg_const6(i32 %x) {
743 ; CHECK-LABEL: @add_nsw_neg_const6(
744 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], -42
745 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[ADD]], 2147483605
746 ; CHECK-NEXT: ret i1 [[CMP]]
748 %add = add nsw i32 %x, -42
749 %cmp = icmp ne i32 %add, 2147483605
753 ; The lower bound of the 'add' is -1.
755 define i1 @add_nsw_pos_const1(i32 %x) {
756 ; CHECK-LABEL: @add_nsw_pos_const1(
757 ; CHECK-NEXT: ret i1 false
759 %add = add nsw i32 %x, 2147483647
760 %cmp = icmp slt i32 %add, -1
764 ; InstCombine can fold this, but not InstSimplify.
766 define i1 @add_nsw_pos_const2(i32 %x) {
767 ; CHECK-LABEL: @add_nsw_pos_const2(
768 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], 2147483647
769 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD]], 0
770 ; CHECK-NEXT: ret i1 [[CMP]]
772 %add = add nsw i32 %x, 2147483647
773 %cmp = icmp slt i32 %add, 0
777 ; The lower bound of the 'add' is -2 (move the constants to prove we're doing range-based analysis).
779 define i1 @add_nsw_pos_const3(i32 %x) {
780 ; CHECK-LABEL: @add_nsw_pos_const3(
781 ; CHECK-NEXT: ret i1 false
783 %add = add nsw i32 %x, 2147483646
784 %cmp = icmp slt i32 %add, -2
788 ; InstCombine can fold this, but not InstSimplify.
790 define i1 @add_nsw_pos_const4(i32 %x) {
791 ; CHECK-LABEL: @add_nsw_pos_const4(
792 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], 2147483646
793 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD]], -1
794 ; CHECK-NEXT: ret i1 [[CMP]]
796 %add = add nsw i32 %x, 2147483646
797 %cmp = icmp slt i32 %add, -1
801 ; The lower bound of the 'add' is -2147483648 + 42 = -2147483606 (move the constants again and change the cmp predicate).
803 define i1 @add_nsw_pos_const5(i32 %x) {
804 ; CHECK-LABEL: @add_nsw_pos_const5(
805 ; CHECK-NEXT: ret i1 false
807 %add = add nsw i32 %x, 42
808 %cmp = icmp eq i32 %add, -2147483607
812 ; InstCombine can fold this, but not InstSimplify.
814 define i1 @add_nsw_pos_const6(i32 %x) {
815 ; CHECK-LABEL: @add_nsw_pos_const6(
816 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], 42
817 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ADD]], -2147483606
818 ; CHECK-NEXT: ret i1 [[CMP]]
820 %add = add nsw i32 %x, 42
821 %cmp = icmp eq i32 %add, -2147483606
825 ; Verify that vectors work too.
827 define <2 x i1> @add_nsw_pos_const5_splat_vec(<2 x i32> %x) {
828 ; CHECK-LABEL: @add_nsw_pos_const5_splat_vec(
829 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
831 %add = add nsw <2 x i32> %x, <i32 42, i32 42>
832 %cmp = icmp ne <2 x i32> %add, <i32 -2147483607, i32 -2147483607>
836 ; PR34838 - https://bugs.llvm.org/show_bug.cgi?id=34838
837 ; The shift is known to create poison, so we can simplify the cmp.
839 define i1 @ne_shl_by_constant_produces_poison(i8 %x) {
840 ; CHECK-LABEL: @ne_shl_by_constant_produces_poison(
841 ; CHECK-NEXT: ret i1 poison
843 %zx = zext i8 %x to i16 ; zx = 0x00xx
844 %xor = xor i16 %zx, 32767 ; xor = 0x7fyy
845 %sub = sub nsw i16 %zx, %xor ; sub = 0x80zz (the top bit is known one)
846 %poison = shl nsw i16 %sub, 2 ; oops! this shl can't be nsw; that's POISON
847 %cmp = icmp ne i16 %poison, 1
851 define i1 @eq_shl_by_constant_produces_poison(i8 %x) {
852 ; CHECK-LABEL: @eq_shl_by_constant_produces_poison(
853 ; CHECK-NEXT: ret i1 poison
855 %clear_high_bit = and i8 %x, 127 ; 0x7f
856 %set_next_high_bits = or i8 %clear_high_bit, 112 ; 0x70
857 %poison = shl nsw i8 %set_next_high_bits, 3
858 %cmp = icmp eq i8 %poison, 15
862 ; Shift-by-variable that produces poison is more complicated but still possible.
863 ; We guarantee that the shift will change the sign of the shifted value (and
864 ; therefore produce poison) by limiting its range from 1 to 3.
866 define i1 @eq_shl_by_variable_produces_poison(i8 %x) {
867 ; CHECK-LABEL: @eq_shl_by_variable_produces_poison(
868 ; CHECK-NEXT: ret i1 poison
870 %clear_high_bit = and i8 %x, 127 ; 0x7f
871 %set_next_high_bits = or i8 %clear_high_bit, 112 ; 0x70
872 %notundef_shiftamt = and i8 %x, 3
873 %nonzero_shiftamt = or i8 %notundef_shiftamt, 1
874 %poison = shl nsw i8 %set_next_high_bits, %nonzero_shiftamt
875 %cmp = icmp eq i8 %poison, 15
879 ; No overflow, so mul constant must be a factor of cmp constant.
881 define i1 @mul_nuw_urem_cmp_constant1(i8 %x) {
882 ; CHECK-LABEL: @mul_nuw_urem_cmp_constant1(
883 ; CHECK-NEXT: ret i1 false
885 %m = mul nuw i8 %x, 43
886 %r = icmp eq i8 %m, 42
890 ; Invert predicate and check vector type.
892 define <2 x i1> @mul_nuw_urem_cmp_constant_vec_splat(<2 x i8> %x) {
893 ; CHECK-LABEL: @mul_nuw_urem_cmp_constant_vec_splat(
894 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
896 %m = mul nuw <2 x i8> %x, <i8 45, i8 45>
897 %r = icmp ne <2 x i8> %m, <i8 15, i8 15>
901 ; Undefs in vector constants are ok.
903 define <2 x i1> @mul_nuw_urem_cmp_constant_vec_splat_undef1(<2 x i8> %x) {
904 ; CHECK-LABEL: @mul_nuw_urem_cmp_constant_vec_splat_undef1(
905 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
907 %m = mul nuw <2 x i8> %x, <i8 45, i8 45>
908 %r = icmp ne <2 x i8> %m, <i8 15, i8 undef>
912 ; Undefs in vector constants are ok.
914 define <2 x i1> @mul_nuw_urem_cmp_constant_vec_splat_undef2(<2 x i8> %x) {
915 ; CHECK-LABEL: @mul_nuw_urem_cmp_constant_vec_splat_undef2(
916 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
918 %m = mul nuw <2 x i8> %x, <i8 undef, i8 45>
919 %r = icmp ne <2 x i8> %m, <i8 15, i8 15>
923 ; Check "negative" numbers (constants should be analyzed as unsigned).
925 define i1 @mul_nuw_urem_cmp_constant2(i8 %x) {
926 ; CHECK-LABEL: @mul_nuw_urem_cmp_constant2(
927 ; CHECK-NEXT: ret i1 false
929 %m = mul nuw i8 %x, -42
930 %r = icmp eq i8 %m, -84
934 ; Negative test - require nuw.
936 define i1 @mul_urem_cmp_constant1(i8 %x) {
937 ; CHECK-LABEL: @mul_urem_cmp_constant1(
938 ; CHECK-NEXT: [[M:%.*]] = mul i8 [[X:%.*]], 43
939 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 42
940 ; CHECK-NEXT: ret i1 [[R]]
943 %r = icmp eq i8 %m, 42
947 ; Negative test - x could be 0.
949 define i1 @mul_nuw_urem_cmp_constant0(i8 %x) {
950 ; CHECK-LABEL: @mul_nuw_urem_cmp_constant0(
951 ; CHECK-NEXT: [[M:%.*]] = mul nuw i8 [[X:%.*]], 23
952 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 0
953 ; CHECK-NEXT: ret i1 [[R]]
955 %m = mul nuw i8 %x, 23
956 %r = icmp eq i8 %m, 0
960 ; Negative test - cmp constant is multiple of mul constant.
962 define i1 @mul_nuw_urem_cmp_constant_is_0(i8 %x) {
963 ; CHECK-LABEL: @mul_nuw_urem_cmp_constant_is_0(
964 ; CHECK-NEXT: [[M:%.*]] = mul nuw i8 [[X:%.*]], 42
965 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 84
966 ; CHECK-NEXT: ret i1 [[R]]
968 %m = mul nuw i8 %x, 42
969 %r = icmp eq i8 %m, 84
973 ; Negative test - cmp constant is multiple (treated as unsigned).
975 define i1 @mul_nuw_urem_cmp_neg_constant_is_0(i8 %x) {
976 ; CHECK-LABEL: @mul_nuw_urem_cmp_neg_constant_is_0(
977 ; CHECK-NEXT: [[M:%.*]] = mul nuw i8 [[X:%.*]], 43
978 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], -127
979 ; CHECK-NEXT: ret i1 [[R]]
981 %m = mul nuw i8 %x, 43
982 %r = icmp eq i8 %m, -127
986 ; No overflow, so mul constant must be a factor of cmp constant.
988 define i1 @mul_nsw_srem_cmp_constant1(i8 %x) {
989 ; CHECK-LABEL: @mul_nsw_srem_cmp_constant1(
990 ; CHECK-NEXT: ret i1 false
992 %m = mul nsw i8 %x, 43
993 %r = icmp eq i8 %m, 45
997 ; Invert predicate and check vector type.
999 define <2 x i1> @mul_nsw_srem_cmp_constant_vec_splat(<2 x i8> %x) {
1000 ; CHECK-LABEL: @mul_nsw_srem_cmp_constant_vec_splat(
1001 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
1003 %m = mul nsw <2 x i8> %x, <i8 45, i8 45>
1004 %r = icmp ne <2 x i8> %m, <i8 15, i8 15>
1008 ; Undefs in vector constants are ok.
1010 define <2 x i1> @mul_nsw_srem_cmp_constant_vec_splat_undef1(<2 x i8> %x) {
1011 ; CHECK-LABEL: @mul_nsw_srem_cmp_constant_vec_splat_undef1(
1012 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
1014 %m = mul nsw <2 x i8> %x, <i8 45, i8 45>
1015 %r = icmp ne <2 x i8> %m, <i8 15, i8 undef>
1019 ; Undefs in vector constants are ok.
1021 define <2 x i1> @mul_nsw_srem_cmp_constant_vec_splat_undef2(<2 x i8> %x) {
1022 ; CHECK-LABEL: @mul_nsw_srem_cmp_constant_vec_splat_undef2(
1023 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
1025 %m = mul nsw <2 x i8> %x, <i8 undef, i8 45>
1026 %r = icmp ne <2 x i8> %m, <i8 15, i8 15>
1030 ; Check negative numbers (constants should be analyzed as signed).
1032 define i1 @mul_nsw_srem_cmp_constant2(i8 %x) {
1033 ; CHECK-LABEL: @mul_nsw_srem_cmp_constant2(
1034 ; CHECK-NEXT: ret i1 false
1036 %m = mul nsw i8 %x, 43
1037 %r = icmp eq i8 %m, -127
1041 ; Negative test - require nsw.
1043 define i1 @mul_srem_cmp_constant1(i8 %x) {
1044 ; CHECK-LABEL: @mul_srem_cmp_constant1(
1045 ; CHECK-NEXT: [[M:%.*]] = mul i8 [[X:%.*]], 43
1046 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 42
1047 ; CHECK-NEXT: ret i1 [[R]]
1050 %r = icmp eq i8 %m, 42
1054 ; Negative test - x could be 0.
1056 define i1 @mul_nsw_srem_cmp_constant0(i8 %x) {
1057 ; CHECK-LABEL: @mul_nsw_srem_cmp_constant0(
1058 ; CHECK-NEXT: [[M:%.*]] = mul nsw i8 [[X:%.*]], 23
1059 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 0
1060 ; CHECK-NEXT: ret i1 [[R]]
1062 %m = mul nsw i8 %x, 23
1063 %r = icmp eq i8 %m, 0
1067 ; Negative test - cmp constant is multiple of mul constant.
1069 define i1 @mul_nsw_srem_cmp_constant_is_0(i8 %x) {
1070 ; CHECK-LABEL: @mul_nsw_srem_cmp_constant_is_0(
1071 ; CHECK-NEXT: [[M:%.*]] = mul nsw i8 [[X:%.*]], 42
1072 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 84
1073 ; CHECK-NEXT: ret i1 [[R]]
1075 %m = mul nsw i8 %x, 42
1076 %r = icmp eq i8 %m, 84
1080 ; Negative test - cmp constant is multiple (treated as signed).
1082 define i1 @mul_nsw_srem_cmp_neg_constant_is_0(i8 %x) {
1083 ; CHECK-LABEL: @mul_nsw_srem_cmp_neg_constant_is_0(
1084 ; CHECK-NEXT: [[M:%.*]] = mul nsw i8 [[X:%.*]], -42
1085 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], -84
1086 ; CHECK-NEXT: ret i1 [[R]]
1088 %m = mul nsw i8 %x, -42
1089 %r = icmp eq i8 %m, -84
1093 ; Don't crash trying to div/rem-by-zero.
1095 define i1 @mul_nsw_by_zero(i8 %x) {
1096 ; CHECK-LABEL: @mul_nsw_by_zero(
1098 ; CHECK-NEXT: br label [[BB3:%.*]]
1100 ; CHECK-NEXT: ret i1 false
1102 ; CHECK-NEXT: br label [[BB2:%.*]]
1107 %r = icmp eq i8 %m, 45
1110 %m = mul nsw i8 %x, 0
1114 ; Don't crash trying to div/rem-by-zero.
1116 define i1 @mul_nuw_by_zero(i8 %x) {
1117 ; CHECK-LABEL: @mul_nuw_by_zero(
1119 ; CHECK-NEXT: br label [[BB3:%.*]]
1121 ; CHECK-NEXT: ret i1 false
1123 ; CHECK-NEXT: br label [[BB2:%.*]]
1128 %r = icmp eq i8 %m, 45
1131 %m = mul nuw i8 %x, 0
1136 define <2 x i1> @heterogeneous_constvector(<2 x i8> %x) {
1137 ; CHECK-LABEL: @heterogeneous_constvector(
1138 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
1140 %c = icmp ult <2 x i8> %x, <i8 undef, i8 poison>