summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorAlexandre Isoard <alexandre.isoard@gmail.com>2017-09-01 14:59:59 +0000
committerAlexandre Isoard <alexandre.isoard@gmail.com>2017-09-01 14:59:59 +0000
commit405728fd47a555e51196a6883d33318f22fab9a4 (patch)
tree0aa242b490a05acf28737503cd6324006e5b3951 /llvm/lib
parent65528f29913a541f3d250dbee2d93a3b1db68e4d (diff)
downloadbcm5719-llvm-405728fd47a555e51196a6883d33318f22fab9a4.tar.gz
bcm5719-llvm-405728fd47a555e51196a6883d33318f22fab9a4.zip
[SCEV] Add URem support to SCEV
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 using that relation: %r --> (-%b * (%t /u %b)) + %t We implement two special cases: - if %b is 1, the result is always 0 - if %b is a power-of-two, we produce a zext/trunc based expression instead That is, the following code: %r = urem i32 %t, 65536 Produces: %r --> (zext i16 (trunc i32 %a to i16) to i32) Note that while this helps get a tighter bound on the range analysis and the known-bits analysis, this exposes some normalization shortcoming of SCEVs: %div = udim i32 %a, 65536 %mul = mul i32 %div, 65536 %rem = urem i32 %a, 65536 %add = add i32 %mul, %rem Will usually not be reduced. llvm-svn: 312329
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/ScalarEvolution.cpp31
1 files changed, 31 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 25decab88ed..e3bd30a9e3c 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -2981,6 +2981,34 @@ 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!");
+
+ // Short-circuit easy cases
+ if (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS)) {
+ // If constant is one, the result is trivial
+ if (RHSC->getValue()->isOne())
+ return getZero(LHS->getType()); // X urem 1 --> 0
+
+ // If constant is a power of two, fold into a zext(trunc(LHS)).
+ if (RHSC->getAPInt().isPowerOf2()) {
+ Type *FullTy = LHS->getType();
+ Type *TruncTy =
+ IntegerType::get(getContext(), RHSC->getAPInt().logBase2());
+ return getZeroExtendExpr(getTruncateExpr(LHS, TruncTy), FullTy);
+ }
+ }
+
+ // Fallback to %a == %x urem %y == %x -<nuw> ((%x udiv %y) *<nuw> %y)
+ 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,
@@ -4144,6 +4172,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:
@@ -5782,6 +5811,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