diff options
Diffstat (limited to 'llvm/lib/Analysis/ScalarEvolution.cpp')
-rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 363 |
1 files changed, 201 insertions, 162 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index f7c22cfb0310..7dc7f9904c70 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -2915,8 +2915,8 @@ ScalarEvolution::getOrCreateAddRecExpr(ArrayRef<const SCEV *> Ops, const Loop *L, SCEV::NoWrapFlags Flags) { FoldingSetNodeID ID; ID.AddInteger(scAddRecExpr); - for (unsigned i = 0, e = Ops.size(); i != e; ++i) - ID.AddPointer(Ops[i]); + for (const SCEV *Op : Ops) + ID.AddPointer(Op); ID.AddPointer(L); void *IP = nullptr; SCEVAddRecExpr *S = @@ -2939,8 +2939,8 @@ ScalarEvolution::getOrCreateMulExpr(ArrayRef<const SCEV *> Ops, SCEV::NoWrapFlags Flags) { FoldingSetNodeID ID; ID.AddInteger(scMulExpr); - for (unsigned i = 0, e = Ops.size(); i != e; ++i) - ID.AddPointer(Ops[i]); + for (const SCEV *Op : Ops) + ID.AddPointer(Op); void *IP = nullptr; SCEVMulExpr *S = static_cast<SCEVMulExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP)); @@ -3708,8 +3708,8 @@ SCEV *ScalarEvolution::findExistingSCEVInCache(SCEVTypes SCEVType, ArrayRef<const SCEV *> Ops) { FoldingSetNodeID ID; ID.AddInteger(SCEVType); - for (unsigned i = 0, e = Ops.size(); i != e; ++i) - ID.AddPointer(Ops[i]); + for (const SCEV *Op : Ops) + ID.AddPointer(Op); void *IP = nullptr; return UniqueSCEVs.FindNodeOrInsertPos(ID, IP); } @@ -4094,6 +4094,17 @@ void ScalarEvolution::eraseValueFromMap(Value *V) { } } +void ScalarEvolution::insertValueToMap(Value *V, const SCEV *S) { + // A recursive query may have already computed the SCEV. It should be + // equivalent, but may not necessarily be exactly the same, e.g. due to lazily + // inferred nowrap flags. + auto It = ValueExprMap.find_as(V); + if (It == ValueExprMap.end()) { + ValueExprMap.insert({SCEVCallbackVH(V, this), S}); + ExprValueMap[S].insert({V, nullptr}); + } +} + /// Return an existing SCEV if it exists, otherwise analyze the expression and /// create a new one. const SCEV *ScalarEvolution::getSCEV(Value *V) { @@ -4134,10 +4145,9 @@ const SCEV *ScalarEvolution::getExistingSCEV(Value *V) { ValueExprMapType::iterator I = ValueExprMap.find_as(V); if (I != ValueExprMap.end()) { const SCEV *S = I->second; - if (checkValidity(S)) - return S; - eraseValueFromMap(V); - forgetMemoizedResults(S); + assert(checkValidity(S) && + "existing SCEV has not been properly invalidated"); + return S; } return nullptr; } @@ -4430,44 +4440,6 @@ static void PushDefUseChildren(Instruction *I, } } -void ScalarEvolution::forgetSymbolicName(Instruction *PN, const SCEV *SymName) { - SmallVector<Instruction *, 16> Worklist; - SmallPtrSet<Instruction *, 8> Visited; - SmallVector<const SCEV *, 8> ToForget; - Visited.insert(PN); - Worklist.push_back(PN); - while (!Worklist.empty()) { - Instruction *I = Worklist.pop_back_val(); - - auto It = ValueExprMap.find_as(static_cast<Value *>(I)); - if (It != ValueExprMap.end()) { - const SCEV *Old = It->second; - - // Short-circuit the def-use traversal if the symbolic name - // ceases to appear in expressions. - if (Old != SymName && !hasOperand(Old, SymName)) - continue; - - // SCEVUnknown for a PHI either means that it has an unrecognized - // structure, it's a PHI that's in the progress of being computed - // by createNodeForPHI, or it's a single-value PHI. In the first case, - // additional loop trip count information isn't going to change anything. - // In the second case, createNodeForPHI will perform the necessary - // updates on its own when it gets to that point. In the third, we do - // want to forget the SCEVUnknown. - if (!isa<PHINode>(I) || - !isa<SCEVUnknown>(Old) || - (I != PN && Old == SymName)) { - eraseValueFromMap(It->first); - ToForget.push_back(Old); - } - } - - PushDefUseChildren(I, Worklist, Visited); - } - forgetMemoizedResults(ToForget); -} - namespace { /// Takes SCEV S and Loop L. For each AddRec sub-expression, use its start @@ -5335,15 +5307,17 @@ const SCEV *ScalarEvolution::createSimpleAffineAddRec(PHINode *PN, const SCEV *StartVal = getSCEV(StartValueV); const SCEV *PHISCEV = getAddRecExpr(StartVal, Accum, L, Flags); - - ValueExprMap[SCEVCallbackVH(PN, this)] = PHISCEV; + insertValueToMap(PN, PHISCEV); // We can add Flags to the post-inc expression only if we // know that it is *undefined behavior* for BEValueV to // overflow. - if (auto *BEInst = dyn_cast<Instruction>(BEValueV)) - if (isLoopInvariant(Accum, L) && isAddRecNeverPoison(BEInst, L)) + if (auto *BEInst = dyn_cast<Instruction>(BEValueV)) { + assert(isLoopInvariant(Accum, L) && + "Accum is defined outside L, but is not invariant?"); + if (isAddRecNeverPoison(BEInst, L)) (void)getAddRecExpr(getAddExpr(StartVal, Accum), Accum, L, Flags); + } return PHISCEV; } @@ -5386,7 +5360,7 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) { // Handle PHI node value symbolically. const SCEV *SymbolicName = getUnknown(PN); - ValueExprMap.insert({SCEVCallbackVH(PN, this), SymbolicName}); + insertValueToMap(PN, SymbolicName); // Using this symbolic name for the PHI, analyze the value coming around // the back-edge. @@ -5457,8 +5431,8 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) { // Okay, for the entire analysis of this edge we assumed the PHI // to be symbolic. We now need to go back and purge all of the // entries for the scalars that use the symbolic expression. - forgetSymbolicName(PN, SymbolicName); - ValueExprMap[SCEVCallbackVH(PN, this)] = PHISCEV; + forgetMemoizedResults(SymbolicName); + insertValueToMap(PN, PHISCEV); // We can add Flags to the post-inc expression only if we // know that it is *undefined behavior* for BEValueV to @@ -5489,8 +5463,8 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) { // Okay, for the entire analysis of this edge we assumed the PHI // to be symbolic. We now need to go back and purge all of the // entries for the scalars that use the symbolic expression. - forgetSymbolicName(PN, SymbolicName); - ValueExprMap[SCEVCallbackVH(PN, this)] = Shifted; + forgetMemoizedResults(SymbolicName); + insertValueToMap(PN, Shifted); return Shifted; } } @@ -7598,62 +7572,19 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { // Now that we know more about the trip count for this loop, forget any // existing SCEV values for PHI nodes in this loop since they are only // conservative estimates made without the benefit of trip count - // information. This is similar to the code in forgetLoop, except that - // it handles SCEVUnknown PHI nodes specially. + // information. This invalidation is not necessary for correctness, and is + // only done to produce more precise results. if (Result.hasAnyInfo()) { - SmallVector<Instruction *, 16> Worklist; - SmallPtrSet<Instruction *, 8> Discovered; + // Invalidate any expression using an addrec in this loop. SmallVector<const SCEV *, 8> ToForget; - PushLoopPHIs(L, Worklist, Discovered); - while (!Worklist.empty()) { - Instruction *I = Worklist.pop_back_val(); - - ValueExprMapType::iterator It = - ValueExprMap.find_as(static_cast<Value *>(I)); - if (It != ValueExprMap.end()) { - const SCEV *Old = It->second; - - // SCEVUnknown for a PHI either means that it has an unrecognized - // structure, or it's a PHI that's in the progress of being computed - // by createNodeForPHI. In the former case, additional loop trip - // count information isn't going to change anything. In the later - // case, createNodeForPHI will perform the necessary updates on its - // own when it gets to that point. - if (!isa<PHINode>(I) || !isa<SCEVUnknown>(Old)) { - eraseValueFromMap(It->first); - ToForget.push_back(Old); - } - if (PHINode *PN = dyn_cast<PHINode>(I)) - ConstantEvolutionLoopExitValue.erase(PN); - } - - // 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) && - Discovered.insert(I).second) - Worklist.push_back(I); - } - } + auto LoopUsersIt = LoopUsers.find(L); + if (LoopUsersIt != LoopUsers.end()) + append_range(ToForget, LoopUsersIt->second); forgetMemoizedResults(ToForget); + + // Invalidate constant-evolved loop header phis. + for (PHINode &PN : L->getHeader()->phis()) + ConstantEvolutionLoopExitValue.erase(&PN); } // Re-lookup the insert position, since the call to @@ -7672,10 +7603,12 @@ void ScalarEvolution::forgetAllLoops() { // result. BackedgeTakenCounts.clear(); PredicatedBackedgeTakenCounts.clear(); + BECountUsers.clear(); LoopPropertiesCache.clear(); ConstantEvolutionLoopExitValue.clear(); ValueExprMap.clear(); ValuesAtScopes.clear(); + ValuesAtScopesUsers.clear(); LoopDispositions.clear(); BlockDispositions.clear(); UnsignedRanges.clear(); @@ -7697,8 +7630,8 @@ void ScalarEvolution::forgetLoop(const Loop *L) { auto *CurrL = LoopWorklist.pop_back_val(); // Drop any stored trip count value. - BackedgeTakenCounts.erase(CurrL); - PredicatedBackedgeTakenCounts.erase(CurrL); + forgetBackedgeTakenCounts(CurrL, /* Predicated */ false); + forgetBackedgeTakenCounts(CurrL, /* Predicated */ true); // Drop information about predicated SCEV rewrites for this loop. for (auto I = PredicatedSCEVRewrites.begin(); @@ -7872,10 +7805,6 @@ bool ScalarEvolution::BackedgeTakenInfo::isConstantMaxOrZero( return MaxOrZero && !any_of(ExitNotTaken, PredicateNotAlwaysTrue); } -bool ScalarEvolution::BackedgeTakenInfo::hasOperand(const SCEV *S) const { - return Operands.contains(S); -} - ScalarEvolution::ExitLimit::ExitLimit(const SCEV *E) : ExitLimit(E, E, false, None) { } @@ -7916,19 +7845,6 @@ ScalarEvolution::ExitLimit::ExitLimit(const SCEV *E, const SCEV *M, : ExitLimit(E, M, MaxOrZero, None) { } -class SCEVRecordOperands { - SmallPtrSetImpl<const SCEV *> &Operands; - -public: - SCEVRecordOperands(SmallPtrSetImpl<const SCEV *> &Operands) - : Operands(Operands) {} - bool follow(const SCEV *S) { - Operands.insert(S); - return true; - } - bool isDone() { return false; } -}; - /// Allocate memory for BackedgeTakenInfo and copy the not-taken count of each /// computable exit into a persistent ExitNotTakenInfo array. ScalarEvolution::BackedgeTakenInfo::BackedgeTakenInfo( @@ -7957,14 +7873,6 @@ ScalarEvolution::BackedgeTakenInfo::BackedgeTakenInfo( assert((isa<SCEVCouldNotCompute>(ConstantMax) || isa<SCEVConstant>(ConstantMax)) && "No point in having a non-constant max backedge taken count!"); - - SCEVRecordOperands RecordOperands(Operands); - SCEVTraversal<SCEVRecordOperands> ST(RecordOperands); - if (!isa<SCEVCouldNotCompute>(ConstantMax)) - ST.visitAll(ConstantMax); - for (auto &ENT : ExitNotTaken) - if (!isa<SCEVCouldNotCompute>(ENT.ExactNotTaken)) - ST.visitAll(ENT.ExactNotTaken); } /// Compute the number of times the backedge of the specified loop will execute. @@ -8046,6 +7954,13 @@ ScalarEvolution::computeBackedgeTakenCount(const Loop *L, // The loop backedge will be taken the maximum or zero times if there's // a single exit that must be taken the maximum or zero times. bool MaxOrZero = (MustExitMaxOrZero && ExitingBlocks.size() == 1); + + // Remember which SCEVs are used in exit limits for invalidation purposes. + // We only care about non-constant SCEVs here, so we can ignore EL.MaxNotTaken + // and MaxBECount, which must be SCEVConstant. + for (const auto &Pair : ExitCounts) + if (!isa<SCEVConstant>(Pair.second.ExactNotTaken)) + BECountUsers[Pair.second.ExactNotTaken].insert({L, AllowPredicates}); return BackedgeTakenInfo(std::move(ExitCounts), CouldComputeBECount, MaxBECount, MaxOrZero); } @@ -8916,6 +8831,9 @@ const SCEV *ScalarEvolution::getSCEVAtScope(const SCEV *V, const Loop *L) { LS.second = C; break; } + + if (!isa<SCEVConstant>(C)) + ValuesAtScopesUsers[C].push_back({L, V}); return C; } @@ -12387,7 +12305,7 @@ const SCEV *SCEVAddRecExpr::getNumIterationsInRange(const ConstantRange &Range, if (Range.contains(Val->getValue())) return SE.getCouldNotCompute(); // Something strange happened - // Ensure that the previous value is in the range. This is a sanity check. + // Ensure that the previous value is in the range. assert(Range.contains( EvaluateConstantChrecAtConstant(this, ConstantInt::get(SE.getContext(), ExitVal - 1), SE)->getValue()) && @@ -12531,9 +12449,11 @@ ScalarEvolution::ScalarEvolution(ScalarEvolution &&Arg) BackedgeTakenCounts(std::move(Arg.BackedgeTakenCounts)), PredicatedBackedgeTakenCounts( std::move(Arg.PredicatedBackedgeTakenCounts)), + BECountUsers(std::move(Arg.BECountUsers)), ConstantEvolutionLoopExitValue( std::move(Arg.ConstantEvolutionLoopExitValue)), ValuesAtScopes(std::move(Arg.ValuesAtScopes)), + ValuesAtScopesUsers(std::move(Arg.ValuesAtScopesUsers)), LoopDispositions(std::move(Arg.LoopDispositions)), LoopPropertiesCache(std::move(Arg.LoopPropertiesCache)), BlockDispositions(std::move(Arg.BlockDispositions)), @@ -12946,6 +12866,23 @@ bool ScalarEvolution::hasOperand(const SCEV *S, const SCEV *Op) const { return SCEVExprContains(S, [&](const SCEV *Expr) { return Expr == Op; }); } +void ScalarEvolution::forgetBackedgeTakenCounts(const Loop *L, + bool Predicated) { + auto &BECounts = + Predicated ? PredicatedBackedgeTakenCounts : BackedgeTakenCounts; + auto It = BECounts.find(L); + if (It != BECounts.end()) { + for (const ExitNotTakenInfo &ENT : It->second.ExitNotTaken) { + if (!isa<SCEVConstant>(ENT.ExactNotTaken)) { + auto UserIt = BECountUsers.find(ENT.ExactNotTaken); + assert(UserIt != BECountUsers.end()); + UserIt->second.erase({L, Predicated}); + } + } + BECounts.erase(It); + } +} + void ScalarEvolution::forgetMemoizedResults(ArrayRef<const SCEV *> SCEVs) { SmallPtrSet<const SCEV *, 8> ToForget(SCEVs.begin(), SCEVs.end()); SmallVector<const SCEV *, 8> Worklist(ToForget.begin(), ToForget.end()); @@ -12970,32 +12907,52 @@ void ScalarEvolution::forgetMemoizedResults(ArrayRef<const SCEV *> SCEVs) { else ++I; } - - auto RemoveSCEVFromBackedgeMap = [&ToForget]( - DenseMap<const Loop *, BackedgeTakenInfo> &Map) { - for (auto I = Map.begin(), E = Map.end(); I != E;) { - BackedgeTakenInfo &BEInfo = I->second; - if (any_of(ToForget, - [&BEInfo](const SCEV *S) { return BEInfo.hasOperand(S); })) - Map.erase(I++); - else - ++I; - } - }; - - RemoveSCEVFromBackedgeMap(BackedgeTakenCounts); - RemoveSCEVFromBackedgeMap(PredicatedBackedgeTakenCounts); } void ScalarEvolution::forgetMemoizedResultsImpl(const SCEV *S) { - ValuesAtScopes.erase(S); LoopDispositions.erase(S); BlockDispositions.erase(S); UnsignedRanges.erase(S); SignedRanges.erase(S); - ExprValueMap.erase(S); HasRecMap.erase(S); MinTrailingZerosCache.erase(S); + + auto ExprIt = ExprValueMap.find(S); + if (ExprIt != ExprValueMap.end()) { + for (auto &ValueAndOffset : ExprIt->second) { + if (ValueAndOffset.second == nullptr) { + auto ValueIt = ValueExprMap.find_as(ValueAndOffset.first); + if (ValueIt != ValueExprMap.end()) + ValueExprMap.erase(ValueIt); + } + } + ExprValueMap.erase(ExprIt); + } + + auto ScopeIt = ValuesAtScopes.find(S); + if (ScopeIt != ValuesAtScopes.end()) { + for (const auto &Pair : ScopeIt->second) + if (!isa_and_nonnull<SCEVConstant>(Pair.second)) + erase_value(ValuesAtScopesUsers[Pair.second], + std::make_pair(Pair.first, S)); + ValuesAtScopes.erase(ScopeIt); + } + + auto ScopeUserIt = ValuesAtScopesUsers.find(S); + if (ScopeUserIt != ValuesAtScopesUsers.end()) { + for (const auto &Pair : ScopeUserIt->second) + erase_value(ValuesAtScopes[Pair.second], std::make_pair(Pair.first, S)); + ValuesAtScopesUsers.erase(ScopeUserIt); + } + + auto BEUsersIt = BECountUsers.find(S); + if (BEUsersIt != BECountUsers.end()) { + // Work on a copy, as forgetBackedgeTakenCounts() will modify the original. + auto Copy = BEUsersIt->second; + for (const auto &Pair : Copy) + forgetBackedgeTakenCounts(Pair.getPointer(), Pair.getInt()); + BECountUsers.erase(BEUsersIt); + } } void @@ -13100,16 +13057,43 @@ void ScalarEvolution::verify() const { ValidLoops.insert(L); Worklist.append(L->begin(), L->end()); } - // Check for SCEV expressions referencing invalid/deleted loops. for (auto &KV : ValueExprMap) { - auto *AR = dyn_cast<SCEVAddRecExpr>(KV.second); - if (!AR) - continue; - assert(ValidLoops.contains(AR->getLoop()) && - "AddRec references invalid loop"); + // Check for SCEV expressions referencing invalid/deleted loops. + if (auto *AR = dyn_cast<SCEVAddRecExpr>(KV.second)) { + assert(ValidLoops.contains(AR->getLoop()) && + "AddRec references invalid loop"); + } + + // Check that the value is also part of the reverse map. + auto It = ExprValueMap.find(KV.second); + if (It == ExprValueMap.end() || !It->second.contains({KV.first, nullptr})) { + dbgs() << "Value " << *KV.first + << " is in ValueExprMap but not in ExprValueMap\n"; + std::abort(); + } + } + + for (const auto &KV : ExprValueMap) { + for (const auto &ValueAndOffset : KV.second) { + if (ValueAndOffset.second != nullptr) + continue; + + auto It = ValueExprMap.find_as(ValueAndOffset.first); + if (It == ValueExprMap.end()) { + dbgs() << "Value " << *ValueAndOffset.first + << " is in ExprValueMap but not in ValueExprMap\n"; + std::abort(); + } + if (It->second != KV.first) { + dbgs() << "Value " << *ValueAndOffset.first + << " mapped to " << *It->second + << " rather than " << *KV.first << "\n"; + std::abort(); + } + } } - // Verify intergity of SCEV users. + // Verify integrity of SCEV users. for (const auto &S : UniqueSCEVs) { SmallVector<const SCEV *, 4> Ops; collectUniqueOps(&S, Ops); @@ -13125,6 +13109,61 @@ void ScalarEvolution::verify() const { std::abort(); } } + + // Verify integrity of ValuesAtScopes users. + for (const auto &ValueAndVec : ValuesAtScopes) { + const SCEV *Value = ValueAndVec.first; + for (const auto &LoopAndValueAtScope : ValueAndVec.second) { + const Loop *L = LoopAndValueAtScope.first; + const SCEV *ValueAtScope = LoopAndValueAtScope.second; + if (!isa<SCEVConstant>(ValueAtScope)) { + auto It = ValuesAtScopesUsers.find(ValueAtScope); + if (It != ValuesAtScopesUsers.end() && + is_contained(It->second, std::make_pair(L, Value))) + continue; + dbgs() << "Value: " << *Value << ", Loop: " << *L << ", ValueAtScope: " + << ValueAtScope << " missing in ValuesAtScopesUsers\n"; + std::abort(); + } + } + } + + for (const auto &ValueAtScopeAndVec : ValuesAtScopesUsers) { + const SCEV *ValueAtScope = ValueAtScopeAndVec.first; + for (const auto &LoopAndValue : ValueAtScopeAndVec.second) { + const Loop *L = LoopAndValue.first; + const SCEV *Value = LoopAndValue.second; + assert(!isa<SCEVConstant>(Value)); + auto It = ValuesAtScopes.find(Value); + if (It != ValuesAtScopes.end() && + is_contained(It->second, std::make_pair(L, ValueAtScope))) + continue; + dbgs() << "Value: " << *Value << ", Loop: " << *L << ", ValueAtScope: " + << ValueAtScope << " missing in ValuesAtScopes\n"; + std::abort(); + } + } + + // Verify integrity of BECountUsers. + auto VerifyBECountUsers = [&](bool Predicated) { + auto &BECounts = + Predicated ? PredicatedBackedgeTakenCounts : BackedgeTakenCounts; + for (const auto &LoopAndBEInfo : BECounts) { + for (const ExitNotTakenInfo &ENT : LoopAndBEInfo.second.ExitNotTaken) { + if (!isa<SCEVConstant>(ENT.ExactNotTaken)) { + auto UserIt = BECountUsers.find(ENT.ExactNotTaken); + if (UserIt != BECountUsers.end() && + UserIt->second.contains({ LoopAndBEInfo.first, Predicated })) + continue; + dbgs() << "Value " << *ENT.ExactNotTaken << " for loop " + << *LoopAndBEInfo.first << " missing from BECountUsers\n"; + std::abort(); + } + } + } + }; + VerifyBECountUsers(/* Predicated */ false); + VerifyBECountUsers(/* Predicated */ true); } bool ScalarEvolution::invalidate( |