1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[InstSimplify] fold icmp with mul nsw and constant operands

https://rise4fun.com/Alive/slvl

  Name: mul nsw with icmp eq
  Pre: (C2 % C1) != 0
  %a = mul nsw i8 %x, C1
  %r = icmp eq i8 %a, C2
    =>
  %r = false

  Name: mul nsw with icmp ne
  Pre: (C2 % C1) != 0
  %a = mul nsw i8 %x, C1
  %r = icmp ne i8 %a, C2
    =>
  %r = true

Follow-up to the 'nuw' variation added with:
rGf879c9b79621
This commit is contained in:
Sanjay Patel 2020-08-05 14:37:05 -04:00
parent 60815c576a
commit 82aa9a6b56
3 changed files with 114 additions and 7 deletions

View File

@ -2750,12 +2750,14 @@ static Value *simplifyICmpWithConstant(CmpInst::Predicate Pred, Value *LHS,
return ConstantInt::getFalse(ITy);
}
// (mul nuw X, MulC) != C --> true (if C is not a multiple of MulC)
// (mul nuw X, MulC) == C --> false (if C is not a multiple of MulC)
// (mul nuw/nsw X, MulC) != C --> true (if C is not a multiple of MulC)
// (mul nuw/nsw X, MulC) == C --> false (if C is not a multiple of MulC)
const APInt *MulC;
if (ICmpInst::isEquality(Pred) &&
match(LHS, m_NUWMul(m_Value(), m_APIntAllowUndef(MulC))) &&
C->urem(*MulC) != 0)
((match(LHS, m_NUWMul(m_Value(), m_APIntAllowUndef(MulC))) &&
C->urem(*MulC) != 0) ||
(match(LHS, m_NSWMul(m_Value(), m_APIntAllowUndef(MulC))) &&
C->srem(*MulC) != 0)))
return ConstantInt::get(ITy, Pred == ICmpInst::ICMP_NE);
return nullptr;

View File

@ -194,9 +194,7 @@ define i1 @ugt_rem_zero_nonuw(i8 %x) {
define i1 @sgt_minnum(i8 %x) {
; CHECK-LABEL: @sgt_minnum(
; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], 7
; CHECK-NEXT: [[B:%.*]] = icmp ne i8 [[A]], -128
; CHECK-NEXT: ret i1 [[B]]
; CHECK-NEXT: ret i1 true
;
%a = mul nsw i8 %x, 7
%b = icmp sgt i8 %a, -128

View File

@ -916,3 +916,110 @@ define i1 @mul_nuw_urem_cmp_neg_constant_is_0(i8 %x) {
%r = icmp eq i8 %m, -127
ret i1 %r
}
; No overflow, so mul constant must be a factor of cmp constant.
define i1 @mul_nsw_srem_cmp_constant1(i8 %x) {
; CHECK-LABEL: @mul_nsw_srem_cmp_constant1(
; CHECK-NEXT: ret i1 false
;
%m = mul nsw i8 %x, 43
%r = icmp eq i8 %m, 45
ret i1 %r
}
; Invert predicate and check vector type.
define <2 x i1> @mul_nsw_srem_cmp_constant_vec_splat(<2 x i8> %x) {
; CHECK-LABEL: @mul_nsw_srem_cmp_constant_vec_splat(
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%m = mul nsw <2 x i8> %x, <i8 45, i8 45>
%r = icmp ne <2 x i8> %m, <i8 15, i8 15>
ret <2 x i1> %r
}
; Undefs in vector constants are ok.
define <2 x i1> @mul_nsw_srem_cmp_constant_vec_splat_undef1(<2 x i8> %x) {
; CHECK-LABEL: @mul_nsw_srem_cmp_constant_vec_splat_undef1(
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%m = mul nsw <2 x i8> %x, <i8 45, i8 45>
%r = icmp ne <2 x i8> %m, <i8 15, i8 undef>
ret <2 x i1> %r
}
; Undefs in vector constants are ok.
define <2 x i1> @mul_nsw_srem_cmp_constant_vec_splat_undef2(<2 x i8> %x) {
; CHECK-LABEL: @mul_nsw_srem_cmp_constant_vec_splat_undef2(
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%m = mul nsw <2 x i8> %x, <i8 undef, i8 45>
%r = icmp ne <2 x i8> %m, <i8 15, i8 15>
ret <2 x i1> %r
}
; Check negative numbers (constants should be analyzed as signed).
define i1 @mul_nsw_srem_cmp_constant2(i8 %x) {
; CHECK-LABEL: @mul_nsw_srem_cmp_constant2(
; CHECK-NEXT: ret i1 false
;
%m = mul nsw i8 %x, 43
%r = icmp eq i8 %m, -127
ret i1 %r
}
; Negative test - require nsw.
define i1 @mul_srem_cmp_constant1(i8 %x) {
; CHECK-LABEL: @mul_srem_cmp_constant1(
; CHECK-NEXT: [[M:%.*]] = mul i8 [[X:%.*]], 43
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 42
; CHECK-NEXT: ret i1 [[R]]
;
%m = mul i8 %x, 43
%r = icmp eq i8 %m, 42
ret i1 %r
}
; Negative test - x could be 0.
define i1 @mul_nsw_srem_cmp_constant0(i8 %x) {
; CHECK-LABEL: @mul_nsw_srem_cmp_constant0(
; CHECK-NEXT: [[M:%.*]] = mul nsw i8 [[X:%.*]], 23
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%m = mul nsw i8 %x, 23
%r = icmp eq i8 %m, 0
ret i1 %r
}
; Negative test - cmp constant is multiple of mul constant.
define i1 @mul_nsw_srem_cmp_constant_is_0(i8 %x) {
; CHECK-LABEL: @mul_nsw_srem_cmp_constant_is_0(
; CHECK-NEXT: [[M:%.*]] = mul nsw i8 [[X:%.*]], 42
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 84
; CHECK-NEXT: ret i1 [[R]]
;
%m = mul nsw i8 %x, 42
%r = icmp eq i8 %m, 84
ret i1 %r
}
; Negative test - cmp constant is multiple (treated as signed).
define i1 @mul_nsw_srem_cmp_neg_constant_is_0(i8 %x) {
; CHECK-LABEL: @mul_nsw_srem_cmp_neg_constant_is_0(
; CHECK-NEXT: [[M:%.*]] = mul nsw i8 [[X:%.*]], -42
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], -84
; CHECK-NEXT: ret i1 [[R]]
;
%m = mul nsw i8 %x, -42
%r = icmp eq i8 %m, -84
ret i1 %r
}