diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index c17fa97ef5f..8249d70d1f5 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -725,22 +725,32 @@ private: SmallVector, 2>> LoopDispositions; - /// Cache for \c loopHasNoAbnormalExits. - DenseMap LoopHasNoAbnormalExits; + struct LoopProperties { + /// Set to true if the loop contains no instruction that can have side + /// effects (i.e. via throwing an exception, volatile or atomic access). + bool HasNoAbnormalExits; - /// Cache for \c loopHasNoSideEffects. - DenseMap LoopHasNoSideEffects; + /// Set to true if the loop contains no instruction that can abnormally exit + /// the loop (i.e. via throwing an exception, by terminating the thread + /// cleanly or by infinite looping in a called function). Strictly + /// speaking, the last one is not leaving the loop, but is identical to + /// leaving the loop for reasoning about undefined behavior. + bool HasNoSideEffects; + }; - /// Returns true if \p L contains no instruction that can have side effects - /// (i.e. via throwing an exception, volatile or atomic access). - bool loopHasNoSideEffects(const Loop *L); + /// Cache for \c getLoopProperties. + DenseMap LoopPropertiesCache; - /// Returns true if \p L contains no instruction that can abnormally exit - /// the loop (i.e. via throwing an exception, by terminating the thread - /// cleanly or by infinite looping in a called function). Strictly - /// speaking, the last one is not leaving the loop, but is identical to - /// leaving the loop for reasoning about undefined behavior. - bool loopHasNoAbnormalExits(const Loop *L); + /// Return a \c LoopProperties instance for \p L, creating one if necessary. + LoopProperties getLoopProperties(const Loop *L); + + bool loopHasNoSideEffects(const Loop *L) { + return getLoopProperties(L).HasNoSideEffects; + } + + bool loopHasNoAbnormalExits(const Loop *L) { + return getLoopProperties(L).HasNoAbnormalExits; + } /// Compute a LoopDisposition value. LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L); diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 602a287dcbc..af23effcaf2 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -4953,39 +4953,33 @@ bool ScalarEvolution::isAddRecNeverPoison(const Instruction *I, const Loop *L) { return LatchControlDependentOnPoison && loopHasNoAbnormalExits(L); } -bool ScalarEvolution::loopHasNoSideEffects(const Loop *L) { - auto Itr = LoopHasNoSideEffects.find(L); - if (Itr == LoopHasNoSideEffects.end()) { - auto NoSideEffectsInBB = [&](BasicBlock *BB) { - return all_of(*BB, [](Instruction &I) { - // Non-atomic, non-volatile stores are ok. - if (auto *SI = dyn_cast(&I)) - return SI->isSimple(); +ScalarEvolution::LoopProperties +ScalarEvolution::getLoopProperties(const Loop *L) { + typedef ScalarEvolution::LoopProperties LoopProperties; - return !I.mayHaveSideEffects(); - }); + auto Itr = LoopPropertiesCache.find(L); + if (Itr == LoopPropertiesCache.end()) { + auto HasSideEffects = [](Instruction *I) { + if (auto *SI = dyn_cast(I)) + return !SI->isSimple(); + + return I->mayHaveSideEffects(); }; - auto InsertPair = LoopHasNoSideEffects.insert( - {L, all_of(L->getBlocks(), NoSideEffectsInBB)}); - assert(InsertPair.second && "We just checked!"); - Itr = InsertPair.first; - } + LoopProperties LP = {/* HasNoAbnormalExits */ true, + /*HasNoSideEffects*/ true}; - return Itr->second; -} + for (auto *BB : L->getBlocks()) + for (auto &I : *BB) { + if (!isGuaranteedToTransferExecutionToSuccessor(&I)) + LP.HasNoAbnormalExits = false; + if (HasSideEffects(&I)) + LP.HasNoSideEffects = false; + if (!LP.HasNoAbnormalExits && !LP.HasNoSideEffects) + break; // We're already as pessimistic as we can get. + } -bool ScalarEvolution::loopHasNoAbnormalExits(const Loop *L) { - auto Itr = LoopHasNoAbnormalExits.find(L); - if (Itr == LoopHasNoAbnormalExits.end()) { - auto NoAbnormalExitInBB = [&](BasicBlock *BB) { - return all_of(*BB, [](Instruction &I) { - return isGuaranteedToTransferExecutionToSuccessor(&I); - }); - }; - - auto InsertPair = LoopHasNoAbnormalExits.insert( - {L, all_of(L->getBlocks(), NoAbnormalExitInBB)}); + auto InsertPair = LoopPropertiesCache.insert({L, LP}); assert(InsertPair.second && "We just checked!"); Itr = InsertPair.first; } @@ -5561,8 +5555,7 @@ void ScalarEvolution::forgetLoop(const Loop *L) { for (Loop *I : *L) forgetLoop(I); - LoopHasNoAbnormalExits.erase(L); - LoopHasNoSideEffects.erase(L); + LoopPropertiesCache.erase(L); } void ScalarEvolution::forgetValue(Value *V) {