1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -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 ; InstCombine can fold this, but not InstSimplify.
628 define i1 @add_nsw_neg_const2(i32 %x) {
629 ; CHECK-LABEL: @add_nsw_neg_const2(
630 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], -2147483647
631 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD]], -1
632 ; CHECK-NEXT: ret i1 [[CMP]]
634 %add = add nsw i32 %x, -2147483647
635 %cmp = icmp sgt i32 %add, -1
639 ; The upper bound of the 'add' is 1 (move the constants to prove we're doing range-based analysis).
641 define i1 @add_nsw_neg_const3(i32 %x) {
642 ; CHECK-LABEL: @add_nsw_neg_const3(
643 ; CHECK-NEXT: ret i1 false
645 %add = add nsw i32 %x, -2147483646
646 %cmp = icmp sgt i32 %add, 1
650 ; InstCombine can fold this, but not InstSimplify.
652 define i1 @add_nsw_neg_const4(i32 %x) {
653 ; CHECK-LABEL: @add_nsw_neg_const4(
654 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], -2147483646
655 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD]], 0
656 ; CHECK-NEXT: ret i1 [[CMP]]
658 %add = add nsw i32 %x, -2147483646
659 %cmp = icmp sgt i32 %add, 0
663 ; The upper bound of the 'add' is 2147483647 - 42 = 2147483605 (move the constants again and try a different cmp predicate).
665 define i1 @add_nsw_neg_const5(i32 %x) {
666 ; CHECK-LABEL: @add_nsw_neg_const5(
667 ; CHECK-NEXT: ret i1 true
669 %add = add nsw i32 %x, -42
670 %cmp = icmp ne i32 %add, 2147483606
674 ; InstCombine can fold this, but not InstSimplify.
676 define i1 @add_nsw_neg_const6(i32 %x) {
677 ; CHECK-LABEL: @add_nsw_neg_const6(
678 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], -42
679 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[ADD]], 2147483605
680 ; CHECK-NEXT: ret i1 [[CMP]]
682 %add = add nsw i32 %x, -42
683 %cmp = icmp ne i32 %add, 2147483605
687 ; The lower bound of the 'add' is -1.
689 define i1 @add_nsw_pos_const1(i32 %x) {
690 ; CHECK-LABEL: @add_nsw_pos_const1(
691 ; CHECK-NEXT: ret i1 false
693 %add = add nsw i32 %x, 2147483647
694 %cmp = icmp slt i32 %add, -1
698 ; InstCombine can fold this, but not InstSimplify.
700 define i1 @add_nsw_pos_const2(i32 %x) {
701 ; CHECK-LABEL: @add_nsw_pos_const2(
702 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], 2147483647
703 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD]], 0
704 ; CHECK-NEXT: ret i1 [[CMP]]
706 %add = add nsw i32 %x, 2147483647
707 %cmp = icmp slt i32 %add, 0
711 ; The lower bound of the 'add' is -2 (move the constants to prove we're doing range-based analysis).
713 define i1 @add_nsw_pos_const3(i32 %x) {
714 ; CHECK-LABEL: @add_nsw_pos_const3(
715 ; CHECK-NEXT: ret i1 false
717 %add = add nsw i32 %x, 2147483646
718 %cmp = icmp slt i32 %add, -2
722 ; InstCombine can fold this, but not InstSimplify.
724 define i1 @add_nsw_pos_const4(i32 %x) {
725 ; CHECK-LABEL: @add_nsw_pos_const4(
726 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], 2147483646
727 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD]], -1
728 ; CHECK-NEXT: ret i1 [[CMP]]
730 %add = add nsw i32 %x, 2147483646
731 %cmp = icmp slt i32 %add, -1
735 ; The lower bound of the 'add' is -2147483648 + 42 = -2147483606 (move the constants again and change the cmp predicate).
737 define i1 @add_nsw_pos_const5(i32 %x) {
738 ; CHECK-LABEL: @add_nsw_pos_const5(
739 ; CHECK-NEXT: ret i1 false
741 %add = add nsw i32 %x, 42
742 %cmp = icmp eq i32 %add, -2147483607
746 ; InstCombine can fold this, but not InstSimplify.
748 define i1 @add_nsw_pos_const6(i32 %x) {
749 ; CHECK-LABEL: @add_nsw_pos_const6(
750 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], 42
751 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ADD]], -2147483606
752 ; CHECK-NEXT: ret i1 [[CMP]]
754 %add = add nsw i32 %x, 42
755 %cmp = icmp eq i32 %add, -2147483606
759 ; Verify that vectors work too.
761 define <2 x i1> @add_nsw_pos_const5_splat_vec(<2 x i32> %x) {
762 ; CHECK-LABEL: @add_nsw_pos_const5_splat_vec(
763 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
765 %add = add nsw <2 x i32> %x, <i32 42, i32 42>
766 %cmp = icmp ne <2 x i32> %add, <i32 -2147483607, i32 -2147483607>
770 ; PR34838 - https://bugs.llvm.org/show_bug.cgi?id=34838
771 ; The shift is known to create poison, so we can simplify the cmp.
773 define i1 @ne_shl_by_constant_produces_poison(i8 %x) {
774 ; CHECK-LABEL: @ne_shl_by_constant_produces_poison(
775 ; CHECK-NEXT: ret i1 poison
777 %zx = zext i8 %x to i16 ; zx = 0x00xx
778 %xor = xor i16 %zx, 32767 ; xor = 0x7fyy
779 %sub = sub nsw i16 %zx, %xor ; sub = 0x80zz (the top bit is known one)
780 %poison = shl nsw i16 %sub, 2 ; oops! this shl can't be nsw; that's POISON
781 %cmp = icmp ne i16 %poison, 1
785 define i1 @eq_shl_by_constant_produces_poison(i8 %x) {
786 ; CHECK-LABEL: @eq_shl_by_constant_produces_poison(
787 ; CHECK-NEXT: ret i1 poison
789 %clear_high_bit = and i8 %x, 127 ; 0x7f
790 %set_next_high_bits = or i8 %clear_high_bit, 112 ; 0x70
791 %poison = shl nsw i8 %set_next_high_bits, 3
792 %cmp = icmp eq i8 %poison, 15
796 ; Shift-by-variable that produces poison is more complicated but still possible.
797 ; We guarantee that the shift will change the sign of the shifted value (and
798 ; therefore produce poison) by limiting its range from 1 to 3.
800 define i1 @eq_shl_by_variable_produces_poison(i8 %x) {
801 ; CHECK-LABEL: @eq_shl_by_variable_produces_poison(
802 ; CHECK-NEXT: ret i1 poison
804 %clear_high_bit = and i8 %x, 127 ; 0x7f
805 %set_next_high_bits = or i8 %clear_high_bit, 112 ; 0x70
806 %notundef_shiftamt = and i8 %x, 3
807 %nonzero_shiftamt = or i8 %notundef_shiftamt, 1
808 %poison = shl nsw i8 %set_next_high_bits, %nonzero_shiftamt
809 %cmp = icmp eq i8 %poison, 15
813 ; No overflow, so mul constant must be a factor of cmp constant.
815 define i1 @mul_nuw_urem_cmp_constant1(i8 %x) {
816 ; CHECK-LABEL: @mul_nuw_urem_cmp_constant1(
817 ; CHECK-NEXT: ret i1 false
819 %m = mul nuw i8 %x, 43
820 %r = icmp eq i8 %m, 42
824 ; Invert predicate and check vector type.
826 define <2 x i1> @mul_nuw_urem_cmp_constant_vec_splat(<2 x i8> %x) {
827 ; CHECK-LABEL: @mul_nuw_urem_cmp_constant_vec_splat(
828 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
830 %m = mul nuw <2 x i8> %x, <i8 45, i8 45>
831 %r = icmp ne <2 x i8> %m, <i8 15, i8 15>
835 ; Undefs in vector constants are ok.
837 define <2 x i1> @mul_nuw_urem_cmp_constant_vec_splat_undef1(<2 x i8> %x) {
838 ; CHECK-LABEL: @mul_nuw_urem_cmp_constant_vec_splat_undef1(
839 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
841 %m = mul nuw <2 x i8> %x, <i8 45, i8 45>
842 %r = icmp ne <2 x i8> %m, <i8 15, i8 undef>
846 ; Undefs in vector constants are ok.
848 define <2 x i1> @mul_nuw_urem_cmp_constant_vec_splat_undef2(<2 x i8> %x) {
849 ; CHECK-LABEL: @mul_nuw_urem_cmp_constant_vec_splat_undef2(
850 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
852 %m = mul nuw <2 x i8> %x, <i8 undef, i8 45>
853 %r = icmp ne <2 x i8> %m, <i8 15, i8 15>
857 ; Check "negative" numbers (constants should be analyzed as unsigned).
859 define i1 @mul_nuw_urem_cmp_constant2(i8 %x) {
860 ; CHECK-LABEL: @mul_nuw_urem_cmp_constant2(
861 ; CHECK-NEXT: ret i1 false
863 %m = mul nuw i8 %x, -42
864 %r = icmp eq i8 %m, -84
868 ; Negative test - require nuw.
870 define i1 @mul_urem_cmp_constant1(i8 %x) {
871 ; CHECK-LABEL: @mul_urem_cmp_constant1(
872 ; CHECK-NEXT: [[M:%.*]] = mul i8 [[X:%.*]], 43
873 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 42
874 ; CHECK-NEXT: ret i1 [[R]]
877 %r = icmp eq i8 %m, 42
881 ; Negative test - x could be 0.
883 define i1 @mul_nuw_urem_cmp_constant0(i8 %x) {
884 ; CHECK-LABEL: @mul_nuw_urem_cmp_constant0(
885 ; CHECK-NEXT: [[M:%.*]] = mul nuw i8 [[X:%.*]], 23
886 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 0
887 ; CHECK-NEXT: ret i1 [[R]]
889 %m = mul nuw i8 %x, 23
890 %r = icmp eq i8 %m, 0
894 ; Negative test - cmp constant is multiple of mul constant.
896 define i1 @mul_nuw_urem_cmp_constant_is_0(i8 %x) {
897 ; CHECK-LABEL: @mul_nuw_urem_cmp_constant_is_0(
898 ; CHECK-NEXT: [[M:%.*]] = mul nuw i8 [[X:%.*]], 42
899 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 84
900 ; CHECK-NEXT: ret i1 [[R]]
902 %m = mul nuw i8 %x, 42
903 %r = icmp eq i8 %m, 84
907 ; Negative test - cmp constant is multiple (treated as unsigned).
909 define i1 @mul_nuw_urem_cmp_neg_constant_is_0(i8 %x) {
910 ; CHECK-LABEL: @mul_nuw_urem_cmp_neg_constant_is_0(
911 ; CHECK-NEXT: [[M:%.*]] = mul nuw i8 [[X:%.*]], 43
912 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], -127
913 ; CHECK-NEXT: ret i1 [[R]]
915 %m = mul nuw i8 %x, 43
916 %r = icmp eq i8 %m, -127
920 ; No overflow, so mul constant must be a factor of cmp constant.
922 define i1 @mul_nsw_srem_cmp_constant1(i8 %x) {
923 ; CHECK-LABEL: @mul_nsw_srem_cmp_constant1(
924 ; CHECK-NEXT: ret i1 false
926 %m = mul nsw i8 %x, 43
927 %r = icmp eq i8 %m, 45
931 ; Invert predicate and check vector type.
933 define <2 x i1> @mul_nsw_srem_cmp_constant_vec_splat(<2 x i8> %x) {
934 ; CHECK-LABEL: @mul_nsw_srem_cmp_constant_vec_splat(
935 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
937 %m = mul nsw <2 x i8> %x, <i8 45, i8 45>
938 %r = icmp ne <2 x i8> %m, <i8 15, i8 15>
942 ; Undefs in vector constants are ok.
944 define <2 x i1> @mul_nsw_srem_cmp_constant_vec_splat_undef1(<2 x i8> %x) {
945 ; CHECK-LABEL: @mul_nsw_srem_cmp_constant_vec_splat_undef1(
946 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
948 %m = mul nsw <2 x i8> %x, <i8 45, i8 45>
949 %r = icmp ne <2 x i8> %m, <i8 15, i8 undef>
953 ; Undefs in vector constants are ok.
955 define <2 x i1> @mul_nsw_srem_cmp_constant_vec_splat_undef2(<2 x i8> %x) {
956 ; CHECK-LABEL: @mul_nsw_srem_cmp_constant_vec_splat_undef2(
957 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
959 %m = mul nsw <2 x i8> %x, <i8 undef, i8 45>
960 %r = icmp ne <2 x i8> %m, <i8 15, i8 15>
964 ; Check negative numbers (constants should be analyzed as signed).
966 define i1 @mul_nsw_srem_cmp_constant2(i8 %x) {
967 ; CHECK-LABEL: @mul_nsw_srem_cmp_constant2(
968 ; CHECK-NEXT: ret i1 false
970 %m = mul nsw i8 %x, 43
971 %r = icmp eq i8 %m, -127
975 ; Negative test - require nsw.
977 define i1 @mul_srem_cmp_constant1(i8 %x) {
978 ; CHECK-LABEL: @mul_srem_cmp_constant1(
979 ; CHECK-NEXT: [[M:%.*]] = mul i8 [[X:%.*]], 43
980 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 42
981 ; CHECK-NEXT: ret i1 [[R]]
984 %r = icmp eq i8 %m, 42
988 ; Negative test - x could be 0.
990 define i1 @mul_nsw_srem_cmp_constant0(i8 %x) {
991 ; CHECK-LABEL: @mul_nsw_srem_cmp_constant0(
992 ; CHECK-NEXT: [[M:%.*]] = mul nsw i8 [[X:%.*]], 23
993 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 0
994 ; CHECK-NEXT: ret i1 [[R]]
996 %m = mul nsw i8 %x, 23
997 %r = icmp eq i8 %m, 0
1001 ; Negative test - cmp constant is multiple of mul constant.
1003 define i1 @mul_nsw_srem_cmp_constant_is_0(i8 %x) {
1004 ; CHECK-LABEL: @mul_nsw_srem_cmp_constant_is_0(
1005 ; CHECK-NEXT: [[M:%.*]] = mul nsw i8 [[X:%.*]], 42
1006 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 84
1007 ; CHECK-NEXT: ret i1 [[R]]
1009 %m = mul nsw i8 %x, 42
1010 %r = icmp eq i8 %m, 84
1014 ; Negative test - cmp constant is multiple (treated as signed).
1016 define i1 @mul_nsw_srem_cmp_neg_constant_is_0(i8 %x) {
1017 ; CHECK-LABEL: @mul_nsw_srem_cmp_neg_constant_is_0(
1018 ; CHECK-NEXT: [[M:%.*]] = mul nsw i8 [[X:%.*]], -42
1019 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], -84
1020 ; CHECK-NEXT: ret i1 [[R]]
1022 %m = mul nsw i8 %x, -42
1023 %r = icmp eq i8 %m, -84
1027 ; Don't crash trying to div/rem-by-zero.
1029 define i1 @mul_nsw_by_zero(i8 %x) {
1030 ; CHECK-LABEL: @mul_nsw_by_zero(
1032 ; CHECK-NEXT: br label [[BB3:%.*]]
1034 ; CHECK-NEXT: ret i1 false
1036 ; CHECK-NEXT: br label [[BB2:%.*]]
1041 %r = icmp eq i8 %m, 45
1044 %m = mul nsw i8 %x, 0
1048 ; Don't crash trying to div/rem-by-zero.
1050 define i1 @mul_nuw_by_zero(i8 %x) {
1051 ; CHECK-LABEL: @mul_nuw_by_zero(
1053 ; CHECK-NEXT: br label [[BB3:%.*]]
1055 ; CHECK-NEXT: ret i1 false
1057 ; CHECK-NEXT: br label [[BB2:%.*]]
1062 %r = icmp eq i8 %m, 45
1065 %m = mul nuw i8 %x, 0
1070 define <2 x i1> @heterogeneous_constvector(<2 x i8> %x) {
1071 ; CHECK-LABEL: @heterogeneous_constvector(
1072 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
1074 %c = icmp ult <2 x i8> %x, <i8 undef, i8 poison>