[llvm-branch-commits] [llvm-branch] r119622 - in /llvm/branches/Apple/whitney: include/llvm/Analysis/ScalarEvolution.h lib/Analysis/ScalarEvolution.cpp
Daniel Dunbar
daniel at zuster.org
Wed Nov 17 18:36:14 PST 2010
Author: ddunbar
Date: Wed Nov 17 20:36:14 2010
New Revision: 119622
URL: http://llvm.org/viewvc/llvm-project?rev=119622&view=rev
Log:
Merge r119584:
--
Author: Dan Gohman <gohman at apple.com>
Date: Wed Nov 17 23:21:44 2010 +0000
Merge the implementations of isLoopInvariant and hasComputableLoopEvolution, and
memoize the results. This improves compile time in code which highly complex
expressions which get queried many times.
Modified:
llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolution.h
llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolution.cpp
Modified: llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolution.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolution.h?rev=119622&r1=119621&r2=119622&view=diff
==============================================================================
--- llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolution.h (original)
+++ llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolution.h Wed Nov 17 20:36:14 2010
@@ -142,6 +142,16 @@
/// they must ask this class for services.
///
class ScalarEvolution : public FunctionPass {
+ public:
+ /// LoopDisposition - An enum describing the relationship between a
+ /// SCEV and a loop.
+ enum LoopDisposition {
+ LoopVariant, ///< The SCEV is loop-variant (unknown).
+ LoopInvariant, ///< The SCEV is loop-invariant.
+ LoopComputable ///< The SCEV varies predictably with the loop.
+ };
+
+ private:
/// SCEVCallbackVH - A CallbackVH to arrange for ScalarEvolution to be
/// notified whenever a Value is deleted.
class SCEVCallbackVH : public CallbackVH {
@@ -229,6 +239,13 @@
std::map<const SCEV *,
std::map<const Loop *, const SCEV *> > ValuesAtScopes;
+ /// LoopDispositions - Memoized computeLoopDisposition results.
+ std::map<const SCEV *,
+ std::map<const Loop *, LoopDisposition> > LoopDispositions;
+
+ /// computeLoopDisposition - Compute a LoopDisposition value.
+ LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L);
+
/// UnsignedRanges - Memoized results from getUnsignedRange
DenseMap<const SCEV *, ConstantRange> UnsignedRanges;
@@ -663,6 +680,10 @@
const SCEV *&LHS,
const SCEV *&RHS);
+ /// getLoopDisposition - Return the "disposition" of the given SCEV with
+ /// respect to the given loop.
+ LoopDisposition getLoopDisposition(const SCEV *S, const Loop *L);
+
/// isLoopInvariant - Return true if the value of the given SCEV is
/// unchanging in the specified loop.
bool isLoopInvariant(const SCEV *S, const Loop *L);
Modified: llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolution.cpp?rev=119622&r1=119621&r2=119622&view=diff
==============================================================================
--- llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolution.cpp Wed Nov 17 20:36:14 2010
@@ -325,6 +325,7 @@
void SCEVUnknown::deleted() {
// Clear this SCEVUnknown from various maps.
SE->ValuesAtScopes.erase(this);
+ SE->LoopDispositions.erase(this);
SE->UnsignedRanges.erase(this);
SE->SignedRanges.erase(this);
@@ -338,6 +339,7 @@
void SCEVUnknown::allUsesReplacedWith(Value *New) {
// Clear this SCEVUnknown from various maps.
SE->ValuesAtScopes.erase(this);
+ SE->LoopDispositions.erase(this);
SE->UnsignedRanges.erase(this);
SE->SignedRanges.erase(this);
@@ -2634,6 +2636,7 @@
!isa<SCEVUnknown>(Old) ||
(I != PN && Old == SymName)) {
ValuesAtScopes.erase(Old);
+ LoopDispositions.erase(Old);
UnsignedRanges.erase(Old);
SignedRanges.erase(Old);
ValueExprMap.erase(It);
@@ -3667,6 +3670,7 @@
// own when it gets to that point.
if (!isa<PHINode>(I) || !isa<SCEVUnknown>(Old)) {
ValuesAtScopes.erase(Old);
+ LoopDispositions.erase(Old);
UnsignedRanges.erase(Old);
SignedRanges.erase(Old);
ValueExprMap.erase(It);
@@ -3702,6 +3706,7 @@
if (It != ValueExprMap.end()) {
const SCEV *Old = It->second;
ValuesAtScopes.erase(Old);
+ LoopDispositions.erase(Old);
UnsignedRanges.erase(Old);
SignedRanges.erase(Old);
ValueExprMap.erase(It);
@@ -3738,6 +3743,7 @@
if (It != ValueExprMap.end()) {
const SCEV *Old = It->second;
ValuesAtScopes.erase(Old);
+ LoopDispositions.erase(Old);
UnsignedRanges.erase(Old);
SignedRanges.erase(Old);
ValueExprMap.erase(It);
@@ -5795,6 +5801,7 @@
BackedgeTakenCounts.clear();
ConstantEvolutionLoopExitValue.clear();
ValuesAtScopes.clear();
+ LoopDispositions.clear();
UnsignedRanges.clear();
SignedRanges.clear();
UniqueSCEVs.clear();
@@ -5893,54 +5900,82 @@
PrintLoopInfo(OS, &SE, *I);
}
-bool ScalarEvolution::isLoopInvariant(const SCEV *S, const Loop *L) {
+ScalarEvolution::LoopDisposition
+ScalarEvolution::getLoopDisposition(const SCEV *S, const Loop *L) {
+ std::map<const Loop *, LoopDisposition> &Values = LoopDispositions[S];
+ std::pair<std::map<const Loop *, LoopDisposition>::iterator, bool> Pair =
+ Values.insert(std::make_pair(L, LoopVariant));
+ if (!Pair.second)
+ return Pair.first->second;
+
+ LoopDisposition D = computeLoopDisposition(S, L);
+ return LoopDispositions[S][L] = D;
+}
+
+ScalarEvolution::LoopDisposition
+ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) {
switch (S->getSCEVType()) {
case scConstant:
- return true;
+ return LoopInvariant;
case scTruncate:
case scZeroExtend:
case scSignExtend:
- return isLoopInvariant(cast<SCEVCastExpr>(S)->getOperand(), L);
+ return getLoopDisposition(cast<SCEVCastExpr>(S)->getOperand(), L);
case scAddRecExpr: {
const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(S);
+ // If L is the addrec's loop, it's computable.
+ if (AR->getLoop() == L)
+ return LoopComputable;
+
// Add recurrences are never invariant in the function-body (null loop).
if (!L)
- return false;
+ return LoopVariant;
// This recurrence is variant w.r.t. L if L contains AR's loop.
if (L->contains(AR->getLoop()))
- return false;
+ return LoopVariant;
// This recurrence is invariant w.r.t. L if AR's loop contains L.
if (AR->getLoop()->contains(L))
- return true;
+ return LoopInvariant;
// This recurrence is variant w.r.t. L if any of its operands
// are variant.
for (SCEVAddRecExpr::op_iterator I = AR->op_begin(), E = AR->op_end();
I != E; ++I)
if (!isLoopInvariant(*I, L))
- return false;
+ return LoopVariant;
// Otherwise it's loop-invariant.
- return true;
+ return LoopInvariant;
}
case scAddExpr:
case scMulExpr:
case scUMaxExpr:
case scSMaxExpr: {
const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S);
+ bool HasVarying = false;
for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end();
- I != E; ++I)
- if (!isLoopInvariant(*I, L))
- return false;
- return true;
+ I != E; ++I) {
+ LoopDisposition D = getLoopDisposition(*I, L);
+ if (D == LoopVariant)
+ return LoopVariant;
+ if (D == LoopComputable)
+ HasVarying = true;
+ }
+ return HasVarying ? LoopComputable : LoopInvariant;
}
case scUDivExpr: {
const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S);
- return isLoopInvariant(UDiv->getLHS(), L) &&
- isLoopInvariant(UDiv->getRHS(), L);
+ LoopDisposition LD = getLoopDisposition(UDiv->getLHS(), L);
+ if (LD == LoopVariant)
+ return LoopVariant;
+ LoopDisposition RD = getLoopDisposition(UDiv->getRHS(), L);
+ if (RD == LoopVariant)
+ return LoopVariant;
+ return (LD == LoopInvariant && RD == LoopInvariant) ?
+ LoopInvariant : LoopComputable;
}
case scUnknown:
// All non-instruction values are loop invariant. All instructions are loop
@@ -5948,71 +5983,23 @@
// Instructions are never considered invariant in the function body
// (null loop) because they are defined within the "loop".
if (Instruction *I = dyn_cast<Instruction>(cast<SCEVUnknown>(S)->getValue()))
- return L && !L->contains(I);
- return true;
+ return (L && !L->contains(I)) ? LoopInvariant : LoopVariant;
+ return LoopInvariant;
case scCouldNotCompute:
llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
- return false;
+ return LoopVariant;
default: break;
}
llvm_unreachable("Unknown SCEV kind!");
- return false;
+ return LoopVariant;
+}
+
+bool ScalarEvolution::isLoopInvariant(const SCEV *S, const Loop *L) {
+ return getLoopDisposition(S, L) == LoopInvariant;
}
bool ScalarEvolution::hasComputableLoopEvolution(const SCEV *S, const Loop *L) {
- switch (S->getSCEVType()) {
- case scConstant:
- return false;
- case scTruncate:
- case scZeroExtend:
- case scSignExtend:
- return hasComputableLoopEvolution(cast<SCEVCastExpr>(S)->getOperand(), L);
- case scAddRecExpr:
- return cast<SCEVAddRecExpr>(S)->getLoop() == L;
- case scAddExpr:
- case scMulExpr:
- case scUMaxExpr:
- case scSMaxExpr: {
- const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S);
- bool HasVarying = false;
- for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end();
- I != E; ++I) {
- const SCEV *Op = *I;
- if (!isLoopInvariant(Op, L)) {
- if (hasComputableLoopEvolution(Op, L))
- HasVarying = true;
- else
- return false;
- }
- }
- return HasVarying;
- }
- case scUDivExpr: {
- const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S);
- bool HasVarying = false;
- if (!isLoopInvariant(UDiv->getLHS(), L)) {
- if (hasComputableLoopEvolution(UDiv->getLHS(), L))
- HasVarying = true;
- else
- return false;
- }
- if (!isLoopInvariant(UDiv->getRHS(), L)) {
- if (hasComputableLoopEvolution(UDiv->getRHS(), L))
- HasVarying = true;
- else
- return false;
- }
- return HasVarying;
- }
- case scUnknown:
- return false;
- case scCouldNotCompute:
- llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
- return false;
- default: break;
- }
- llvm_unreachable("Unknown SCEV kind!");
- return false;
+ return getLoopDisposition(S, L) == LoopComputable;
}
bool ScalarEvolution::dominates(const SCEV *S, BasicBlock *BB) const {
More information about the llvm-branch-commits
mailing list