[llvm-commits] [llvm] r109705 - in /llvm/trunk: include/llvm/Analysis/ScalarEvolution.h include/llvm/Analysis/ScalarEvolutionExpressions.h lib/Analysis/ScalarEvolution.cpp unittests/Analysis/ unittests/Analysis/Makefile unittests/Analysis/ScalarEvolutionTest.cpp unittests/Makefile

Dan Gohman gohman at apple.com
Wed Jul 28 17:17:55 PDT 2010


Author: djg
Date: Wed Jul 28 19:17:55 2010
New Revision: 109705

URL: http://llvm.org/viewvc/llvm-project?rev=109705&view=rev
Log:
Factor out some of the code for updating old SCEVUnknown values, and
extend it to handle the case where multiple RAUWs affect a single
SCEVUnknown.

Add a ScalarEvolution unittest to test for this situation.

Added:
    llvm/trunk/unittests/Analysis/   (with props)
    llvm/trunk/unittests/Analysis/Makefile
      - copied, changed from r109674, llvm/trunk/unittests/VMCore/Makefile
    llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp
Modified:
    llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
    llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h
    llvm/trunk/lib/Analysis/ScalarEvolution.cpp
    llvm/trunk/unittests/Makefile

Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=109705&r1=109704&r2=109705&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Wed Jul 28 19:17:55 2010
@@ -386,6 +386,11 @@
     bool isKnownPredicateWithRanges(ICmpInst::Predicate Pred,
                                     const SCEV *LHS, const SCEV *RHS);
 
+    /// forgetSCEVUnknown - V is being deleted or RAUW'd; remove the
+    /// SCEVUnknown for it from the uniquing map, and optionally
+    /// clear its contents to point to a replacement value.
+    void forgetSCEVUnknown(Value *V, Value *NewV);
+
   public:
     static char ID; // Pass identification, replacement for typeid
     ScalarEvolution();

Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h?rev=109705&r1=109704&r2=109705&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h Wed Jul 28 19:17:55 2010
@@ -524,11 +524,26 @@
     friend class ScalarEvolution;
     friend class ScalarEvolution::SCEVCallbackVH;
 
-    // This should be an AssertingVH, however SCEVUnknowns are allocated in a
-    // BumpPtrAllocator so their destructors are never called.
+    /// V - The Value represented by this SCEVUnknown.
+    /// This should be an AssertingVH, however SCEVUnknowns are allocated in a
+    /// BumpPtrAllocator so their destructors are never called.
     Value *V;
+
+    /// UpdateList - When values are RAUW'd with new values, and the new
+    /// values already have their own SCEVUnknowns, they can end up with
+    /// muliple SCEVUnknowns. This pointer links them all together so that
+    /// they can all be updated when another RAUW happens.
+    SCEVUnknown *UpdateList;
+
+    /// getUpdateListBack - Return the last SCEVUnknown in te UpdateList.
+    SCEVUnknown *getUpdateListBack() {
+      SCEVUnknown *P = this;
+      while (SCEVUnknown *Q = P->UpdateList) P = Q;
+      return P;
+    }
+
     SCEVUnknown(const FoldingSetNodeIDRef ID, Value *v) :
-      SCEV(ID, scUnknown), V(v) {}
+      SCEV(ID, scUnknown), V(v), UpdateList(0) {}
 
   public:
     Value *getValue() const { return V; }

Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=109705&r1=109704&r2=109705&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Wed Jul 28 19:17:55 2010
@@ -3660,29 +3660,59 @@
   }
 }
 
