2016-06-21 02:40:37 +08:00
|
|
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
|
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
|
|
|
|
|
|
|
define i1 @PR1817_1(i32 %X) {
|
|
|
|
; CHECK-LABEL: @PR1817_1(
|
|
|
|
; CHECK-NEXT: [[A:%.*]] = icmp slt i32 %X, 10
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ult i32 %X, 10
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = and i1 [[A]], [[B]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%A = icmp slt i32 %X, 10
|
|
|
|
%B = icmp ult i32 %X, 10
|
|
|
|
%C = and i1 %A, %B
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @PR1817_2(i32 %X) {
|
|
|
|
; CHECK-LABEL: @PR1817_2(
|
|
|
|
; CHECK-NEXT: [[A:%.*]] = icmp slt i32 %X, 10
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ult i32 %X, 10
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = or i1 [[A]], [[B]]
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%A = icmp slt i32 %X, 10
|
|
|
|
%B = icmp ult i32 %X, 10
|
|
|
|
%C = or i1 %A, %B
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @PR2330(i32 %a, i32 %b) {
|
|
|
|
; CHECK-LABEL: @PR2330(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or i32 %b, %a
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[TMP1]], 8
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
|
|
|
;
|
|
|
|
%cmp1 = icmp ult i32 %a, 8
|
|
|
|
%cmp2 = icmp ult i32 %b, 8
|
|
|
|
%and = and i1 %cmp2, %cmp1
|
|
|
|
ret i1 %and
|
|
|
|
}
|
|
|
|
|
2017-04-15 02:19:27 +08:00
|
|
|
; if LHSC and RHSC differ only by one bit:
|
|
|
|
; (X == C1 || X == C2) -> (X | (C1 ^ C2)) == C2
|
|
|
|
; PR14708: https://bugs.llvm.org/show_bug.cgi?id=14708
|
|
|
|
|
|
|
|
define i1 @or_eq_with_one_bit_diff_constants1(i32 %x) {
|
|
|
|
; CHECK-LABEL: @or_eq_with_one_bit_diff_constants1(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or i32 %x, 1
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 51
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
|
|
|
;
|
|
|
|
%cmp1 = icmp eq i32 %x, 50
|
|
|
|
%cmp2 = icmp eq i32 %x, 51
|
|
|
|
%or = or i1 %cmp1, %cmp2
|
|
|
|
ret i1 %or
|
|
|
|
}
|
|
|
|
|
|
|
|
; (X != C1 && X != C2) -> (X | (C1 ^ C2)) != C2
|
|
|
|
|
|
|
|
define i1 @and_ne_with_one_bit_diff_constants1(i32 %x) {
|
|
|
|
; CHECK-LABEL: @and_ne_with_one_bit_diff_constants1(
|
2017-04-15 03:23:50 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or i32 %x, 1
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 51
|
2017-04-15 02:19:27 +08:00
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
|
|
|
;
|
|
|
|
%cmp1 = icmp ne i32 %x, 51
|
|
|
|
%cmp2 = icmp ne i32 %x, 50
|
|
|
|
%and = and i1 %cmp1, %cmp2
|
|
|
|
ret i1 %and
|
|
|
|
}
|
|
|
|
|
|
|
|
; The constants are not necessarily off-by-one, just off-by-one-bit.
|
|
|
|
|
|
|
|
define i1 @or_eq_with_one_bit_diff_constants2(i32 %x) {
|
|
|
|
; CHECK-LABEL: @or_eq_with_one_bit_diff_constants2(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or i32 %x, 32
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 97
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
2016-06-21 02:40:37 +08:00
|
|
|
;
|
2017-04-15 02:19:27 +08:00
|
|
|
%cmp1 = icmp eq i32 %x, 97
|
|
|
|
%cmp2 = icmp eq i32 %x, 65
|
|
|
|
%or = or i1 %cmp1, %cmp2
|
|
|
|
ret i1 %or
|
2016-06-21 02:40:37 +08:00
|
|
|
}
|
|
|
|
|
2017-04-15 02:19:27 +08:00
|
|
|
define i1 @and_ne_with_one_bit_diff_constants2(i19 %x) {
|
|
|
|
; CHECK-LABEL: @and_ne_with_one_bit_diff_constants2(
|
2017-04-15 03:23:50 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or i19 %x, 128
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i19 [[TMP1]], 193
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
2017-04-15 02:19:27 +08:00
|
|
|
;
|
|
|
|
%cmp1 = icmp ne i19 %x, 65
|
|
|
|
%cmp2 = icmp ne i19 %x, 193
|
|
|
|
%and = and i1 %cmp1, %cmp2
|
|
|
|
ret i1 %and
|
|
|
|
}
|
|
|
|
|
|
|
|
; Make sure the constants are treated as unsigned when comparing them.
|
|
|
|
|
|
|
|
define i1 @or_eq_with_one_bit_diff_constants3(i8 %x) {
|
|
|
|
; CHECK-LABEL: @or_eq_with_one_bit_diff_constants3(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or i8 %x, -128
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], -2
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
|
|
|
;
|
|
|
|
%cmp1 = icmp eq i8 %x, 254
|
|
|
|
%cmp2 = icmp eq i8 %x, 126
|
|
|
|
%or = or i1 %cmp1, %cmp2
|
|
|
|
ret i1 %or
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @and_ne_with_one_bit_diff_constants3(i8 %x) {
|
|
|
|
; CHECK-LABEL: @and_ne_with_one_bit_diff_constants3(
|
2017-04-15 03:23:50 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or i8 %x, -128
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP1]], -63
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
2017-04-15 02:19:27 +08:00
|
|
|
;
|
|
|
|
%cmp1 = icmp ne i8 %x, 65
|
|
|
|
%cmp2 = icmp ne i8 %x, 193
|
|
|
|
%and = and i1 %cmp1, %cmp2
|
|
|
|
ret i1 %and
|
|
|
|
}
|
|
|
|
|
|
|
|
; Use an 'add' to eliminate an icmp if the constants are off-by-one (not off-by-one-bit).
|
|
|
|
; (X == 13 | X == 14) -> X-13 <u 2
|
|
|
|
|
|
|
|
define i1 @or_eq_with_diff_one(i8 %x) {
|
|
|
|
; CHECK-LABEL: @or_eq_with_diff_one(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i8 %x, -13
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], 2
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
|
|
|
;
|
|
|
|
%cmp1 = icmp eq i8 %x, 13
|
|
|
|
%cmp2 = icmp eq i8 %x, 14
|
|
|
|
%or = or i1 %cmp1, %cmp2
|
|
|
|
ret i1 %or
|
|
|
|
}
|
|
|
|
|
|
|
|
; (X != 40 | X != 39) -> X-39 >u 1
|
|
|
|
|
|
|
|
define i1 @and_ne_with_diff_one(i32 %x) {
|
|
|
|
; CHECK-LABEL: @and_ne_with_diff_one(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i32 %x, -39
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[TMP1]], 1
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
|
|
|
;
|
|
|
|
%cmp1 = icmp ne i32 %x, 40
|
|
|
|
%cmp2 = icmp ne i32 %x, 39
|
|
|
|
%and = and i1 %cmp1, %cmp2
|
|
|
|
ret i1 %and
|
|
|
|
}
|
|
|
|
|
|
|
|
; Make sure the constants are treated as signed when comparing them.
|
|
|
|
; PR32524: https://bugs.llvm.org/show_bug.cgi?id=32524
|
|
|
|
|
|
|
|
define i1 @or_eq_with_diff_one_signed(i32 %x) {
|
|
|
|
; CHECK-LABEL: @or_eq_with_diff_one_signed(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i32 %x, 1
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[TMP1]], 2
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
|
|
|
;
|
|
|
|
%cmp1 = icmp eq i32 %x, 0
|
|
|
|
%cmp2 = icmp eq i32 %x, -1
|
|
|
|
%or = or i1 %cmp1, %cmp2
|
|
|
|
ret i1 %or
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @and_ne_with_diff_one_signed(i64 %x) {
|
|
|
|
; CHECK-LABEL: @and_ne_with_diff_one_signed(
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i64 %x, 1
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP1]], 1
|
|
|
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
|
|
|
;
|
|
|
|
%cmp1 = icmp ne i64 %x, -1
|
|
|
|
%cmp2 = icmp ne i64 %x, 0
|
|
|
|
%and = and i1 %cmp1, %cmp2
|
|
|
|
ret i1 %and
|
|
|
|
}
|
|
|
|
|
2017-04-16 01:50:45 +08:00
|
|
|
; FIXME: Vectors with splat constants get the same folds.
|
|
|
|
|
|
|
|
define <2 x i1> @or_eq_with_one_bit_diff_constants2_splatvec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @or_eq_with_one_bit_diff_constants2_splatvec(
|
|
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq <2 x i32> %x, <i32 97, i32 97>
|
|
|
|
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq <2 x i32> %x, <i32 65, i32 65>
|
|
|
|
; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[CMP1]], [[CMP2]]
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[OR]]
|
|
|
|
;
|
|
|
|
%cmp1 = icmp eq <2 x i32> %x, <i32 97, i32 97>
|
|
|
|
%cmp2 = icmp eq <2 x i32> %x, <i32 65, i32 65>
|
|
|
|
%or = or <2 x i1> %cmp1, %cmp2
|
|
|
|
ret <2 x i1> %or
|
|
|
|
}
|
2017-04-15 02:19:27 +08:00
|
|
|
|
2017-04-16 01:50:45 +08:00
|
|
|
define <2 x i1> @and_ne_with_diff_one_splatvec(<2 x i32> %x) {
|
|
|
|
; CHECK-LABEL: @and_ne_with_diff_one_splatvec(
|
|
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> %x, <i32 40, i32 40>
|
|
|
|
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne <2 x i32> %x, <i32 39, i32 39>
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]]
|
|
|
|
; CHECK-NEXT: ret <2 x i1> [[AND]]
|
|
|
|
;
|
|
|
|
%cmp1 = icmp ne <2 x i32> %x, <i32 40, i32 40>
|
|
|
|
%cmp2 = icmp ne <2 x i32> %x, <i32 39, i32 39>
|
|
|
|
%and = and <2 x i1> %cmp1, %cmp2
|
|
|
|
ret <2 x i1> %and
|
|
|
|
}
|
2017-04-15 02:19:27 +08:00
|
|
|
|