[llvm-branch-commits] [llvm-branch] r119622 - in /llvm/branches/Apple/whitney: include/llvm/Analysis/ScalarEvolution.h lib/Analysis/ScalarEvolution.cpp

Daniel Dunbar daniel at zuster.org
Wed Nov 17 18:36:14 PST 2010


Author: ddunbar
Date: Wed Nov 17 20:36:14 2010
New Revision: 119622

URL: http://llvm.org/viewvc/llvm-project?rev=119622&view=rev
Log:
Merge r119584:
--
Author: Dan Gohman <gohman at apple.com>
Date:   Wed Nov 17 23:21:44 2010 +0000

    Merge the implementations of isLoopInvariant and hasComputableLoopEvolution, and
    memoize the results. This improves compile time in code which highly complex
    expressions which get queried many times.

Modified:
    llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolution.h
    llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolution.cpp

Modified: llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolution.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolution.h?rev=119622&r1=119621&r2=119622&view=diff
==============================================================================
--- llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolution.h (original)
+++ llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolution.h Wed Nov 17 20:36:14 2010
@@ -142,6 +142,16 @@
   /// they must ask this class for services.
   ///
   class ScalarEvolution : public FunctionPass {
+  public:
+    /// LoopDisposition - An enum describing the relationship between a
+    /// SCEV and a loop.
+    enum LoopDisposition {
+      LoopVariant,    ///< The SCEV is loop-variant (unknown).
+      LoopInvariant,  ///< The SCEV is loop-invariant.
+      LoopComputable  ///< The SCEV varies predictably with the loop.
+    };
+
+  private:
     /// SCEVCallbackVH - A CallbackVH to arrange for ScalarEvolution to be
     /// notified whenever a Value is deleted.
     class SCEVCallbackVH : public CallbackVH {
@@ -229,6 +239,13 @@
     std::map<const SCEV *,
              std::map<const Loop *, const SCEV *> > ValuesAtScopes;
 
+    /// LoopDispositions - Memoized computeLoopDisposition results.
+    std::map<const SCEV *,
+             std::map<const Loop *, LoopDisposition> > LoopDispositions;
+
+    /// computeLoopDisposition - Compute a LoopDisposition value.
+    LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L);
+
     /// UnsignedRanges - Memoized results from getUnsignedRange
     DenseMap<const SCEV *, ConstantRange> UnsignedRanges;
 
@@ -663,6 +680,10 @@
                               const SCEV *&LHS,
                               const SCEV *&RHS);
 
+    /// getLoopDisposition - Return the "disposition" of the given SCEV with
+    /// respect to the given loop.
+    LoopDisposition getLoopDisposition(const SCEV *S, const Loop *L);
+
     /// isLoopInvariant - Return true if the value of the given SCEV is
     /// unchanging in the specified loop.
     bool isLoopInvariant(const SCEV *S, const Loop *L);

