forked from OSchip/llvm-project
[InstCombine] fold icmp with 'mul nsw/nuw' and constant operands
This also removes a more specific fold that only handled icmp with 0. https://rise4fun.com/Alive/sdM9 Name: mul nsw with icmp eq Pre: (C1 != 0) && (C2 % C1) == 0 %a = mul nsw i8 %x, C1 %r = icmp eq i8 %a, C2 => %r = icmp eq i8 %x, C2 / C1 Name: mul nuw with icmp eq Pre: (C1 != 0) && (C2 %u C1) == 0 %a = mul nuw i8 %x, C1 %r = icmp eq i8 %a, C2 => %r = icmp eq i8 %x, C2 /u C1 Name: mul nsw with icmp ne Pre: (C1 != 0) && (C2 % C1) == 0 %a = mul nsw i8 %x, C1 %r = icmp ne i8 %a, C2 => %r = icmp ne i8 %x, C2 / C1 Name: mul nuw with icmp ne Pre: (C1 != 0) && (C2 %u C1) == 0 %a = mul nuw i8 %x, C1 %r = icmp ne i8 %a, C2 => %r = icmp ne i8 %x, C2 /u C1
This commit is contained in:
parent
0315571a19
commit
c66169136f
|
@ -1981,6 +1981,21 @@ Instruction *InstCombinerImpl::foldICmpMulConstant(ICmpInst &Cmp,
|
|||
Constant::getNullValue(Mul->getType()));
|
||||
}
|
||||
|
||||
// If the multiply does not wrap, try to divide the compare constant by the
|
||||
// multiplication factor.
|
||||
if (Cmp.isEquality() && !MulC->isNullValue()) {
|
||||
// (mul nsw X, MulC) == C --> X == C /s MulC
|
||||
if (Mul->hasNoSignedWrap() && C.srem(*MulC).isNullValue()) {
|
||||
Constant *NewC = ConstantInt::get(Mul->getType(), C.sdiv(*MulC));
|
||||
return new ICmpInst(Pred, Mul->getOperand(0), NewC);
|
||||
}
|
||||
// (mul nuw X, MulC) == C --> X == C /u MulC
|
||||
if (Mul->hasNoUnsignedWrap() && C.urem(*MulC).isNullValue()) {
|
||||
Constant *NewC = ConstantInt::get(Mul->getType(), C.udiv(*MulC));
|
||||
return new ICmpInst(Pred, Mul->getOperand(0), NewC);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -3051,17 +3066,6 @@ Instruction *InstCombinerImpl::foldICmpBinOpEqualityWithConstant(
|
|||
}
|
||||
break;
|
||||
}
|
||||
case Instruction::Mul:
|
||||
if (C.isNullValue() && BO->hasNoSignedWrap()) {
|
||||
const APInt *BOC;
|
||||
if (match(BOp1, m_APInt(BOC)) && !BOC->isNullValue()) {
|
||||
// The trivial case (mul X, 0) is handled by InstSimplify.
|
||||
// General case : (mul X, C) != 0 iff X != 0
|
||||
// (mul X, C) == 0 iff X == 0
|
||||
return new ICmpInst(Pred, BOp0, Constant::getNullValue(RHS->getType()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Instruction::UDiv:
|
||||
if (C.isNullValue()) {
|
||||
// (icmp eq/ne (udiv A, B), 0) -> (icmp ugt/ule i32 B, A)
|
||||
|
|
|
@ -121,8 +121,7 @@ define i1 @ugt_rem_nz(i8 %x) {
|
|||
|
||||
define i1 @eq_nsw_rem_zero(i8 %x) {
|
||||
; CHECK-LABEL: @eq_nsw_rem_zero(
|
||||
; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], -5
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp eq i8 [[A]], 20
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp eq i8 [[X:%.*]], -4
|
||||
; CHECK-NEXT: ret i1 [[B]]
|
||||
;
|
||||
%a = mul nsw i8 %x, -5
|
||||
|
@ -132,8 +131,7 @@ define i1 @eq_nsw_rem_zero(i8 %x) {
|
|||
|
||||
define <2 x i1> @ne_nsw_rem_zero(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @ne_nsw_rem_zero(
|
||||
; CHECK-NEXT: [[A:%.*]] = mul nsw <2 x i8> [[X:%.*]], <i8 5, i8 5>
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp ne <2 x i8> [[A]], <i8 -30, i8 -30>
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp ne <2 x i8> [[X:%.*]], <i8 -6, i8 -6>
|
||||
; CHECK-NEXT: ret <2 x i1> [[B]]
|
||||
;
|
||||
%a = mul nsw <2 x i8> %x, <i8 5, i8 5>
|
||||
|
@ -141,6 +139,8 @@ define <2 x i1> @ne_nsw_rem_zero(<2 x i8> %x) {
|
|||
ret <2 x i1> %b
|
||||
}
|
||||
|
||||
; TODO: Missed fold with undef.
|
||||
|
||||
define <2 x i1> @ne_nsw_rem_zero_undef1(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @ne_nsw_rem_zero_undef1(
|
||||
; CHECK-NEXT: [[A:%.*]] = mul nsw <2 x i8> [[X:%.*]], <i8 5, i8 undef>
|
||||
|
@ -152,6 +152,8 @@ define <2 x i1> @ne_nsw_rem_zero_undef1(<2 x i8> %x) {
|
|||
ret <2 x i1> %b
|
||||
}
|
||||
|
||||
; TODO: Missed fold with undef.
|
||||
|
||||
define <2 x i1> @ne_nsw_rem_zero_undef2(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @ne_nsw_rem_zero_undef2(
|
||||
; CHECK-NEXT: [[A:%.*]] = mul nsw <2 x i8> [[X:%.*]], <i8 5, i8 5>
|
||||
|
@ -167,7 +169,7 @@ define i1 @eq_nsw_rem_zero_uses(i8 %x) {
|
|||
; CHECK-LABEL: @eq_nsw_rem_zero_uses(
|
||||
; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], -5
|
||||
; CHECK-NEXT: call void @use(i8 [[A]])
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp eq i8 [[A]], 20
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp eq i8 [[X]], -4
|
||||
; CHECK-NEXT: ret i1 [[B]]
|
||||
;
|
||||
%a = mul nsw i8 %x, -5
|
||||
|
@ -200,8 +202,7 @@ define i1 @ne_nsw_rem_nz(i8 %x) {
|
|||
|
||||
define <2 x i1> @eq_nuw_rem_zero(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @eq_nuw_rem_zero(
|
||||
; CHECK-NEXT: [[A:%.*]] = mul nuw <2 x i8> [[X:%.*]], <i8 5, i8 5>
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i8> [[A]], <i8 20, i8 20>
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i8> [[X:%.*]], <i8 4, i8 4>
|
||||
; CHECK-NEXT: ret <2 x i1> [[B]]
|
||||
;
|
||||
%a = mul nuw <2 x i8> %x, <i8 5, i8 5>
|
||||
|
@ -209,6 +210,8 @@ define <2 x i1> @eq_nuw_rem_zero(<2 x i8> %x) {
|
|||
ret <2 x i1> %b
|
||||
}
|
||||
|
||||
; TODO: Missed fold with undef.
|
||||
|
||||
define <2 x i1> @eq_nuw_rem_zero_undef1(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @eq_nuw_rem_zero_undef1(
|
||||
; CHECK-NEXT: [[A:%.*]] = mul nuw <2 x i8> [[X:%.*]], <i8 undef, i8 5>
|
||||
|
@ -220,6 +223,8 @@ define <2 x i1> @eq_nuw_rem_zero_undef1(<2 x i8> %x) {
|
|||
ret <2 x i1> %b
|
||||
}
|
||||
|
||||
; TODO: Missed fold with undef.
|
||||
|
||||
define <2 x i1> @eq_nuw_rem_zero_undef2(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @eq_nuw_rem_zero_undef2(
|
||||
; CHECK-NEXT: [[A:%.*]] = mul nuw <2 x i8> [[X:%.*]], <i8 5, i8 5>
|
||||
|
@ -233,8 +238,7 @@ define <2 x i1> @eq_nuw_rem_zero_undef2(<2 x i8> %x) {
|
|||
|
||||
define i1 @ne_nuw_rem_zero(i8 %x) {
|
||||
; CHECK-LABEL: @ne_nuw_rem_zero(
|
||||
; CHECK-NEXT: [[A:%.*]] = mul nuw i8 [[X:%.*]], 5
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp ne i8 [[A]], -126
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp ne i8 [[X:%.*]], 26
|
||||
; CHECK-NEXT: ret i1 [[B]]
|
||||
;
|
||||
%a = mul nuw i8 %x, 5
|
||||
|
@ -246,7 +250,7 @@ define i1 @ne_nuw_rem_zero_uses(i8 %x) {
|
|||
; CHECK-LABEL: @ne_nuw_rem_zero_uses(
|
||||
; CHECK-NEXT: [[A:%.*]] = mul nuw i8 [[X:%.*]], 5
|
||||
; CHECK-NEXT: call void @use(i8 [[A]])
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp ne i8 [[A]], -126
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp ne i8 [[X]], 26
|
||||
; CHECK-NEXT: ret i1 [[B]]
|
||||
;
|
||||
%a = mul nuw i8 %x, 5
|
||||
|
|
Loading…
Reference in New Issue