[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