diff options
author | Dan Gohman <gohman@apple.com> | 2010-07-29 00:17:55 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2010-07-29 00:17:55 +0000 |
commit | c6743207e20904008d2de016adfa6b0a9355c0e7 (patch) | |
tree | 8f727d234ed249b9d463ddf3c4658401a81dd93a /lib/Analysis/ScalarEvolution.cpp | |
parent | e2fb451dbb50d9b1b4254f5acc7c98b1a8ebd3cf (diff) |
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/ScalarEvolution.cpp')
-rw-r--r-- | lib/Analysis/ScalarEvolution.cpp | 74 |
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 |