summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorAlexandre Isoard <alexandre.isoard@gmail.com>2017-06-29 16:29:04 +0000
committerAlexandre Isoard <alexandre.isoard@gmail.com>2017-06-29 16:29:04 +0000
commitaa29afc75600c659e9eef0f124b7fa74fd8006cb (patch)
tree9c9c43296812661cad7b1a50efd682e085465895 /llvm/lib
parent39b88f01a53cc561c0002361eb77b1a4d0d35bfd (diff)
downloadbcm5719-llvm-aa29afc75600c659e9eef0f124b7fa74fd8006cb.tar.gz
bcm5719-llvm-aa29afc75600c659e9eef0f124b7fa74fd8006cb.zip
ScalarEvolution: Add URem support
In LLVM IR the following code: %r = urem <ty> %t, %b is equivalent to: %q = udiv <ty> %t, %b %s = mul <ty> nuw %q, %b %r = sub <ty> nuw %t, %q ; (t / b) * b + (t % b) = t As UDiv, Mul and Sub are already supported by SCEV, URem can be implemented with minimal effort this way. Note: While SRem and SDiv are also related this way, SCEV does not provides SDiv yet. llvm-svn: 306695
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/ScalarEvolution.cpp26
1 files changed, 26 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 73a95ec405c..80bbc8b05e2 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -2935,6 +2935,29 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
return getOrCreateMulExpr(Ops, Flags);
}
+/// Represents an unsigned remainder expression based on unsigned division.
+const SCEV *ScalarEvolution::getURemExpr(const SCEV *LHS,
+ const SCEV *RHS) {
+ assert(getEffectiveSCEVType(LHS->getType()) ==
+ getEffectiveSCEVType(RHS->getType()) &&
+ "SCEVURemExpr operand types don't match!");
+
+ // TODO:
+ // - short circuit '%a = %x urem %x --> 0' (why is it not done for udiv?)
+ // - short circuit '%a = %x urem 0 --> %a' (same as for udiv)
+ // - update upper-bound and lower-bound cache for the final result
+ // (or improve how subtraction is estimated)
+
+ // Short-circuit easy cases
+ if (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS))
+ if (RHSC->getValue()->equalsInt(1))
+ return getZero(LHS->getType()); // X urem 1 --> 0
+
+ const SCEV *UDiv = getUDivExpr(LHS, RHS);
+ const SCEV *Mult = getMulExpr(UDiv, RHS, SCEV::FlagNUW);
+ return getMinusSCEV(LHS, Mult, SCEV::FlagNUW);
+}
+
/// Get a canonical unsigned division expression, or something simpler if
/// possible.
const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
@@ -4095,6 +4118,7 @@ static Optional<BinaryOp> MatchBinaryOp(Value *V, DominatorTree &DT) {
case Instruction::Sub:
case Instruction::Mul:
case Instruction::UDiv:
+ case Instruction::URem:
case Instruction::And:
case Instruction::Or:
case Instruction::AShr:
@@ -5416,6 +5440,8 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
}
case Instruction::UDiv:
return getUDivExpr(getSCEV(BO->LHS), getSCEV(BO->RHS));
+ case Instruction::URem:
+ return getURemExpr(getSCEV(BO->LHS), getSCEV(BO->RHS));
case Instruction::Sub: {
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap;
if (BO->Op)
OpenPOWER on IntegriCloud