Add memoization for getSCEVAtScope results for instructions
authorDan Gohman <gohman@apple.com>
Fri, 8 May 2009 20:47:27 +0000 (20:47 +0000)
committerDan Gohman <gohman@apple.com>
Fri, 8 May 2009 20:47:27 +0000 (20:47 +0000)
which are not analyzed with SCEV techniques, which can require
brute-forcing through a large number of instructions. This
fixes a massive compile-time issue on 400.perlbench (in
particular, the loop in MD5Transform).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@71259 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/ScalarEvolution.h
lib/Analysis/ScalarEvolution.cpp

index d6fb8f011b88427ae53605135bbba6f87f8b97ab..c9a80b74a2d182056e3a366bc1c635f9db0526f5 100644 (file)
@@ -271,6 +271,11 @@ namespace llvm {
     /// exit value.
     std::map<PHINode*, Constant*> ConstantEvolutionLoopExitValue;
 
+    /// ValuesAtScopes - This map contains entries for all the instructions
+    /// that we attempt to compute getSCEVAtScope information for without
+    /// using SCEV techniques, which can be expensive.
+    std::map<Instruction *, std::map<const Loop *, Constant *> > ValuesAtScopes;
+
     /// createSCEV - We know that there is no SCEV for the specified value.
     /// Analyze the expression.
     SCEVHandle createSCEV(Value *V);
index 8b48b78da41795078830bb1b01facc783b9a3101..4ddde5db5ed108af6623e7fa8388fef5b6387fc8 100644 (file)
@@ -2766,6 +2766,13 @@ SCEVHandle ScalarEvolution::getSCEVAtScope(const SCEV *V, const Loop *L) {
       // the arguments into constants, and if so, try to constant propagate the
       // result.  This is particularly useful for computing loop exit values.
       if (CanConstantFold(I)) {
+        // Check to see if we've folded this instruction at this loop before.
+        std::map<const Loop *, Constant *> &Values = ValuesAtScopes[I];
+        std::pair<std::map<const Loop *, Constant *>::iterator, bool> Pair =
+          Values.insert(std::make_pair(L, static_cast<Constant *>(0)));
+        if (!Pair.second)
+          return Pair.first->second ? &*getUnknown(Pair.first->second) : V;
+
         std::vector<Constant*> Operands;
         Operands.reserve(I->getNumOperands());
         for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
@@ -2812,6 +2819,7 @@ SCEVHandle ScalarEvolution::getSCEVAtScope(const SCEV *V, const Loop *L) {
         else
           C = ConstantFoldInstOperands(I->getOpcode(), I->getType(),
                                        &Operands[0], Operands.size());
+        Pair.first->second = C;
         return getUnknown(C);
       }
     }
@@ -3473,6 +3481,8 @@ void SCEVCallbackVH::deleted() {
   assert(SE && "SCEVCallbackVH called with a non-null ScalarEvolution!");
   if (PHINode *PN = dyn_cast<PHINode>(getValPtr()))
     SE->ConstantEvolutionLoopExitValue.erase(PN);
+  if (Instruction *I = dyn_cast<Instruction>(getValPtr()))
+    SE->ValuesAtScopes.erase(I);
   SE->Scalars.erase(getValPtr());
   // this now dangles!
 }
@@ -3499,6 +3509,8 @@ void SCEVCallbackVH::allUsesReplacedWith(Value *) {
     }
     if (PHINode *PN = dyn_cast<PHINode>(U))
       SE->ConstantEvolutionLoopExitValue.erase(PN);
+    if (Instruction *I = dyn_cast<Instruction>(U))
+      SE->ValuesAtScopes.erase(I);
     if (SE->Scalars.erase(U))
       for (Value::use_iterator UI = U->use_begin(), UE = U->use_end();
            UI != UE; ++UI)
@@ -3507,6 +3519,8 @@ void SCEVCallbackVH::allUsesReplacedWith(Value *) {
   if (DeleteOld) {
     if (PHINode *PN = dyn_cast<PHINode>(Old))
       SE->ConstantEvolutionLoopExitValue.erase(PN);
+    if (Instruction *I = dyn_cast<Instruction>(Old))
+      SE->ValuesAtScopes.erase(I);
     SE->Scalars.erase(Old);
     // this now dangles!
   }
@@ -3535,6 +3549,7 @@ void ScalarEvolution::releaseMemory() {
   Scalars.clear();
   BackedgeTakenCounts.clear();
   ConstantEvolutionLoopExitValue.clear();
+  ValuesAtScopes.clear();
 }
 
 void ScalarEvolution::getAnalysisUsage(AnalysisUsage &AU) const {