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

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


Author: ddunbar
Date: Wed Nov 17 20:36:21 2010
New Revision: 119624

URL: http://llvm.org/viewvc/llvm-project?rev=119624&view=rev
Log:
Merge r119595:
--
Author: Dan Gohman <gohman at apple.com>
Date:   Thu Nov 18 00:34:22 2010 +0000

    Introduce memoization for ScalarEvolution dominates and properlyDominates
    queries, and SCEVExpander getRelevantLoop queries.

Modified:
    llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolution.h
    llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolutionExpander.h
    llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolution.cpp
    llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolutionExpander.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=119624&r1=119623&r2=119624&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:21 2010
@@ -151,6 +151,14 @@
       LoopComputable  ///< The SCEV varies predictably with the loop.
     };
 
+    /// BlockDisposition - An enum describing the relationship between a
+    /// SCEV and a basic block.
+    enum BlockDisposition {
+      DoesNotDominateBlock,  ///< The SCEV does not dominate the block.
+      DominatesBlock,        ///< The SCEV dominates the block.
+      ProperlyDominatesBlock ///< The SCEV properly dominates the block.
+    };
+
   private:
     /// SCEVCallbackVH - A CallbackVH to arrange for ScalarEvolution to be
     /// notified whenever a Value is deleted.
@@ -246,6 +254,13 @@
     /// computeLoopDisposition - Compute a LoopDisposition value.
     LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L);
 
+    /// BlockDispositions - Memoized computeBlockDisposition results.
+    std::map<const SCEV *,
+             std::map<const BasicBlock *, BlockDisposition> > BlockDispositions;
+
+    /// computeBlockDisposition - Compute a BlockDisposition value.
+    BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB);
+
     /// UnsignedRanges - Memoized results from getUnsignedRange
     DenseMap<const SCEV *, ConstantRange> UnsignedRanges;
 
@@ -697,13 +712,17 @@
     /// to compute the value of the expression at any particular loop iteration.
     bool hasComputableLoopEvolution(const SCEV *S, const Loop *L);
 
+    /// getLoopDisposition - Return the "disposition" of the given SCEV with
+    /// respect to the given block.
+    BlockDisposition getBlockDisposition(const SCEV *S, const BasicBlock *BB);
+
     /// dominates - Return true if elements that makes up the given SCEV
     /// dominate the specified basic block.
-    bool dominates(const SCEV *S, BasicBlock *BB) const;
+    bool dominates(const SCEV *S, const BasicBlock *BB);
 
     /// properlyDominates - Return true if elements that makes up the given SCEV
     /// properly dominate the specified basic block.
-    bool properlyDominates(const SCEV *S, BasicBlock *BB) const;
+    bool properlyDominates(const SCEV *S, const BasicBlock *BB);
 
     /// hasOperand - Test whether the given SCEV has Op as a direct or
     /// indirect operand.

Modified: llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolutionExpander.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolutionExpander.h?rev=119624&r1=119623&r2=119624&view=diff
==============================================================================
--- llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolutionExpander.h (original)
+++ llvm/branches/Apple/whitney/include/llvm/Analysis/ScalarEvolutionExpander.h Wed Nov 17 20:36:21 2010
@@ -35,6 +35,9 @@
     std::set<AssertingVH<Value> > InsertedValues;
     std::set<AssertingVH<Value> > InsertedPostIncValues;
 
+    /// RelevantLoops - A memoization of the "relevant" loop for a given SCEV.
+    DenseMap<const SCEV *, const Loop *> RelevantLoops;
+
     /// PostIncLoops - Addrecs referring to any of the given loops are expanded
     /// in post-inc mode. For example, expanding {1,+,1}<L> in post-inc mode
     /// returns the add instruction that adds one to the phi for {0,+,1}<L>,
@@ -168,6 +171,9 @@
       return InsertedValues.count(I) || InsertedPostIncValues.count(I);
     }
 
