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>