[llvm] c661691 - [InstCombine] fold icmp with 'mul nsw/nuw' and constant operands
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 5 14:30:40 PDT 2020
Author: Sanjay Patel
Date: 2020-08-05T17:29:32-04:00
New Revision: c66169136fe667d653ff40ba4bd9f6047702e93c
URL: https://github.com/llvm/llvm-project/commit/c66169136fe667d653ff40ba4bd9f6047702e93c
DIFF: https://github.com/llvm/llvm-project/commit/c66169136fe667d653ff40ba4bd9f6047702e93c.diff
LOG: [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
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/icmp-mul.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index ca2bcb9bc415..7aa3126e1754 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -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)
diff --git a/llvm/test/Transforms/InstCombine/icmp-mul.ll b/llvm/test/Transforms/InstCombine/icmp-mul.ll
index 45c50c325b96..8e7d9056726e 100644
--- a/llvm/test/Transforms/InstCombine/icmp-mul.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-mul.ll
@@ -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
More information about the llvm-commits
mailing list