+    /// getRelevantLoop - Determine the most "relevant" loop for the given SCEV.
+    const Loop *getRelevantLoop(const SCEV *);
+
     Value *visitConstant(const SCEVConstant *S) {
       return S->getValue();
     }

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=119624&r1=119623&r2=119624&view=diff
==============================================================================
--- llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolution.cpp Wed Nov 17 20:36:21 2010
@@ -5782,6 +5782,7 @@
   ConstantEvolutionLoopExitValue.clear();
   ValuesAtScopes.clear();
   LoopDispositions.clear();
+  BlockDispositions.clear();
   UnsignedRanges.clear();
   SignedRanges.clear();
   UniqueSCEVs.clear();
@@ -5982,64 +5983,35 @@
   return getLoopDisposition(S, L) == LoopComputable;
 }
 
-bool ScalarEvolution::dominates(const SCEV *S, BasicBlock *BB) const {
-  switch (S->getSCEVType()) {
-  case scConstant:
-    return true;
-  case scTruncate:
-  case scZeroExtend:
-  case scSignExtend:
-    return dominates(cast<SCEVCastExpr>(S)->getOperand(), BB);
-  case scAddRecExpr: {
-    const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(S);
-    if (!DT->dominates(AR->getLoop()->getHeader(), BB))
-      return false;
-  }
-  // FALL THROUGH into SCEVNAryExpr handling.
-  case scAddExpr:
-  case scMulExpr:
-  case scUMaxExpr:
-  case scSMaxExpr: {
-    const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S);
-    for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end();
-         I != E; ++I)
-      if (!dominates(*I, BB))
-        return false;
-    return true;
-  }
-  case scUDivExpr: {
-    const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S);
-    return dominates(UDiv->getLHS(), BB) && dominates(UDiv->getRHS(), BB);
-  }
-  case scUnknown:
-    if (Instruction *I =
-          dyn_cast<Instruction>(cast<SCEVUnknown>(S)->getValue()))
-      return DT->dominates(I->getParent(), BB);
-    return true;
-  case scCouldNotCompute:
-    llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
-    return false;
-  default: break;
-  }
-  llvm_unreachable("Unknown SCEV kind!");
-  return false;
+ScalarEvolution::BlockDisposition
+ScalarEvolution::getBlockDisposition(const SCEV *S, const BasicBlock *BB) {
+  std::map<const BasicBlock *, BlockDisposition> &Values = BlockDispositions[S];
+  std::pair<std::map<const BasicBlock *, BlockDisposition>::iterator, bool>
+    Pair = Values.insert(std::make_pair(BB, DoesNotDominateBlock));
+  if (!Pair.second)
+    return Pair.first->second;
+
+  BlockDisposition D = computeBlockDisposition(S, BB);
+  return BlockDispositions[S][BB] = D;
 }
 
-bool ScalarEvolution::properlyDominates(const SCEV *S, BasicBlock *BB) const {
+ScalarEvolution::BlockDisposition
+ScalarEvolution::computeBlockDisposition(const SCEV *S, const BasicBlock *BB) {
   switch (S->getSCEVType()) {
   case scConstant:
-    return true;
+    return ProperlyDominatesBlock;
   case scTruncate:
   case scZeroExtend:
   case scSignExtend:
-    return properlyDominates(cast<SCEVCastExpr>(S)->getOperand(), BB);
+    return getBlockDisposition(cast<SCEVCastExpr>(S)->getOperand(), BB);
   case scAddRecExpr: {
     // This uses a "dominates" query instead of "properly dominates" query
-    // because the instruction which produces the addrec's value is a PHI, and
-    // a PHI effectively properly dominates its entire containing block.
+    // to test for proper dominance too, because the instruction which
+    // produces the addrec's value is a PHI, and a PHI effectively properly
+    // dominates its entire containing block.
     const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(S);
     if (!DT->dominates(AR->getLoop()->getHeader(), BB))
-      return false;
+      return DoesNotDominateBlock;
   }
   // FALL THROUGH into SCEVNAryExpr handling.
   case scAddExpr:
@@ -6047,29 +6019,54 @@
   case scUMaxExpr:
   case scSMaxExpr: {
     const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S);
+    bool Proper = true;
     for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end();
-         I != E; ++I)
-      if (!properlyDominates(*I, BB))
-        return false;
-    return true;
+         I != E; ++I) {
+      BlockDisposition D = getBlockDisposition(*I, BB);
+      if (D == DoesNotDominateBlock)
+        return DoesNotDominateBlock;
+      if (D == DominatesBlock)
+        Proper = false;
+    }
+    return Proper ? ProperlyDominatesBlock : DominatesBlock;
   }
   case scUDivExpr: {
     const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S);
