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 @@ -2115,6 +2115,10 @@ std::pair>> PredicatedSCEVRewrites; + /// Set of AddRecs for which proving NUW via an induction has already been + /// tried. + SmallPtrSet UnsignedWrapViaInductionTried; + /// 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 @@ -5007,6 +5007,10 @@ if (!AR->isAffine()) return Result; + // This function can be expensive, only try to prove NUW once per AddRec. + if (!UnsignedWrapViaInductionTried.insert(AR).second) + return Result; + const SCEV *Step = AR->getStepRecurrence(*this); unsigned BitWidth = getTypeSizeInBits(AR->getType()); const Loop *L = AR->getLoop(); @@ -13580,6 +13584,9 @@ HasRecMap.erase(S); MinTrailingZerosCache.erase(S); + if (auto *AR = dyn_cast(S)) + UnsignedWrapViaInductionTried.erase(AR); + auto ExprIt = ExprValueMap.find(S); if (ExprIt != ExprValueMap.end()) { for (Value *V : ExprIt->second) {