From: Sanjoy Das Date: Mon, 26 Sep 2016 02:44:07 +0000 (+0000) Subject: [SCEV] Combine two predicates into one; NFC X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a80a7d1c30562b8c351ea50d7bf41e8c7d85d277;p=llvm [SCEV] Combine two predicates into one; NFC Both `loopHasNoSideEffects` and `loopHasNoAbnormalExits` involve walking the loop and maintaining similar sorts of caches. This commit changes SCEV to compute both the predicates via a single walk, and maintain a single cache instead of two. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282375 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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; - - /// Cache for \c loopHasNoSideEffects. - DenseMap LoopHasNoSideEffects; - - /// 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); - - /// 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); + 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; + + /// 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; + }; + + /// Cache for \c getLoopProperties. + DenseMap LoopPropertiesCache; + + /// 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(); - - return !I.mayHaveSideEffects(); - }); - }; +ScalarEvolution::LoopProperties +ScalarEvolution::getLoopProperties(const Loop *L) { + typedef ScalarEvolution::LoopProperties LoopProperties; - auto InsertPair = LoopHasNoSideEffects.insert( - {L, all_of(L->getBlocks(), NoSideEffectsInBB)}); - assert(InsertPair.second && "We just checked!"); - Itr = InsertPair.first; - } + auto Itr = LoopPropertiesCache.find(L); + if (Itr == LoopPropertiesCache.end()) { + auto HasSideEffects = [](Instruction *I) { + if (auto *SI = dyn_cast(I)) + return !SI->isSimple(); - return Itr->second; -} - -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); - }); + return I->mayHaveSideEffects(); }; - auto InsertPair = LoopHasNoAbnormalExits.insert( - {L, all_of(L->getBlocks(), NoAbnormalExitInBB)}); + LoopProperties LP = {/* HasNoAbnormalExits */ true, + /*HasNoSideEffects*/ true}; + + 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. + } + + 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) {