Modified: llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolution.cpp?rev=119622&r1=119621&r2=119622&view=diff
==============================================================================
--- llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolution.cpp Wed Nov 17 20:36:14 2010
@@ -325,6 +325,7 @@
 void SCEVUnknown::deleted() {
   // Clear this SCEVUnknown from various maps.
   SE->ValuesAtScopes.erase(this);
+  SE->LoopDispositions.erase(this);
   SE->UnsignedRanges.erase(this);
   SE->SignedRanges.erase(this);
 
@@ -338,6 +339,7 @@
 void SCEVUnknown::allUsesReplacedWith(Value *New) {
   // Clear this SCEVUnknown from various maps.
   SE->ValuesAtScopes.erase(this);
+  SE->LoopDispositions.erase(this);
   SE->UnsignedRanges.erase(this);
   SE->SignedRanges.erase(this);
 
@@ -2634,6 +2636,7 @@
           !isa<SCEVUnknown>(Old) ||
           (I != PN && Old == SymName)) {
         ValuesAtScopes.erase(Old);
+        LoopDispositions.erase(Old);
         UnsignedRanges.erase(Old);
         SignedRanges.erase(Old);
         ValueExprMap.erase(It);
@@ -3667,6 +3670,7 @@
           // own when it gets to that point.
           if (!isa<PHINode>(I) || !isa<SCEVUnknown>(Old)) {
             ValuesAtScopes.erase(Old);
+            LoopDispositions.erase(Old);
             UnsignedRanges.erase(Old);
             SignedRanges.erase(Old);
             ValueExprMap.erase(It);
@@ -3702,6 +3706,7 @@
     if (It != ValueExprMap.end()) {
       const SCEV *Old = It->second;
       ValuesAtScopes.erase(Old);
+      LoopDispositions.erase(Old);
       UnsignedRanges.erase(Old);
       SignedRanges.erase(Old);
       ValueExprMap.erase(It);
@@ -3738,6 +3743,7 @@
     if (It != ValueExprMap.end()) {
       const SCEV *Old = It->second;
       ValuesAtScopes.erase(Old);
+      LoopDispositions.erase(Old);
       UnsignedRanges.erase(Old);
       SignedRanges.erase(Old);
       ValueExprMap.erase(It);
@@ -5795,6 +5801,7 @@
   BackedgeTakenCounts.clear();
   ConstantEvolutionLoopExitValue.clear();
   ValuesAtScopes.clear();
+  LoopDispositions.clear();
   UnsignedRanges.clear();
   SignedRanges.clear();
   UniqueSCEVs.clear();
@@ -5893,54 +5900,82 @@
     PrintLoopInfo(OS, &SE, *I);
 }
 
-bool ScalarEvolution::isLoopInvariant(const SCEV *S, const Loop *L) {
+ScalarEvolution::LoopDisposition
+ScalarEvolution::getLoopDisposition(const SCEV *S, const Loop *L) {
+  std::map<const Loop *, LoopDisposition> &Values = LoopDispositions[S];
+  std::pair<std::map<const Loop *, LoopDisposition>::iterator, bool> Pair =
+    Values.insert(std::make_pair(L, LoopVariant));
+  if (!Pair.second)
+    return Pair.first->second;
+
+  LoopDisposition D = computeLoopDisposition(S, L);
+  return LoopDispositions[S][L] = D;
+}
+
+ScalarEvolution::LoopDisposition
+ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) {
   switch (S->getSCEVType()) {
   case scConstant:
-    return true;
+    return LoopInvariant;
   case scTruncate:
   case scZeroExtend:
   case scSignExtend:
-    return isLoopInvariant(cast<SCEVCastExpr>(S)->getOperand(), L);
+    return getLoopDisposition(cast<SCEVCastExpr>(S)->getOperand(), L);
   case scAddRecExpr: {
     const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(S);
 
+    // If L is the addrec's loop, it's computable.
+    if (AR->getLoop() == L)
+      return LoopComputable;
+
     // Add recurrences are never invariant in the function-body (null loop).
     if (!L)
-      return false;
+      return LoopVariant;
 
     // This recurrence is variant w.r.t. L if L contains AR's loop.
     if (L->contains(AR->getLoop()))
-      return false;
+      return LoopVariant;
 
     // This recurrence is invariant w.r.t. L if AR's loop contains L.
     if (AR->getLoop()->contains(L))
-      return true;
+      return LoopInvariant;
 
     // This recurrence is variant w.r.t. L if any of its operands
     // are variant.
     for (SCEVAddRecExpr::op_iterator I = AR->op_begin(), E = AR->op_end();
          I != E; ++I)
       if (!isLoopInvariant(*I, L))
-        return false;
+        return LoopVariant;
 
     // Otherwise it's loop-invariant.
-    return true;
+    return LoopInvariant;
   }
   case scAddExpr:
   case scMulExpr:
   case scUMaxExpr:
   case scSMaxExpr: {
     const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S);
+    bool HasVarying = false;
     for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end();
-         I != E; ++I)
-      if (!isLoopInvariant(*I, L))
-        return false;
-    return true;
+         I != E; ++I) {
+      LoopDisposition D = getLoopDisposition(*I, L);
+      if (D == LoopVariant)
+        return LoopVariant;
+      if (D == LoopComputable)
+        HasVarying = true;
+    }
+    return HasVarying ? LoopComputable : LoopInvariant;
   }
   case scUDivExpr: {
     const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S);
-    return isLoopInvariant(UDiv->getLHS(), L) &&
-           isLoopInvariant(UDiv->getRHS(), L);
+    LoopDisposition LD = getLoopDisposition(UDiv->getLHS(), L);
+    if (LD == LoopVariant)
+      return LoopVariant;
+    LoopDisposition RD = getLoopDisposition(UDiv->getRHS(), L);
+    if (RD == LoopVariant)
+      return LoopVariant;
+    return (LD == LoopInvariant && RD == LoopInvariant) ?
+           LoopInvariant : LoopComputable;
   }
   case scUnknown:
     // All non-instruction values are loop invariant.  All instructions are loop
@@ -5948,71 +5983,23 @@
     // Instructions are never considered invariant in the function body
     // (null loop) because they are defined within the "loop".
     if (Instruction *I = dyn_cast<Instruction>(cast<SCEVUnknown>(S)->getValue()))
-      return L && !L->contains(I);
-    return true;
+      return (L && !L->contains(I)) ? LoopInvariant : LoopVariant;
+    return LoopInvariant;
   case scCouldNotCompute:
     llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
-    return false;
+    return LoopVariant;
   default: break;
   }
   llvm_unreachable("Unknown SCEV kind!");
-  return false;
+  return LoopVariant;
+}
+
+bool ScalarEvolution::isLoopInvariant(const SCEV *S, const Loop *L) {
+  return getLoopDisposition(S, L) == LoopInvariant;
 }
 
 bool ScalarEvolution::hasComputableLoopEvolution(const SCEV *S, const Loop *L) {
-  switch (S->getSCEVType()) {
-  case scConstant:
-    return false;
-  case scTruncate:
-  case scZeroExtend:
-  case scSignExtend:
-    return hasComputableLoopEvolution(cast<SCEVCastExpr>(S)->getOperand(), L);
-  case scAddRecExpr:
-    return cast<SCEVAddRecExpr>(S)->getLoop() == L;
-  case scAddExpr:
-  case scMulExpr:
-  case scUMaxExpr:
-  case scSMaxExpr: {
-    const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S);
-    bool HasVarying = false;
-    for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end();
-         I != E; ++I) {
-      const SCEV *Op = *I;
-      if (!isLoopInvariant(Op, L)) {
-        if (hasComputableLoopEvolution(Op, L))
-          HasVarying = true;
-        else
-          return false;
-      }
-    }
-    return HasVarying;
-  }
-  case scUDivExpr: {
-    const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S);
-    bool HasVarying = false;
-    if (!isLoopInvariant(UDiv->getLHS(), L)) {
-      if (hasComputableLoopEvolution(UDiv->getLHS(), L))
-        HasVarying = true;
-      else
-        return false;
-    }
-    if (!isLoopInvariant(UDiv->getRHS(), L)) {
-      if (hasComputableLoopEvolution(UDiv->getRHS(), L))
-        HasVarying = true;
-      else
-        return false;
-    }
-    return HasVarying;
-  }
-  case scUnknown:
-    return false;
-  case scCouldNotCompute:
-    llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
-    return false;
-  default: break;
-  }
-  llvm_unreachable("Unknown SCEV kind!");
-  return false;
+  return getLoopDisposition(S, L) == LoopComputable;
 }
 
 bool ScalarEvolution::dominates(const SCEV *S, BasicBlock *BB) const {





More information about the llvm-branch-commits mailing list