summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Analysis
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2017-09-10 17:55:08 +0000
committerSanjay Patel <spatel@rotateright.com>2017-09-10 17:55:08 +0000
commit5876189ff1161169b4767beec337a3cfa2d7ca4e (patch)
tree9038e44dcca773eef28d59daf648ce0d073459b0 /llvm/lib/Analysis
parent9a95e1afd0e0e5c59aaa8db124124c8a954cff2d (diff)
downloadbcm5719-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.cpp49
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;
}
OpenPOWER on IntegriCloud