From d1eb62ad11273c05f5aee59927331139930e16f2 Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Sun, 25 Sep 2016 23:12:00 +0000 Subject: [PATCH] [SCEV] Simplify tracking ExitNotTakenInfo instances; NFC This change simplifies a data structure optimization in the `BackedgeTakenInfo` class for loops with exactly one computable exit. I've sanity checked that this does not regress compile time performance, using sqlite3's amalgamated build. llvm-svn: 282365 --- llvm/include/llvm/Analysis/ScalarEvolution.h | 143 +++---------------- llvm/lib/Analysis/ScalarEvolution.cpp | 96 ++++--------- 2 files changed, 46 insertions(+), 193 deletions(-) diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h index 94de390ddf10..0c615d150eb2 100644 --- a/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -574,143 +574,44 @@ private: } }; - /// Forward declaration of ExitNotTakenExtras - struct ExitNotTakenExtras; + typedef std::pair EdgeExitInfo; /// Information about the number of times a particular loop exit may be /// reached before exiting the loop. struct ExitNotTakenInfo { AssertingVH ExitingBlock; const SCEV *ExactNotTaken; - - ExitNotTakenExtras *ExtraInfo; - bool Complete; - - ExitNotTakenInfo() - : ExitingBlock(nullptr), ExactNotTaken(nullptr), ExtraInfo(nullptr), - Complete(true) {} - - ExitNotTakenInfo(BasicBlock *ExitBlock, const SCEV *Expr, - ExitNotTakenExtras *Ptr) - : ExitingBlock(ExitBlock), ExactNotTaken(Expr), ExtraInfo(Ptr), - Complete(true) {} - - /// Return true if all loop exits are computable. - bool isCompleteList() const { return Complete; } - - /// Sets the incomplete property, indicating that one of the loop exits - /// doesn't have a corresponding ExitNotTakenInfo entry. - void setIncomplete() { Complete = false; } - - /// Returns a pointer to the predicate associated with this information, - /// or nullptr if this doesn't exist (meaning always true). - SCEVUnionPredicate *getPred() const { - if (ExtraInfo) - return &ExtraInfo->Pred; - - return nullptr; - } - - /// Return true if the SCEV predicate associated with this information - /// is always true. - bool hasAlwaysTruePred() const { - return !getPred() || getPred()->isAlwaysTrue(); - } - - /// Defines a simple forward iterator for ExitNotTakenInfo. - class ExitNotTakenInfoIterator - : public std::iterator { - const ExitNotTakenInfo *Start; - unsigned Position; - - public: - ExitNotTakenInfoIterator(const ExitNotTakenInfo *Start, unsigned Position) - : Start(Start), Position(Position) {} - - const ExitNotTakenInfo &operator*() const { - if (Position == 0) - return *Start; - - return Start->ExtraInfo->Exits[Position - 1]; - } - - const ExitNotTakenInfo *operator->() const { - if (Position == 0) - return Start; - - return &Start->ExtraInfo->Exits[Position - 1]; - } - - bool operator==(const ExitNotTakenInfoIterator &RHS) const { - return Start == RHS.Start && Position == RHS.Position; - } - - bool operator!=(const ExitNotTakenInfoIterator &RHS) const { - return Start != RHS.Start || Position != RHS.Position; - } - - ExitNotTakenInfoIterator &operator++() { // Preincrement - if (!Start) - return *this; - - unsigned Elements = - Start->ExtraInfo ? Start->ExtraInfo->Exits.size() + 1 : 1; - - ++Position; - - // We've run out of elements. - if (Position == Elements) { - Start = nullptr; - Position = 0; - } - - return *this; - } - ExitNotTakenInfoIterator operator++(int) { // Postincrement - ExitNotTakenInfoIterator Tmp = *this; - ++*this; - return Tmp; - } - }; - - /// Iterators - ExitNotTakenInfoIterator begin() const { - return ExitNotTakenInfoIterator(this, 0); - } - ExitNotTakenInfoIterator end() const { - return ExitNotTakenInfoIterator(nullptr, 0); + SCEVUnionPredicate Predicate; + bool hasAlwaysTruePredicate() const { + return Predicate.isAlwaysTrue(); } }; - /// Describes the extra information that a ExitNotTakenInfo can have. - struct ExitNotTakenExtras { - /// The predicate associated with the ExitNotTakenInfo struct. - SCEVUnionPredicate Pred; - - /// The extra exits in the loop. Only the ExitNotTakenExtras structure - /// pointed to by the first ExitNotTakenInfo struct (associated with the - /// first loop exit) will populate this vector to prevent having - /// redundant information. - SmallVector Exits; - }; - - typedef std::pair EdgeExitInfo; - /// Information about the backedge-taken count of a loop. This currently /// includes an exact count and a maximum count. /// class BackedgeTakenInfo { /// A list of computable exits and their not-taken counts. Loops almost /// never have more than one computable exit. - ExitNotTakenInfo ExitNotTaken; + SmallVector ExitNotTaken; - /// An expression indicating the least maximum backedge-taken count of the - /// loop that is known, or a SCEVCouldNotCompute. This expression is only - /// valid if the predicates associated with all loop exits are true. - const SCEV *Max; + /// The pointer part of \c MaxAndComplete is an expression indicating the + /// least maximum backedge-taken count of the loop that is known, or a + /// SCEVCouldNotCompute. This expression is only valid if the predicates + /// associated with all loop exits are true. + /// + /// The integer part of \c MaxAndComplete is a boolean indicating if \c + /// ExitNotTaken has an element for every exiting block in the loop. + PointerIntPair MaxAndComplete; + + /// \name Helper projection functions on \c MaxAndComplete. + /// @{ + bool isComplete() const { return MaxAndComplete.getInt(); } + const SCEV *getMax() const { return MaxAndComplete.getPointer(); } + /// @} public: - BackedgeTakenInfo() : Max(nullptr) {} + BackedgeTakenInfo() : MaxAndComplete(nullptr, 0) {} /// Initialize BackedgeTakenInfo from a list of exact exit counts. BackedgeTakenInfo(ArrayRef ExitCounts, bool Complete, @@ -719,11 +620,11 @@ private: /// Test whether this BackedgeTakenInfo contains any computed information, /// or whether it's all SCEVCouldNotCompute values. bool hasAnyInfo() const { - return ExitNotTaken.ExitingBlock || !isa(Max); + return !ExitNotTaken.empty() || !isa(getMax()); } /// Test whether this BackedgeTakenInfo contains complete information. - bool hasFullInfo() const { return ExitNotTaken.isCompleteList(); } + bool hasFullInfo() const { return isComplete(); } /// Return an expression indicating the exact backedge-taken count of the /// loop if it is known or SCEVCouldNotCompute otherwise. This is the diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index a7e6d231db1c..32ef53f4c9c9 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -5601,14 +5601,11 @@ void ScalarEvolution::forgetValue(Value *V) { /// caller's responsibility to specify the relevant loop exit using /// getExact(ExitingBlock, SE). const SCEV * -ScalarEvolution::BackedgeTakenInfo::getExact( - ScalarEvolution *SE, SCEVUnionPredicate *Preds) const { +ScalarEvolution::BackedgeTakenInfo::getExact(ScalarEvolution *SE, + SCEVUnionPredicate *Preds) const { // If any exits were not computable, the loop is not computable. - if (!ExitNotTaken.isCompleteList()) return SE->getCouldNotCompute(); - - // We need exactly one computable exit. - if (!ExitNotTaken.ExitingBlock) return SE->getCouldNotCompute(); - assert(ExitNotTaken.ExactNotTaken && "uninitialized not-taken info"); + if (!isComplete() || ExitNotTaken.empty()) + return SE->getCouldNotCompute(); const SCEV *BECount = nullptr; for (auto &ENT : ExitNotTaken) { @@ -5618,10 +5615,10 @@ ScalarEvolution::BackedgeTakenInfo::getExact( BECount = ENT.ExactNotTaken; else if (BECount != ENT.ExactNotTaken) return SE->getCouldNotCompute(); - if (Preds && ENT.getPred()) - Preds->add(ENT.getPred()); + if (Preds) + Preds->add(&ENT.Predicate); - assert((Preds || ENT.hasAlwaysTruePred()) && + assert((Preds || ENT.hasAlwaysTruePredicate()) && "Predicate should be always true!"); } @@ -5634,7 +5631,7 @@ const SCEV * ScalarEvolution::BackedgeTakenInfo::getExact(BasicBlock *ExitingBlock, ScalarEvolution *SE) const { for (auto &ENT : ExitNotTaken) - if (ENT.ExitingBlock == ExitingBlock && ENT.hasAlwaysTruePred()) + if (ENT.ExitingBlock == ExitingBlock && ENT.hasAlwaysTruePredicate()) return ENT.ExactNotTaken; return SE->getCouldNotCompute(); @@ -5643,21 +5640,22 @@ ScalarEvolution::BackedgeTakenInfo::getExact(BasicBlock *ExitingBlock, /// getMax - Get the max backedge taken count for the loop. const SCEV * ScalarEvolution::BackedgeTakenInfo::getMax(ScalarEvolution *SE) const { + // TODO: use any_of for (auto &ENT : ExitNotTaken) - if (!ENT.hasAlwaysTruePred()) + if (!ENT.hasAlwaysTruePredicate()) return SE->getCouldNotCompute(); - return Max ? Max : SE->getCouldNotCompute(); + if (auto *Max = getMax()) + return Max; + return SE->getCouldNotCompute(); } bool ScalarEvolution::BackedgeTakenInfo::hasOperand(const SCEV *S, ScalarEvolution *SE) const { - if (Max && Max != SE->getCouldNotCompute() && SE->hasOperand(Max, S)) + if (getMax() && getMax() != SE->getCouldNotCompute() && + SE->hasOperand(getMax(), S)) return true; - if (!ExitNotTaken.ExitingBlock) - return false; - for (auto &ENT : ExitNotTaken) if (ENT.ExactNotTaken != SE->getCouldNotCompute() && SE->hasOperand(ENT.ExactNotTaken, S)) @@ -5671,65 +5669,19 @@ bool ScalarEvolution::BackedgeTakenInfo::hasOperand(const SCEV *S, ScalarEvolution::BackedgeTakenInfo::BackedgeTakenInfo( ArrayRef ExitCounts, bool Complete, const SCEV *MaxCount) - : Max(MaxCount) { - - if (!Complete) - ExitNotTaken.setIncomplete(); - - unsigned NumExits = ExitCounts.size(); - if (NumExits == 0) - return; - - ExitNotTaken.ExitingBlock = ExitCounts[0].first; - ExitNotTaken.ExactNotTaken = ExitCounts[0].second.ExactNotTaken; - - // Determine the number of ExitNotTakenExtras structures that we need. - unsigned ExtraInfoSize = 0; - if (NumExits > 1) { - auto HasNonTrivialPredicate = - [](const ScalarEvolution::EdgeExitInfo &Entry) { - return !Entry.second.Predicate.isAlwaysTrue(); - }; - ExtraInfoSize = 1 + std::count_if(std::next(ExitCounts.begin()), - ExitCounts.end(), HasNonTrivialPredicate); - } else if (!ExitCounts[0].second.Predicate.isAlwaysTrue()) - ExtraInfoSize = 1; - - ExitNotTakenExtras *ENT = nullptr; - - // Allocate the ExitNotTakenExtras structures and initialize the first - // element (ExitNotTaken). - if (ExtraInfoSize > 0) { - ENT = new ExitNotTakenExtras[ExtraInfoSize]; - ExitNotTaken.ExtraInfo = &ENT[0]; - *ExitNotTaken.getPred() = std::move(ExitCounts[0].second.Predicate); - } - - if (NumExits == 1) - return; - - assert(ENT && "ExitNotTakenExtras is NULL while having more than one exit"); - - auto &Exits = ExitNotTaken.ExtraInfo->Exits; - - // Handle the rare case of multiple computable exits. - for (unsigned i = 1, PredPos = 1; i < NumExits; ++i) { - ExitNotTakenExtras *Ptr = nullptr; - if (!ExitCounts[i].second.Predicate.isAlwaysTrue()) { - Ptr = &ENT[PredPos++]; - Ptr->Pred = std::move(ExitCounts[i].second.Predicate); - } - - Exits.emplace_back(ExitCounts[i].first, ExitCounts[i].second.ExactNotTaken, - Ptr); - } + : MaxAndComplete(MaxCount, Complete) { + std::transform(ExitCounts.begin(), ExitCounts.end(), + std::back_inserter(ExitNotTaken), + [&](const ScalarEvolution::EdgeExitInfo &EEI) { + BasicBlock *ExitBB = EEI.first; + const ExitLimit &EL = EEI.second; + return ExitNotTakenInfo({ExitBB, EL.ExactNotTaken, EL.Predicate}); + }); } /// Invalidate this result and free the ExitNotTakenInfo array. void ScalarEvolution::BackedgeTakenInfo::clear() { - ExitNotTaken.ExitingBlock = nullptr; - ExitNotTaken.ExactNotTaken = nullptr; - delete[] ExitNotTaken.ExtraInfo; + ExitNotTaken.clear(); } /// Compute the number of times the backedge of the specified loop will execute.