-    return properlyDominates(UDiv->getLHS(), BB) &&
-           properlyDominates(UDiv->getRHS(), BB);
+    const SCEV *LHS = UDiv->getLHS(), *RHS = UDiv->getRHS();
+    BlockDisposition LD = getBlockDisposition(LHS, BB);
+    if (LD == DoesNotDominateBlock)
+      return DoesNotDominateBlock;
+    BlockDisposition RD = getBlockDisposition(RHS, BB);
+    if (RD == DoesNotDominateBlock)
+      return DoesNotDominateBlock;
+    return (LD == ProperlyDominatesBlock && RD == ProperlyDominatesBlock) ?
+      ProperlyDominatesBlock : DominatesBlock;
   }
   case scUnknown:
     if (Instruction *I =
-          dyn_cast<Instruction>(cast<SCEVUnknown>(S)->getValue()))
-      return DT->properlyDominates(I->getParent(), BB);
-    return true;
+          dyn_cast<Instruction>(cast<SCEVUnknown>(S)->getValue())) {
+      if (I->getParent() == BB)
+        return DominatesBlock;
+      if (DT->properlyDominates(I->getParent(), BB))
+        return ProperlyDominatesBlock;
+      return DoesNotDominateBlock;
+    }
+    return ProperlyDominatesBlock;
   case scCouldNotCompute:
     llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
-    return false;
+    return DoesNotDominateBlock;
   default: break;
   }
   llvm_unreachable("Unknown SCEV kind!");
-  return false;
+  return DoesNotDominateBlock;
+}
+
+bool ScalarEvolution::dominates(const SCEV *S, const BasicBlock *BB) {
+  return getBlockDisposition(S, BB) >= DominatesBlock;
+}
+
+bool ScalarEvolution::properlyDominates(const SCEV *S, const BasicBlock *BB) {
+  return getBlockDisposition(S, BB) == ProperlyDominatesBlock;
 }
 
 bool ScalarEvolution::hasOperand(const SCEV *S, const SCEV *Op) const {
@@ -6117,6 +6114,7 @@
 void ScalarEvolution::forgetMemoizedResults(const SCEV *S) {
   ValuesAtScopes.erase(S);
   LoopDispositions.erase(S);
+  BlockDispositions.erase(S);
   UnsignedRanges.erase(S);
   SignedRanges.erase(S);
 }

Modified: llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolutionExpander.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolutionExpander.cpp?rev=119624&r1=119623&r2=119624&view=diff
==============================================================================
--- llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolutionExpander.cpp (original)
+++ llvm/branches/Apple/whitney/lib/Analysis/ScalarEvolutionExpander.cpp Wed Nov 17 20:36:21 2010
@@ -608,15 +608,22 @@
   return A; // Arbitrarily break the tie.
 }
 
-/// GetRelevantLoop - Get the most relevant loop associated with the given
+/// getRelevantLoop - Get the most relevant loop associated with the given
 /// expression, according to PickMostRelevantLoop.
