/// function as they are computed.
DenseMap<const Loop *, BackedgeTakenInfo> PredicatedBackedgeTakenCounts;
- // Cache the calculated exit limits for the loops.
- DenseMap<ExitLimitQuery, ExitLimit> ExitLimits;
-
/// This map contains entries for all of the PHI instructions that we
/// attempt to compute constant evolutions for. This allows us to avoid
/// potentially expensive recomputation of these properties. An instruction
ExitLimit computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,
bool AllowPredicates = false);
- ExitLimit computeExitLimitImpl(const Loop *L, BasicBlock *ExitingBlock,
- bool AllowPredicates = false);
-
/// Compute the number of times the backedge of the specified loop will
/// execute if its exit condition were a conditional branch of ExitCond,
/// TBB, and FBB.
/// to be a constant.
Optional<APInt> computeConstantDifference(const SCEV *LHS, const SCEV *RHS);
- /// Drop memoized information computed for S. Only erase Exit Limits info if
- /// we expect that the operation we have made is going to change it.
- void forgetMemoizedResults(const SCEV *S, bool EraseExitLimit = true);
+ /// Drop memoized information computed for S.
+ void forgetMemoizedResults(const SCEV *S);
/// Return an existing SCEV for V if there is one, otherwise return nullptr.
const SCEV *getExistingSCEV(Value *V);
// own when it gets to that point.
if (!isa<PHINode>(I) || !isa<SCEVUnknown>(Old)) {
eraseValueFromMap(It->first);
- forgetMemoizedResults(Old, false);
+ forgetMemoizedResults(Old);
}
if (PHINode *PN = dyn_cast<PHINode>(I))
ConstantEvolutionLoopExitValue.erase(PN);
}
- PushDefUseChildren(I, Worklist);
+ // Since we don't need to invalidate anything for correctness and we're
+ // only invalidating to make SCEV's results more precise, we get to stop
+ // early to avoid invalidating too much. This is especially important in
+ // cases like:
+ //
+ // %v = f(pn0, pn1) // pn0 and pn1 used through some other phi node
+ // loop0:
+ // %pn0 = phi
+ // ...
+ // loop1:
+ // %pn1 = phi
+ // ...
+ //
+ // where both loop0 and loop1's backedge taken count uses the SCEV
+ // expression for %v. If we don't have the early stop below then in cases
+ // like the above, getBackedgeTakenInfo(loop1) will clear out the trip
+ // count for loop0 and getBackedgeTakenInfo(loop0) will clear out the trip
+ // count for loop1, effectively nullifying SCEV's trip count cache.
+ for (auto *U : I->users())
+ if (auto *I = dyn_cast<Instruction>(U)) {
+ auto *LoopForUser = LI.getLoopFor(I->getParent());
+ if (LoopForUser && L->contains(LoopForUser))
+ Worklist.push_back(I);
+ }
}
}
PushDefUseChildren(I, Worklist);
}
- for (auto I = ExitLimits.begin(); I != ExitLimits.end(); ++I) {
- auto &Query = I->first;
- if (Query.L == CurrL)
- ExitLimits.erase(I);
- }
-
LoopPropertiesCache.erase(CurrL);
// Forget all contained loops too, to avoid dangling entries in the
// ValuesAtScopes map.
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
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)),
}
void
-ScalarEvolution::forgetMemoizedResults(const SCEV *S, bool EraseExitLimit) {
+ScalarEvolution::forgetMemoizedResults(const SCEV *S) {
ValuesAtScopes.erase(S);
LoopDispositions.erase(S);
BlockDispositions.erase(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::addToLoopUseLists(const SCEV *S) {