summaryrefslogtreecommitdiff
path: root/lib/Analysis
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2010-07-29 00:17:55 +0000
committerDan Gohman <gohman@apple.com>2010-07-29 00:17:55 +0000
commitc6743207e20904008d2de016adfa6b0a9355c0e7 (patch)
tree8f727d234ed249b9d463ddf3c4658401a81dd93a /lib/Analysis
parente2fb451dbb50d9b1b4254f5acc7c98b1a8ebd3cf (diff)
downloadllvm-c6743207e20904008d2de016adfa6b0a9355c0e7.tar.gz
llvm-c6743207e20904008d2de016adfa6b0a9355c0e7.tar.bz2
llvm-c6743207e20904008d2de016adfa6b0a9355c0e7.tar.xz
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@109705 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis')
-rw-r--r--lib/Analysis/ScalarEvolution.cpp74
1 files changed, 45 insertions, 29 deletions
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index 7612f43f71..964093b069 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -3660,29 +3660,59 @@ void ScalarEvolution::forgetLoop(const Loop *L) {
}
}
-/// 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::deleted() {
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