summaryrefslogtreecommitdiff
path: root/lib/Analysis/ScalarEvolution.cpp
diff options
context:
space:
mode:
authorMax Kazantsev <max.kazantsev@azul.com>2017-08-03 08:41:30 +0000
committerMax Kazantsev <max.kazantsev@azul.com>2017-08-03 08:41:30 +0000
commit511c1a306c885f5947c676677cc831d700852e5d (patch)
tree7886fbc26c866067851efce64344976e6964a584 /lib/Analysis/ScalarEvolution.cpp
parentdaeea6f68d6d67204c89a1f6100b8e958a02aa5f (diff)
[SCEV] Re-enable "Cache results of computeExitLimit"
The patch rL309080 was reverted because it did not clean up the cache on "forgetValue" method call. This patch re-enables this change, adds the missing check and introduces two new unit tests that make sure that the cache is cleaned properly. Differential Revision: https://reviews.llvm.org/D36087 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309925 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/ScalarEvolution.cpp')
-rw-r--r--lib/Analysis/ScalarEvolution.cpp39
1 files changed, 37 insertions, 2 deletions
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index d5abccb8dbb..d3baf532045 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -6200,7 +6200,7 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) {
// own when it gets to that point.
if (!isa<PHINode>(I) || !isa<SCEVUnknown>(Old)) {
eraseValueFromMap(It->first);
- forgetMemoizedResults(Old);
+ forgetMemoizedResults(Old, false);
}
if (PHINode *PN = dyn_cast<PHINode>(I))
ConstantEvolutionLoopExitValue.erase(PN);
@@ -6264,6 +6264,12 @@ void ScalarEvolution::forgetLoop(const Loop *L) {
PushDefUseChildren(I, Worklist);
}
+ for (auto I = ExitLimits.begin(); I != ExitLimits.end(); ++I) {
+ auto &Query = I->first;
+ if (Query.L == L)
+ ExitLimits.erase(I);
+ }
+
// Forget all contained loops too, to avoid dangling entries in the
// ValuesAtScopes map.
for (Loop *I : *L)
@@ -6526,6 +6532,18 @@ ScalarEvolution::computeBackedgeTakenCount(const Loop *L,
ScalarEvolution::ExitLimit
ScalarEvolution::computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,
bool AllowPredicates) {
+ ExitLimitQuery Query(L, ExitingBlock, AllowPredicates);
+ auto MaybeEL = ExitLimits.find(Query);
+ if (MaybeEL != ExitLimits.end())
+ return MaybeEL->second;
+ ExitLimit EL = computeExitLimitImpl(L, ExitingBlock, AllowPredicates);
+ ExitLimits.insert({Query, EL});
+ return EL;
+}
+
+ScalarEvolution::ExitLimit
+ScalarEvolution::computeExitLimitImpl(const Loop *L, BasicBlock *ExitingBlock,
+ bool AllowPredicates) {
// Okay, we've chosen an exiting block. See what condition causes us to exit
// at this block and remember the exit block and whether all other targets
@@ -10408,6 +10426,7 @@ ScalarEvolution::ScalarEvolution(ScalarEvolution &&Arg)
BackedgeTakenCounts(std::move(Arg.BackedgeTakenCounts)),
PredicatedBackedgeTakenCounts(
std::move(Arg.PredicatedBackedgeTakenCounts)),
+ ExitLimits(std::move(Arg.ExitLimits)),
ConstantEvolutionLoopExitValue(
std::move(Arg.ConstantEvolutionLoopExitValue)),
ValuesAtScopes(std::move(Arg.ValuesAtScopes)),
@@ -10810,7 +10829,16 @@ bool ScalarEvolution::hasOperand(const SCEV *S, const SCEV *Op) const {
return SCEVExprContains(S, [&](const SCEV *Expr) { return Expr == Op; });
}
-void ScalarEvolution::forgetMemoizedResults(const SCEV *S) {
+bool ScalarEvolution::ExitLimit::hasOperand(const SCEV *S) const {
+ auto IsS = [&](const SCEV *X) { return S == X; };
+ auto ContainsS = [&](const SCEV *X) {
+ return !isa<SCEVCouldNotCompute>(X) && SCEVExprContains(X, IsS);
+ };
+ return ContainsS(ExactNotTaken) || ContainsS(MaxNotTaken);
+}
+
+void
+ScalarEvolution::forgetMemoizedResults(const SCEV *S, bool EraseExitLimit) {
ValuesAtScopes.erase(S);
LoopDispositions.erase(S);
BlockDispositions.erase(S);
@@ -10843,6 +10871,13 @@ void ScalarEvolution::forgetMemoizedResults(const SCEV *S) {
RemoveSCEVFromBackedgeMap(BackedgeTakenCounts);
RemoveSCEVFromBackedgeMap(PredicatedBackedgeTakenCounts);
+
+ // TODO: There is a suspicion that we only need to do it when there is a
+ // SCEVUnknown somewhere inside S. Need to check this.
+ if (EraseExitLimit)
+ for (auto I = ExitLimits.begin(), E = ExitLimits.end(); I != E; ++I)
+ if (I->second.hasOperand(S))
+ ExitLimits.erase(I);
}
void ScalarEvolution::verify() const {