[llvm] r313261 - [InstSimplify] clean up div/rem handling; NFCI
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 14 07:09:11 PDT 2017
Author: spatel
Date: Thu Sep 14 07:09:11 2017
New Revision: 313261
URL: http://llvm.org/viewvc/llvm-project?rev=313261&view=rev
Log:
[InstSimplify] clean up div/rem handling; NFCI
The idea to make an 'isDivZero' helper was suggested for the signed case in D37713:
https://reviews.llvm.org/D37713
This clean-up makes it clear that D37713 is just filling the gap for signed div/rem,
removes unnecessary code, and allows us to remove a bit of duplicated code from the
planned improvement in D37713.
Modified:
llvm/trunk/lib/Analysis/InstructionSimplify.cpp
Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=313261&r1=313260&r2=313261&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Thu Sep 14 07:09:11 2017
@@ -905,6 +905,34 @@ static Value *simplifyDivRem(Value *Op0,
return nullptr;
}
+/// Given a predicate and two operands, return true if the comparison is true.
+/// This is a helper for div/rem simplification where we return some other value
+/// when we can prove a relationship between the operands.
+static bool isICmpTrue(ICmpInst::Predicate Pred, Value *LHS, Value *RHS,
+ const SimplifyQuery &Q, unsigned MaxRecurse) {
+ Value *V = SimplifyICmpInst(Pred, LHS, RHS, Q, MaxRecurse);
+ Constant *C = dyn_cast_or_null<Constant>(V);
+ return (C && C->isAllOnesValue());
+}
+
+/// Return true if we can simplify X / Y to 0. Remainder can adapt that answer
+/// to simplify X % Y to X.
+static bool isDivZero(Value *Op0, Value *Op1, const SimplifyQuery &Q,
+ unsigned MaxRecurse, bool IsSigned) {
+ // Recursion is always used, so bail out at once if we already hit the limit.
+ if (!MaxRecurse--)
+ return false;
+
+ if (IsSigned) {
+ // TODO: Handle signed.
+ return false;
+ }
+
+ // IsSigned == false.
+ // Is the quotient unsigned less than the divisor?
+ return isICmpTrue(ICmpInst::ICMP_ULT, Op0, Op1, Q, MaxRecurse);
+}
+
/// These are simplifications common to SDiv and UDiv.
static Value *simplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
const SimplifyQuery &Q, unsigned MaxRecurse) {
@@ -914,7 +942,7 @@ static Value *simplifyDiv(Instruction::B
if (Value *V = simplifyDivRem(Op0, Op1, true))
return V;
- bool isSigned = Opcode == Instruction::SDiv;
+ bool IsSigned = Opcode == Instruction::SDiv;
// (X * Y) / Y -> X if the multiplication does not overflow.
Value *X = nullptr, *Y = nullptr;
@@ -922,8 +950,8 @@ static Value *simplifyDiv(Instruction::B
if (Y != Op1) std::swap(X, Y); // Ensure expression is (X * Y) / Y, Y = Op1
OverflowingBinaryOperator *Mul = cast<OverflowingBinaryOperator>(Op0);
// If the Mul knows it does not overflow, then we are good to go.
- if ((isSigned && Mul->hasNoSignedWrap()) ||
- (!isSigned && Mul->hasNoUnsignedWrap()))
+ if ((IsSigned && Mul->hasNoSignedWrap()) ||
+ (!IsSigned && Mul->hasNoUnsignedWrap()))
return X;
// If X has the form X = A / Y then X * Y cannot overflow.
if (BinaryOperator *Div = dyn_cast<BinaryOperator>(X))
@@ -932,13 +960,13 @@ static Value *simplifyDiv(Instruction::B
}
// (X rem Y) / Y -> 0
- if ((isSigned && match(Op0, m_SRem(m_Value(), m_Specific(Op1)))) ||
- (!isSigned && match(Op0, m_URem(m_Value(), m_Specific(Op1)))))
+ if ((IsSigned && match(Op0, m_SRem(m_Value(), m_Specific(Op1)))) ||
+ (!IsSigned && match(Op0, m_URem(m_Value(), m_Specific(Op1)))))
return Constant::getNullValue(Op0->getType());
// (X /u C1) /u C2 -> 0 if C1 * C2 overflow
ConstantInt *C1, *C2;
- if (!isSigned && match(Op0, m_UDiv(m_Value(X), m_ConstantInt(C1))) &&
+ if (!IsSigned && match(Op0, m_UDiv(m_Value(X), m_ConstantInt(C1))) &&
match(Op1, m_ConstantInt(C2))) {
bool Overflow;
(void)C1->getValue().umul_ov(C2->getValue(), Overflow);
@@ -958,6 +986,9 @@ static Value *simplifyDiv(Instruction::B
if (Value *V = ThreadBinOpOverPHI(Opcode, Op0, Op1, Q, MaxRecurse))
return V;
+ if (isDivZero(Op0, Op1, Q, MaxRecurse, IsSigned))
+ return Constant::getNullValue(Op0->getType());
+
return nullptr;
}
@@ -989,32 +1020,9 @@ static Value *simplifyRem(Instruction::B
if (Value *V = ThreadBinOpOverPHI(Opcode, Op0, Op1, Q, MaxRecurse))
return V;
- return nullptr;
-}
-
-/// Given a predicate and two operands, return true if the comparison is true.
-/// This is a helper for div/rem simplification where we return some other value
-/// when we can prove a relationship between the operands.
-static bool isICmpTrue(ICmpInst::Predicate Pred, Value *LHS, Value *RHS,
- const SimplifyQuery &Q, unsigned MaxRecurse) {
- Value *V = SimplifyICmpInst(Pred, LHS, RHS, Q, MaxRecurse);
- Constant *C = dyn_cast_or_null<Constant>(V);
- return (C && C->isAllOnesValue());
-}
-
-static Value *simplifyUnsignedDivRem(Value *Op0, Value *Op1,
- const SimplifyQuery &Q,
- unsigned MaxRecurse, bool IsDiv) {
- // Recursion is always used, so bail out at once if we already hit the limit.
- if (!MaxRecurse--)
- return nullptr;
-
- // If we can prove that the quotient is unsigned less than the divisor, then
- // we know the answer:
- // X / Y --> 0
- // X % Y --> X
- if (isICmpTrue(ICmpInst::ICMP_ULT, Op0, Op1, Q, MaxRecurse))
- return IsDiv ? Constant::getNullValue(Op0->getType()) : Op0;
+ // If X / Y == 0, then X % Y == X.
+ if (isDivZero(Op0, Op1, Q, MaxRecurse, Opcode == Instruction::SRem))
+ return Op0;
return nullptr;
}
@@ -1023,10 +1031,7 @@ static Value *simplifyUnsignedDivRem(Val
/// If not, this returns null.
static Value *SimplifySDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
unsigned MaxRecurse) {
- if (Value *V = simplifyDiv(Instruction::SDiv, Op0, Op1, Q, MaxRecurse))
- return V;
-
- return nullptr;
+ return simplifyDiv(Instruction::SDiv, Op0, Op1, Q, MaxRecurse);
}
Value *llvm::SimplifySDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
@@ -1037,13 +1042,7 @@ Value *llvm::SimplifySDivInst(Value *Op0
/// If not, this returns null.
static Value *SimplifyUDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
unsigned MaxRecurse) {
- if (Value *V = simplifyDiv(Instruction::UDiv, Op0, Op1, Q, MaxRecurse))
- return V;
-
- if (Value *V = simplifyUnsignedDivRem(Op0, Op1, Q, MaxRecurse, true))
- return V;
-
- return nullptr;
+ return simplifyDiv(Instruction::UDiv, Op0, Op1, Q, MaxRecurse);
}
Value *llvm::SimplifyUDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
@@ -1054,10 +1053,7 @@ Value *llvm::SimplifyUDivInst(Value *Op0
/// If not, this returns null.
static Value *SimplifySRemInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
unsigned MaxRecurse) {
- if (Value *V = simplifyRem(Instruction::SRem, Op0, Op1, Q, MaxRecurse))
- return V;
-
- return nullptr;
+ return simplifyRem(Instruction::SRem, Op0, Op1, Q, MaxRecurse);
}
Value *llvm::SimplifySRemInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
@@ -1068,13 +1064,7 @@ Value *llvm::SimplifySRemInst(Value *Op0
/// If not, this returns null.
static Value *SimplifyURemInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
unsigned MaxRecurse) {
- if (Value *V = simplifyRem(Instruction::URem, Op0, Op1, Q, MaxRecurse))
- return V;
-
- if (Value *V = simplifyUnsignedDivRem(Op0, Op1, Q, MaxRecurse, false))
- return V;
-
- return nullptr;
+ return simplifyRem(Instruction::URem, Op0, Op1, Q, MaxRecurse);
}
Value *llvm::SimplifyURemInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
More information about the llvm-commits
mailing list