diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h --- a/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -2119,6 +2119,10 @@ /// tried. SmallPtrSet UnsignedWrapViaInductionTried; + /// Set of AddRecs for which proving NSW via an induction has already been + /// tried. + SmallPtrSet SignedWrapViaInductionTried; + /// The head of a linked list of all SCEVUnknown values that have been /// allocated. This is used by releaseMemory to locate them all and call /// their destructors. diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -4958,6 +4958,10 @@ if (!AR->isAffine()) return Result; + // This function can be expensive, only try to prove NSW once per AddRec. + if (!SignedWrapViaInductionTried.insert(AR).second) + return Result; + const SCEV *Step = AR->getStepRecurrence(*this); const Loop *L = AR->getLoop(); @@ -13584,8 +13588,10 @@ HasRecMap.erase(S); MinTrailingZerosCache.erase(S); - if (auto *AR = dyn_cast(S)) + if (auto *AR = dyn_cast(S)) { UnsignedWrapViaInductionTried.erase(AR); + SignedWrapViaInductionTried.erase(AR); + } auto ExprIt = ExprValueMap.find(S); if (ExprIt != ExprValueMap.end()) {