-static const Loop *GetRelevantLoop(const SCEV *S, LoopInfo &LI,
-                                   DominatorTree &DT) {
+const Loop *SCEVExpander::getRelevantLoop(const SCEV *S) {
+  // Test whether we've already computed the most relevant loop for this SCEV.
+  std::pair<DenseMap<const SCEV *, const Loop *>::iterator, bool> Pair =
+    RelevantLoops.insert(std::make_pair(S, static_cast<const Loop *>(0)));
+  if (!Pair.second)
+    return Pair.first->second;
+
   if (isa<SCEVConstant>(S))
+    // A constant has no relevant loops.
     return 0;
   if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) {
     if (const Instruction *I = dyn_cast<Instruction>(U->getValue()))
-      return LI.getLoopFor(I->getParent());
+      return Pair.first->second = SE.LI->getLoopFor(I->getParent());
+    // A non-instruction has no relevant loops.
     return 0;
   }
   if (const SCEVNAryExpr *N = dyn_cast<SCEVNAryExpr>(S)) {
@@ -625,16 +632,22 @@
       L = AR->getLoop();
     for (SCEVNAryExpr::op_iterator I = N->op_begin(), E = N->op_end();
          I != E; ++I)
-      L = PickMostRelevantLoop(L, GetRelevantLoop(*I, LI, DT), DT);
-    return L;
+      L = PickMostRelevantLoop(L, getRelevantLoop(*I), *SE.DT);
+    return RelevantLoops[N] = L;
+  }
+  if (const SCEVCastExpr *C = dyn_cast<SCEVCastExpr>(S)) {
+    const Loop *Result = getRelevantLoop(C->getOperand());
+    return RelevantLoops[C] = Result;
+  }
+  if (const SCEVUDivExpr *D = dyn_cast<SCEVUDivExpr>(S)) {
+    const Loop *Result =
+      PickMostRelevantLoop(getRelevantLoop(D->getLHS()),
+                           getRelevantLoop(D->getRHS()),
+                           *SE.DT);
+    return RelevantLoops[D] = Result;
   }
-  if (const SCEVCastExpr *C = dyn_cast<SCEVCastExpr>(S))
-    return GetRelevantLoop(C->getOperand(), LI, DT);
-  if (const SCEVUDivExpr *D = dyn_cast<SCEVUDivExpr>(S))
-    return PickMostRelevantLoop(GetRelevantLoop(D->getLHS(), LI, DT),
-                                GetRelevantLoop(D->getRHS(), LI, DT),
-                                DT);
   llvm_unreachable("Unexpected SCEV type!");
+  return 0;
 }
 
 namespace {
@@ -682,8 +695,7 @@
   SmallVector<std::pair<const Loop *, const SCEV *>, 8> OpsAndLoops;
   for (std::reverse_iterator<SCEVAddExpr::op_iterator> I(S->op_end()),
        E(S->op_begin()); I != E; ++I)
-    OpsAndLoops.push_back(std::make_pair(GetRelevantLoop(*I, *SE.LI, *SE.DT),
-                                         *I));
+    OpsAndLoops.push_back(std::make_pair(getRelevantLoop(*I), *I));
 
   // Sort by loop. Use a stable sort so that constants follow non-constants and
   // pointer operands precede non-pointer operands.
@@ -752,8 +764,7 @@
   SmallVector<std::pair<const Loop *, const SCEV *>, 8> OpsAndLoops;
   for (std::reverse_iterator<SCEVMulExpr::op_iterator> I(S->op_end()),
        E(S->op_begin()); I != E; ++I)
-    OpsAndLoops.push_back(std::make_pair(GetRelevantLoop(*I, *SE.LI, *SE.DT),
-                                         *I));
+    OpsAndLoops.push_back(std::make_pair(getRelevantLoop(*I), *I));
 
   // Sort by loop. Use a stable sort so that constants follow non-constants.
   std::stable_sort(OpsAndLoops.begin(), OpsAndLoops.end(), LoopCompare(*SE.DT));





More information about the llvm-branch-commits mailing list