[llvm-commits] [llvm] r60407 - in /llvm/trunk: include/llvm/Analysis/ScalarEvolution.h include/llvm/Analysis/ScalarEvolutionExpander.h include/llvm/Analysis/ScalarEvolutionExpressions.h lib/Analysis/ScalarEvolution.cpp lib/Analysis/ScalarEvolutionExpander.cpp
Nick Lewycky
nicholas at mxc.ca
Tue Dec 2 00:05:49 PST 2008
Author: nicholas
Date: Tue Dec 2 02:05:48 2008
New Revision: 60407
URL: http://llvm.org/viewvc/llvm-project?rev=60407&view=rev
Log:
Add a new SCEV representing signed division.
Modified:
llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h
llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h
llvm/trunk/lib/Analysis/ScalarEvolution.cpp
llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=60407&r1=60406&r2=60407&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Tue Dec 2 02:05:48 2008
@@ -225,6 +225,7 @@
return getMulExpr(Ops);
}
SCEVHandle getUDivExpr(const SCEVHandle &LHS, const SCEVHandle &RHS);
+ SCEVHandle getSDivExpr(const SCEVHandle &LHS, const SCEVHandle &RHS);
SCEVHandle getAddRecExpr(const SCEVHandle &Start, const SCEVHandle &Step,
const Loop *L);
SCEVHandle getAddRecExpr(std::vector<SCEVHandle> &Operands,
Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h?rev=60407&r1=60406&r2=60407&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h Tue Dec 2 02:05:48 2008
@@ -104,6 +104,8 @@
Value *visitUDivExpr(SCEVUDivExpr *S);
+ Value *visitSDivExpr(SCEVSDivExpr *S);
+
Value *visitAddRecExpr(SCEVAddRecExpr *S);
Value *visitSMaxExpr(SCEVSMaxExpr *S);
Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h?rev=60407&r1=60406&r2=60407&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h Tue Dec 2 02:05:48 2008
@@ -25,7 +25,7 @@
// These should be ordered in terms of increasing complexity to make the
// folders simpler.
scConstant, scTruncate, scZeroExtend, scSignExtend, scAddExpr, scMulExpr,
- scUDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr, scUnknown,
+ scUDivExpr, scSDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr, scUnknown,
scCouldNotCompute
};
@@ -358,6 +358,55 @@
//===--------------------------------------------------------------------===//
+ /// SCEVSDivExpr - This class represents a binary signed division operation.
+ ///
+ class SCEVSDivExpr : public SCEV {
+ friend class ScalarEvolution;
+
+ SCEVHandle LHS, RHS;
+ SCEVSDivExpr(const SCEVHandle &lhs, const SCEVHandle &rhs)
+ : SCEV(scSDivExpr), LHS(lhs), RHS(rhs) {}
+
+ virtual ~SCEVSDivExpr();
+ public:
+ const SCEVHandle &getLHS() const { return LHS; }
+ const SCEVHandle &getRHS() const { return RHS; }
+
+ virtual bool isLoopInvariant(const Loop *L) const {
+ return LHS->isLoopInvariant(L) && RHS->isLoopInvariant(L);
+ }
+
+ virtual bool hasComputableLoopEvolution(const Loop *L) const {
+ return LHS->hasComputableLoopEvolution(L) &&
+ RHS->hasComputableLoopEvolution(L);
+ }
+
+ SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const {
+ SCEVHandle L = LHS->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
+ SCEVHandle R = RHS->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
+ if (L == LHS && R == RHS)
+ return this;
+ else
+ return SE.getSDivExpr(L, R);
+ }
+
+
+ virtual const Type *getType() const;
+
+ void print(std::ostream &OS) const;
+ void print(std::ostream *OS) const { if (OS) print(*OS); }
+
+ /// Methods for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const SCEVSDivExpr *S) { return true; }
+ static inline bool classof(const SCEV *S) {
+ return S->getSCEVType() == scSDivExpr;
+ }
+ };
+
+
+ //===--------------------------------------------------------------------===//
/// SCEVAddRecExpr - This node represents a polynomial recurrence on the trip
/// count of the specified loop.
///
@@ -550,6 +599,8 @@
return ((SC*)this)->visitMulExpr((SCEVMulExpr*)S);
case scUDivExpr:
return ((SC*)this)->visitUDivExpr((SCEVUDivExpr*)S);
+ case scSDivExpr:
+ return ((SC*)this)->visitSDivExpr((SCEVSDivExpr*)S);
case scAddRecExpr:
return ((SC*)this)->visitAddRecExpr((SCEVAddRecExpr*)S);
case scSMaxExpr:
Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=60407&r1=60406&r2=60407&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Tue Dec 2 02:05:48 2008
@@ -324,6 +324,26 @@
return LHS->getType();
}
+
+// SCEVSDivs - Only allow the creation of one SCEVSDivExpr for any particular
+// input. Don't use a SCEVHandle here, or else the object will never be
+// deleted!
+static ManagedStatic<std::map<std::pair<SCEV*, SCEV*>,
+ SCEVSDivExpr*> > SCEVSDivs;
+
+SCEVSDivExpr::~SCEVSDivExpr() {
+ SCEVSDivs->erase(std::make_pair(LHS, RHS));
+}
+
+void SCEVSDivExpr::print(std::ostream &OS) const {
+ OS << "(" << *LHS << " /s " << *RHS << ")";
+}
+
+const Type *SCEVSDivExpr::getType() const {
+ return LHS->getType();
+}
+
+
// SCEVAddRecExprs - Only allow the creation of one SCEVAddRecExpr for any
// particular input. Don't use a SCEVHandle here, or else the object will never
// be deleted!
@@ -1109,9 +1129,12 @@
}
SCEVHandle ScalarEvolution::getUDivExpr(const SCEVHandle &LHS, const SCEVHandle &RHS) {
+ if (LHS == RHS)
+ return getIntegerSCEV(1, LHS->getType()); // X udiv X --> 1
+
if (SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS)) {
if (RHSC->getValue()->equalsInt(1))
- return LHS; // X udiv 1 --> x
+ return LHS; // X udiv 1 --> X
if (SCEVConstant *LHSC = dyn_cast<SCEVConstant>(LHS)) {
Constant *LHSCV = LHSC->getValue();
@@ -1120,13 +1143,34 @@
}
}
- // FIXME: implement folding of (X*4)/4 when we know X*4 doesn't overflow.
-
SCEVUDivExpr *&Result = (*SCEVUDivs)[std::make_pair(LHS, RHS)];
if (Result == 0) Result = new SCEVUDivExpr(LHS, RHS);
return Result;
}
+SCEVHandle ScalarEvolution::getSDivExpr(const SCEVHandle &LHS, const SCEVHandle &RHS) {
+ if (LHS == RHS)
+ return getIntegerSCEV(1, LHS->getType()); // X sdiv X --> 1
+
+ if (SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS)) {
+ if (RHSC->getValue()->equalsInt(1))
+ return LHS; // X sdiv 1 --> X
+
+ if (RHSC->getValue()->isAllOnesValue())
+ return getNegativeSCEV(LHS); // X sdiv -1 --> -X
+
+ if (SCEVConstant *LHSC = dyn_cast<SCEVConstant>(LHS)) {
+ Constant *LHSCV = LHSC->getValue();
+ Constant *RHSCV = RHSC->getValue();
+ return getUnknown(ConstantExpr::getSDiv(LHSCV, RHSCV));
+ }
+ }
+
+ SCEVSDivExpr *&Result = (*SCEVSDivs)[std::make_pair(LHS, RHS)];
+ if (Result == 0) Result = new SCEVSDivExpr(LHS, RHS);
+ return Result;
+}
+
/// SCEVAddRecExpr::get - Get a add recurrence expression for the
/// specified loop. Simplify the expression as much as possible.
@@ -1732,7 +1776,7 @@
return MinOpRes;
}
- // SCEVUDivExpr, SCEVUnknown
+ // SCEVUDivExpr, SCEVSDivExpr, SCEVUnknown
return 0;
}
@@ -1762,6 +1806,9 @@
case Instruction::UDiv:
return SE.getUDivExpr(getSCEV(U->getOperand(0)),
getSCEV(U->getOperand(1)));
+ case Instruction::SDiv:
+ return SE.getSDivExpr(getSCEV(U->getOperand(0)),
+ getSCEV(U->getOperand(1)));
case Instruction::Sub:
return SE.getMinusSCEV(getSCEV(U->getOperand(0)),
getSCEV(U->getOperand(1)));
@@ -1805,7 +1852,7 @@
break;
case Instruction::LShr:
- // Turn logical shift right of a constant into a unsigned divide.
+ // Turn logical shift right of a constant into an unsigned divide.
if (ConstantInt *SA = dyn_cast<ConstantInt>(U->getOperand(1))) {
uint32_t BitWidth = cast<IntegerType>(V->getType())->getBitWidth();
Constant *X = ConstantInt::get(
@@ -2505,16 +2552,26 @@
return Comm;
}
- if (SCEVUDivExpr *Div = dyn_cast<SCEVUDivExpr>(V)) {
- SCEVHandle LHS = getSCEVAtScope(Div->getLHS(), L);
+ if (SCEVUDivExpr *UDiv = dyn_cast<SCEVUDivExpr>(V)) {
+ SCEVHandle LHS = getSCEVAtScope(UDiv->getLHS(), L);
if (LHS == UnknownValue) return LHS;
- SCEVHandle RHS = getSCEVAtScope(Div->getRHS(), L);
+ SCEVHandle RHS = getSCEVAtScope(UDiv->getRHS(), L);
if (RHS == UnknownValue) return RHS;
- if (LHS == Div->getLHS() && RHS == Div->getRHS())
- return Div; // must be loop invariant
+ if (LHS == UDiv->getLHS() && RHS == UDiv->getRHS())
+ return UDiv; // must be loop invariant
return SE.getUDivExpr(LHS, RHS);
}
+ if (SCEVSDivExpr *SDiv = dyn_cast<SCEVSDivExpr>(V)) {
+ SCEVHandle LHS = getSCEVAtScope(SDiv->getLHS(), L);
+ if (LHS == UnknownValue) return LHS;
+ SCEVHandle RHS = getSCEVAtScope(SDiv->getRHS(), L);
+ if (RHS == UnknownValue) return RHS;
+ if (LHS == SDiv->getLHS() && RHS == SDiv->getRHS())
+ return SDiv; // must be loop invariant
+ return SE.getSDivExpr(LHS, RHS);
+ }
+
// If this is a loop recurrence for a loop that does not contain L, then we
// are dealing with the final value computed by the loop.
if (SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(V)) {
Modified: llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp?rev=60407&r1=60406&r2=60407&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Tue Dec 2 02:05:48 2008
@@ -143,6 +143,15 @@
return InsertBinop(Instruction::UDiv, LHS, RHS, InsertPt);
}
+Value *SCEVExpander::visitSDivExpr(SCEVSDivExpr *S) {
+ // Do not fold sdiv into ashr, unless you know that LHS is positive. On
+ // negative values, it rounds the wrong way.
+
+ Value *LHS = expand(S->getLHS());
+ Value *RHS = expand(S->getRHS());
+ return InsertBinop(Instruction::SDiv, LHS, RHS, InsertPt);
+}
+
Value *SCEVExpander::visitAddRecExpr(SCEVAddRecExpr *S) {
const Type *Ty = S->getType();
const Loop *L = S->getLoop();
More information about the llvm-commits
mailing list