[llvm] r282365 - [SCEV] Simplify tracking ExitNotTakenInfo instances; NFC
Sanjoy Das via llvm-commits
llvm-commits at lists.llvm.org
Sun Sep 25 16:12:01 PDT 2016
Author: sanjoy
Date: Sun Sep 25 18:12:00 2016
New Revision: 282365
URL: http://llvm.org/viewvc/llvm-project?rev=282365&view=rev
Log:
[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.
Modified:
llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
llvm/trunk/lib/Analysis/ScalarEvolution.cpp
Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=282365&r1=282364&r2=282365&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Sun Sep 25 18:12:00 2016
@@ -574,143 +574,44 @@ private:
}
};
- /// Forward declaration of ExitNotTakenExtras
- struct ExitNotTakenExtras;
+ typedef std::pair<BasicBlock *, ExitLimit> EdgeExitInfo;
/// Information about the number of times a particular loop exit may be
/// reached before exiting the loop.
struct ExitNotTakenInfo {
AssertingVH<BasicBlock> 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;
+ SCEVUnionPredicate Predicate;
+ bool hasAlwaysTruePredicate() const {
+ return Predicate.isAlwaysTrue();
}
-
- /// 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<std::forward_iterator_tag, ExitNotTakenInfo> {
- 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);
- }
- };
-
- /// 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<ExitNotTakenInfo, 4> Exits;
};
- typedef std::pair<BasicBlock *, ExitLimit> 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<ExitNotTakenInfo, 1> 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<const SCEV *, 1> 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<EdgeExitInfo> 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<SCEVCouldNotCompute>(Max);
+ return !ExitNotTaken.empty() || !isa<SCEVCouldNotCompute>(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
Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=282365&r1=282364&r2=282365&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Sun Sep 25 18:12:00 2016
@@ -5601,14 +5601,11 @@ void ScalarEvolution::forgetValue(Value
/// 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::getE
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::getE
/// 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:
ScalarEvolution::BackedgeTakenInfo::BackedgeTakenInfo(
ArrayRef<ScalarEvolution::EdgeExitInfo> 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.
More information about the llvm-commits
mailing list