-/// forgetValue - This method should be called by the client when it has
-/// changed a value in a way that may effect its value, or which may
-/// disconnect it from a def-use chain linking it to a loop.
-void ScalarEvolution::forgetValue(Value *V) {
-  // If there's a SCEVUnknown tying this value into the SCEV
-  // space, remove it from the folding set map. The SCEVUnknown
-  // object and any other SCEV objects which reference it
-  // (transitively) remain allocated, effectively leaked until
-  // the underlying BumpPtrAllocator is freed.
-  //
+/// forgetSCEVUnknown - V is being deleted or RAUW'd; remove the
+/// SCEVUnknown for it from the uniquing map, and optionally
+/// clear its contents to point to a replacement value.
+void ScalarEvolution::forgetSCEVUnknown(Value *V, Value *NewV) {
   // This permits SCEV pointers to be used as keys in maps
   // such as the ValuesAtScopes map.
+
+  // Check for an exisitng SCEVUnknown for V in the uniquing map.
   FoldingSetNodeID ID;
   ID.AddInteger(scUnknown);
   ID.AddPointer(V);
   void *IP;
   if (SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) {
+    // Remove the old SCEVUnknown from the uniquing map, effectively
+    // leaking it from subsequent use by ScalarEvolution. There
+    // may be existing SCEVs live which still point to it though.
     UniqueSCEVs.RemoveNode(S);
 
-    // This isn't necessary, but we might as well remove the
-    // value from the ValuesAtScopes map too.
-    ValuesAtScopes.erase(S);
+    // If there's a replacement value, update the old SCEVUnknowns
+    // so that SCEVs which still point to it see the new value.
+    if (NewV) {
+      // Update the old SCEVUnknown and all SCEVUnknowns on its update list
+      // to point to NewV instead of V.
+      for (SCEVUnknown *U = cast<SCEVUnknown>(S); U; U = U->UpdateList) {
+        assert(U->V == V && "SCEVUnknown update list is inconsistent!");
+        U->V = NewV;
+      }
+
+      // Check for an existing SCEVUnknown for NewV in the uniquing map.
+      ID.clear();
+      ID.AddInteger(scUnknown);
+      ID.AddPointer(NewV);
+      if (SCEV *NewS = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) {
+        // The uniquing map already had an entry for the new
+        // value. Append the old SCEVUnknown (and its update list) to the
+        // new SCEVUnknown's update list.
+        cast<SCEVUnknown>(NewS)->getUpdateListBack()->UpdateList =
+          cast<SCEVUnknown>(S);
+      } else {
+        // The uniquing map did not have an entry for the new
+        // value yet. Set the old SCEVUnknown, which has now been
+        // updated, to be the SCEVUnknown in the uniquing map.
+        UniqueSCEVs.InsertNode(S, IP);
+      }
+    }
   }
+}
+
+/// forgetValue - This method should be called by the client when it has
+/// changed a value in a way that may effect its value, or which may
+/// disconnect it from a def-use chain linking it to a loop.
+void ScalarEvolution::forgetValue(Value *V) {
+  forgetSCEVUnknown(V, 0);
 
   Instruction *I = dyn_cast<Instruction>(V);
   if (!I) return;
@@ -5692,24 +5722,10 @@
 
 void ScalarEvolution::SCEVCallbackVH::allUsesReplacedWith(Value *V) {
   assert(SE && "SCEVCallbackVH called with a null ScalarEvolution!");
-
   Value *Old = getValPtr();
 
-  // If there's a SCEVUnknown tying this value into the SCEV
-  // space, replace the SCEVUnknown's value with the new value
-  // for the benefit of any SCEVs still referencing it, and
-  // and remove it from the folding set map so that new scevs
-  // don't reference it.
-  FoldingSetNodeID ID;
-  ID.AddInteger(scUnknown);
-  ID.AddPointer(Old);
-  void *IP;
-  if (SCEVUnknown *S = cast_or_null<SCEVUnknown>(
-        SE->UniqueSCEVs.FindNodeOrInsertPos(ID, IP))) {
-    S->V = V;
-    SE->UniqueSCEVs.RemoveNode(S);
-    SE->ValuesAtScopes.erase(S);
-  }
+  // First, update existing SCEVUnknowns.
+  SE->forgetSCEVUnknown(Old, V);
 
   // Forget all the expressions associated with users of the old value,
   // so that future queries will recompute the expressions using the new

Propchange: llvm/trunk/unittests/Analysis/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Wed Jul 28 19:17:55 2010
@@ -0,0 +1,9 @@
+Debug
+Release
+Release-Asserts
+Debug+Coverage-Asserts
+Debug+Coverage
+Release+Coverage
+Debug+Checks
+Debug+Asserts
+Release+Asserts

Copied: llvm/trunk/unittests/Analysis/Makefile (from r109674, llvm/trunk/unittests/VMCore/Makefile)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Analysis/Makefile?p2=llvm/trunk/unittests/Analysis/Makefile&p1=llvm/trunk/unittests/VMCore/Makefile&r1=109674&r2=109705&rev=109705&view=diff
==============================================================================
--- llvm/trunk/unittests/VMCore/Makefile (original)
+++ llvm/trunk/unittests/Analysis/Makefile Wed Jul 28 19:17:55 2010
@@ -1,4 +1,4 @@
-##===- unittests/VMCore/Makefile ---------------------------*- Makefile -*-===##
+##===- unittests/Analysis/Makefile -------------------------*- Makefile -*-===##
 #
 #                     The LLVM Compiler Infrastructure
 #
@@ -8,8 +8,8 @@
 ##===----------------------------------------------------------------------===##
 
 LEVEL = ../..
-TESTNAME = VMCore
-LINK_COMPONENTS := core support target ipa
+TESTNAME = Analysis
+LINK_COMPONENTS := core support target analysis ipa
 
 include $(LEVEL)/Makefile.config
 include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest

Added: llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp?rev=109705&view=auto
==============================================================================
--- llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp (added)
+++ llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp Wed Jul 28 19:17:55 2010
@@ -0,0 +1,78 @@
+//===- ScalarEvolutionsTest.cpp - ScalarEvolution unit tests --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <llvm/Analysis/ScalarEvolutionExpressions.h>
+#include <llvm/GlobalVariable.h>
+#include <llvm/Constants.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/Module.h>
+#include <llvm/PassManager.h>
+#include "gtest/gtest.h"
+
+namespace llvm {
+namespace {
+
+TEST(ScalarEvolutionsTest, ReturnInst) {
+  LLVMContext Context;
+  Module M("world", Context);
+
+  const FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context),
+                                              std::vector<const Type *>(), false);
+  Function *F = cast<Function>(M.getOrInsertFunction("f", FTy));
+  BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
+  ReturnInst::Create(Context, 0, BB);
+
+  const Type *Ty = Type::getInt1Ty(Context);
+  Constant *Init = Constant::getNullValue(Ty);
+  Value *V0 = new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, Init, "V0");
+  Value *V1 = new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, Init, "V1");
+  Value *V2 = new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, Init, "V2");
+
+  // Create a ScalarEvolution and "run" it so that it gets initialized.
+  PassManager PM;
+  ScalarEvolution &SE = *new ScalarEvolution();
+  PM.add(&SE);
+  PM.run(M);
+
+  const SCEV *S0 = SE.getSCEV(V0);
+  const SCEV *S1 = SE.getSCEV(V1);
+  const SCEV *S2 = SE.getSCEV(V2);
+
+  const SCEV *P0 = SE.getAddExpr(S0, S0);
+  const SCEV *P1 = SE.getAddExpr(S1, S1);
+  const SCEV *P2 = SE.getAddExpr(S2, S2);
+
+  const SCEVMulExpr *M0 = cast<SCEVMulExpr>(P0);
+  const SCEVMulExpr *M1 = cast<SCEVMulExpr>(P1);
+  const SCEVMulExpr *M2 = cast<SCEVMulExpr>(P2);
+
+  EXPECT_EQ(cast<SCEVConstant>(M0->getOperand(0))->getValue()->getZExtValue(),
+            2u);
+  EXPECT_EQ(cast<SCEVConstant>(M1->getOperand(0))->getValue()->getZExtValue(),
+            2u);
+  EXPECT_EQ(cast<SCEVConstant>(M2->getOperand(0))->getValue()->getZExtValue(),
+            2u);
+
+  // Before the RAUWs, these are all pointing to separate values.
+  EXPECT_EQ(cast<SCEVUnknown>(M0->getOperand(1))->getValue(), V0);
+  EXPECT_EQ(cast<SCEVUnknown>(M1->getOperand(1))->getValue(), V1);
+  EXPECT_EQ(cast<SCEVUnknown>(M2->getOperand(1))->getValue(), V2);
+
+  // Do some RAUWs.
+  V2->replaceAllUsesWith(V1);
+  V1->replaceAllUsesWith(V0);
+
+  // After the RAUWs, these should all be pointing to V0.
+  EXPECT_EQ(cast<SCEVUnknown>(M0->getOperand(1))->getValue(), V0);
+  EXPECT_EQ(cast<SCEVUnknown>(M1->getOperand(1))->getValue(), V0);
+  EXPECT_EQ(cast<SCEVUnknown>(M2->getOperand(1))->getValue(), V0);
+}
+
+}  // end anonymous namespace
+}  // end namespace llvm

Modified: llvm/trunk/unittests/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Makefile?rev=109705&r1=109704&r2=109705&view=diff
==============================================================================
--- llvm/trunk/unittests/Makefile (original)
+++ llvm/trunk/unittests/Makefile Wed Jul 28 19:17:55 2010
@@ -9,7 +9,7 @@
 
 LEVEL = ..
 
-PARALLEL_DIRS = ADT ExecutionEngine Support Transforms VMCore
+PARALLEL_DIRS = ADT ExecutionEngine Support Transforms VMCore Analysis
 
 include $(LEVEL)/Makefile.common
 





More information about the llvm-commits mailing list