Great!<br><br><div class="gmail_quote">On Thu, Dec 4, 2008 at 10:08 AM, Ted Kremenek <span dir="ltr"><<a href="mailto:kremenek@apple.com">kremenek@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Author: kremenek<br>
Date: Wed Dec 3 20:08:27 2008<br>
New Revision: 60523<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=60523&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=60523&view=rev</a><br>
Log:<br>
Revamp RegionStoreManager::RemoveDeadBindings. This method now does a complete mark-and-sweep of the store, removing dead regions and recording the set of live and dead symbols appropriately.<br>
<br>
Modified:<br>
cfe/trunk/lib/Analysis/RegionStore.cpp<br>
<br>
Modified: cfe/trunk/lib/Analysis/RegionStore.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/RegionStore.cpp?rev=60523&r1=60522&r2=60523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/RegionStore.cpp?rev=60523&r1=60522&r2=60523&view=diff</a><br>
<br>
==============================================================================<br>
--- cfe/trunk/lib/Analysis/RegionStore.cpp (original)<br>
+++ cfe/trunk/lib/Analysis/RegionStore.cpp Wed Dec 3 20:08:27 2008<br>
@@ -52,6 +52,17 @@<br>
};<br>
}<br>
<br>
+// KillSet GDM stuff.<br>
+typedef llvm::ImmutableSet<const MemRegion*> RegionKillSetTy;<br>
+static int RegionKillSetTyIndex = 0;<br>
+namespace clang {<br>
+ template<> struct GRStateTrait<RegionKillSetTy><br>
+ : public GRStatePartialTrait<RegionKillSetTy> {<br>
+ static void* GDMIndex() { return &RegionKillSetTyIndex; }<br>
+ };<br>
+}<br>
+<br>
+<br>
namespace {<br>
<br>
class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {<br>
@@ -116,10 +127,15 @@<br>
assert (false && "Not implemented.");<br>
return 0;<br>
}<br>
-<br>
+<br>
+ /// RemoveDeadBindings - Scans a RegionStore for dead values. It returns<br>
+ /// a new Store with these values removed, and populates LSymbols and<br>
+ /// DSymbols with the known set of live and dead symbols respectively.<br>
Store RemoveDeadBindings(Store store, Stmt* Loc, const LiveVariables& Live,<br>
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,<br>
LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols);<br>
+<br>
+ void UpdateLiveSymbols(SVal X, LiveSymbolsTy& LSymbols);<br>
<br>
Store BindDecl(Store store, const VarDecl* VD, SVal* InitVal, unsigned Count);<br>
<br>
@@ -605,22 +621,130 @@<br>
}<br>
<br>
<br>
+void RegionStoreManager::UpdateLiveSymbols(SVal X, LiveSymbolsTy& LSymbols) {<br>
+ for (SVal::symbol_iterator SI=X.symbol_begin(),SE=X.symbol_end();SI!=SE;++SI)<br>
+ LSymbols.insert(*SI);<br>
+}<br>
+<br>
Store RegionStoreManager::RemoveDeadBindings(Store store, Stmt* Loc,<br>
const LiveVariables& Live,<br>
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,<br>
LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols) {<br>
<br>
RegionBindingsTy B = GetRegionBindings(store);<br>
- typedef SVal::symbol_iterator symbol_iterator;<br>
-<br>
- // FIXME: Mark all region binding value's symbol as live. We also omit symbols<br>
- // in SymbolicRegions.<br>
+<br>
+ // Lazily constructed backmap from MemRegions to SubRegions.<br>
+ typedef llvm::ImmutableSet<const MemRegion*> SubRegionsTy;<br>
+ typedef llvm::ImmutableMap<const MemRegion*, SubRegionsTy> SubRegionsMapTy;<br>
+<br>
+ // FIXME: As a future optimization we can modifiy BumpPtrAllocator to have<br>
+ // the ability to reuse memory. This way we can keep TmpAlloc around as<br>
+ // an instance variable of RegionStoreManager (avoiding repeated malloc<br>
+ // overhead).<br>
+ llvm::BumpPtrAllocator TmpAlloc;<br>
+<br>
+ // Factory objects.<br>
+ SubRegionsMapTy::Factory SubRegMapF(TmpAlloc);<br>
+ SubRegionsTy::Factory SubRegF(TmpAlloc);<br>
+<br>
+ // The backmap from regions to subregions.<br>
+ SubRegionsMapTy SubRegMap = SubRegMapF.GetEmptyMap();<br>
+<br>
+ // Do a pass over the regions in the store. For VarRegions we check if<br>
+ // the variable is still live and if so add it to the list of live roots.<br>
+ // For other regions we populate our region backmap.<br>
for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {<br>
- SVal X = I.getData();<br>
- for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)<br>
- LSymbols.insert(*SI);<br>
+ const MemRegion* R = I.getKey();<br>
+ if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {<br>
+ if (Live.isLive(Loc, VR->getDecl()))<br>
+ RegionRoots.push_back(VR); // This is a live "root".<br>
+ }<br>
+ else {<br>
+ // Get the super region for R.<br>
+ const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion();<br>
+ // Get the current set of subregions for SuperR.<br>
+ const SubRegionsTy* SRptr = SubRegMap.lookup(SuperR);<br>
+ SubRegionsTy SR = SRptr ? *SRptr : SubRegF.GetEmptySet();<br>
+ // Add R to the subregions of SuperR.<br>
+ SubRegMap = SubRegMapF.Add(SubRegMap, SuperR, SubRegF.Add(SR, R));<br>
+<br>
+ // Finally, check if SuperR is a VarRegion. We need to do this<br>
+ // to also mark SuperR as a root (as it may not have a value directly<br>
+ // bound to it in the store).<br>
+ if (const VarRegion* VR = dyn_cast<VarRegion>(SuperR)) {<br>
+ if (Live.isLive(Loc, VR->getDecl()))<br>
+ RegionRoots.push_back(VR); // This is a live "root".<br>
+ }<br>
+ }<br>
}<br>
+<br>
+ // Process the worklist of RegionRoots. This performs a "mark-and-sweep"<br>
+ // of the store. We want to find all live symbols and dead regions.<br>
+ llvm::SmallPtrSet<const MemRegion*, 10> Marked;<br>
+<br>
+ while (!RegionRoots.empty()) {<br>
+ // Dequeue the next region on the worklist.<br>
+ const MemRegion* R = RegionRoots.back();<br>
+ RegionRoots.pop_back();<br>
+<br>
+ // Check if we have already processed this region.<br>
+ if (Marked.count(R)) continue;<br>
+<br>
+ // Mark this region as processed. This is needed for termination in case<br>
+ // a region is referenced more than once.<br>
+ Marked.insert(R);<br>
+<br>
+ // Mark the symbol for any live SymbolicRegion as "live". This means we<br>
+ // should continue to track that symbol.<br>
+ if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R))<br>
+ LSymbols.insert(SymR->getSymbol());<br>
+<br>
+ // Get the data binding for R (if any).<br>
+ RegionBindingsTy::data_type* Xptr = B.lookup(R);<br>
+ if (Xptr) {<br>
+ SVal X = *Xptr;<br>
+ UpdateLiveSymbols(X, LSymbols); // Update the set of live symbols.<br>
+<br>
+ // If X is a region, then add it the RegionRoots.<br>
+ if (loc::MemRegionVal* RegionX = dyn_cast<loc::MemRegionVal>(&X))<br>
+ RegionRoots.push_back(RegionX->getRegion());<br>
+ }<br>
+<br>
+ // Get the subregions of R. These are RegionRoots as well since they<br>
+ // represent values that are also bound to R.<br>
+ const SubRegionsTy* SRptr = SubRegMap.lookup(R);<br>
+ if (!SRptr) continue;<br>
+ SubRegionsTy SR = *SRptr;<br>
+<br>
+ for (SubRegionsTy::iterator I=SR.begin(), E=SR.end(); I!=E; ++I)<br>
+ RegionRoots.push_back(*I);<br>
+ }<br>
+<br>
+ // We have now scanned the store, marking reachable regions and symbols<br>
+ // as live. We now remove all the regions that are dead from the store<br>
+ // as well as update DSymbols with the set symbols that are now dead.<br>
+<br>
+ for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {<br>
+ const MemRegion* R = I.getKey();<br>
+<br>
+ // If this region live? Is so, none of its symbols are dead.<br>
+ if (Marked.count(R))<br>
+ continue;<br>
+<br>
+ // Remove this dead region from the store.<br>
+ store = Remove(store, loc::MemRegionVal(R));<br>
<br>
+ // Mark all non-live symbols that this region references as dead.<br>
+ if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R)) {<br>
+ SymbolID Sym = SymR->getSymbol();<br>
+ if (!LSymbols.count(Sym)) DSymbols.insert(Sym);<br>
+ }<br>
+<br>
+ SVal X = I.getData();<br>
+ SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();<br>
+ for (; SI != SE; ++SI) { if (!LSymbols.count(*SI)) DSymbols.insert(*SI); }<br>
+ }<br>
+<br>
return store;<br>
}<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br>