diff options
author | Sanjay Patel <spatel@rotateright.com> | 2017-09-10 17:55:08 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2017-09-10 17:55:08 +0000 |
commit | 5876189ff1161169b4767beec337a3cfa2d7ca4e (patch) | |
tree | 9038e44dcca773eef28d59daf648ce0d073459b0 /llvm/lib/Analysis | |
parent | 9a95e1afd0e0e5c59aaa8db124124c8a954cff2d (diff) | |
download | bcm5719-llvm-5876189ff1161169b4767beec337a3cfa2d7ca4e.tar.gz bcm5719-llvm-5876189ff1161169b4767beec337a3cfa2d7ca4e.zip |
[InstSimplify] refactor udiv/urem code and add tests; NFCI
This removes some duplicated code and makes it easier to support signed div/rem
in a similar way if we want to do that. Note that the existing comments were not
accurate - we don't need a constant divisor to simplify; icmp simplification does
more than that. But as the added tests show, it could go even further.
llvm-svn: 312885
Diffstat (limited to 'llvm/lib/Analysis')
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 0fb0b7d2449..dbcc7e13f21 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -1075,6 +1075,33 @@ Value *llvm::SimplifySDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) { return ::SimplifySDivInst(Op0, Op1, Q, RecursionLimit); } +/// 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; + + return nullptr; +} + /// Given operands for a UDiv, see if we can fold the result. /// If not, this returns null. static Value *SimplifyUDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, @@ -1082,15 +1109,8 @@ static Value *SimplifyUDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, if (Value *V = SimplifyDiv(Instruction::UDiv, Op0, Op1, Q, MaxRecurse)) return V; - // udiv %V, C -> 0 if %V < C - if (MaxRecurse) { - if (Constant *C = dyn_cast_or_null<Constant>(SimplifyICmpInst( - ICmpInst::ICMP_ULT, Op0, Op1, Q, MaxRecurse - 1))) { - if (C->isAllOnesValue()) { - return Constant::getNullValue(Op0->getType()); - } - } - } + if (Value *V = simplifyUnsignedDivRem(Op0, Op1, Q, MaxRecurse, true)) + return V; return nullptr; } @@ -1198,15 +1218,8 @@ static Value *SimplifyURemInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, if (Value *V = SimplifyRem(Instruction::URem, Op0, Op1, Q, MaxRecurse)) return V; - // urem %V, C -> %V if %V < C - if (MaxRecurse) { - if (Constant *C = dyn_cast_or_null<Constant>(SimplifyICmpInst( - ICmpInst::ICMP_ULT, Op0, Op1, Q, MaxRecurse - 1))) { - if (C->isAllOnesValue()) { - return Op0; - } - } - } + if (Value *V = simplifyUnsignedDivRem(Op0, Op1, Q, MaxRecurse, false)) + return V; return nullptr; } |