[cfe-commits] r98159 - /cfe/trunk/lib/Checker/RegionStore.cpp
Ted Kremenek
kremenek at apple.com
Wed Mar 10 08:32:56 PST 2010
Author: kremenek
Date: Wed Mar 10 10:32:56 2010
New Revision: 98159
URL: http://llvm.org/viewvc/llvm-project?rev=98159&view=rev
Log:
Really apply (unnoticed weird git-svn merge conflict in 98144): Refactor RegionStore::RemoveDeadBindings to use the same core cluster analysis algorithm as RegionStore::InvalidateRegions().
Beyond simplifying the algorithm significantly, we no longer
need to build subregion maps in RemoveDeadBindings(). This
and other changes cause a significant speedup: the time to
analyze sqlite3.c (single core) drops by 14%.
Modified:
cfe/trunk/lib/Checker/RegionStore.cpp
Modified: cfe/trunk/lib/Checker/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/RegionStore.cpp?rev=98159&r1=98158&r2=98159&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/RegionStore.cpp (original)
+++ cfe/trunk/lib/Checker/RegionStore.cpp Wed Mar 10 10:32:56 2010
@@ -453,58 +453,105 @@
//===----------------------------------------------------------------------===//
namespace {
+template <typename DERIVED>
class ClusterAnalysis {
protected:
typedef BumpVector<BindingKey> RegionCluster;
typedef llvm::DenseMap<const MemRegion *, RegionCluster *> ClusterMap;
+ llvm::DenseMap<const RegionCluster*, unsigned> Visited;
+ typedef llvm::SmallVector<std::pair<const MemRegion *, RegionCluster*>, 10>
+ WorkList;
BumpVectorContext BVC;
ClusterMap ClusterM;
+ WorkList WL;
RegionStoreManager &RM;
ASTContext &Ctx;
ValueManager &ValMgr;
+ RegionBindings B;
+
public:
- ClusterAnalysis(RegionStoreManager &rm,
- ASTContext &ctx, ValueManager &valMgr)
- : RM(rm), Ctx(ctx), ValMgr(valMgr) {}
+ ClusterAnalysis(RegionStoreManager &rm, GRStateManager &StateMgr,
+ RegionBindings b)
+ : RM(rm), Ctx(StateMgr.getContext()), ValMgr(StateMgr.getValueManager()),
+ B(b) {}
-protected:
- void AddToCluster(BindingKey K);
- RegionCluster **getCluster(const MemRegion *R);
- void GenerateClusters(RegionBindings B);
-};
-}
+ RegionBindings getRegionBindings() const { return B; }
-void ClusterAnalysis::AddToCluster(BindingKey K) {
- const MemRegion *R = K.getRegion();
- const MemRegion *baseR = R->getBaseRegion();
- RegionCluster **CPtr = getCluster(baseR);
- assert(*CPtr);
- (*CPtr)->push_back(K, BVC);
-}
-
-ClusterAnalysis::RegionCluster **
-ClusterAnalysis::getCluster(const MemRegion *R) {
- RegionCluster *&CRef = ClusterM[R];
- if (!CRef) {
- void *Mem = BVC.getAllocator().Allocate<RegionCluster>();
- CRef = new (Mem) RegionCluster(BVC, 10);
- }
- return &CRef;
-}
-
-void ClusterAnalysis::GenerateClusters(RegionBindings B) {
- // Scan the entire set of bindings and make the region clusters.
- for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
- AddToCluster(RI.getKey());
- if (const MemRegion *R = RI.getData().getAsRegion()) {
- // Generate a cluster, but don't add the region to the cluster
- // if there aren't any bindings.
- getCluster(R->getBaseRegion());
+ void AddToCluster(BindingKey K) {
+ const MemRegion *R = K.getRegion();
+ const MemRegion *baseR = R->getBaseRegion();
+ RegionCluster &C = getCluster(baseR);
+ C.push_back(K, BVC);
+ static_cast<DERIVED*>(this)->VisitAddedToCluster(baseR, C);
+ }
+
+ bool isVisited(const MemRegion *R) {
+ return (bool) Visited[&getCluster(R->getBaseRegion())];
+ }
+
+ RegionCluster& getCluster(const MemRegion *R) {
+ RegionCluster *&CRef = ClusterM[R];
+ if (!CRef) {
+ void *Mem = BVC.getAllocator().template Allocate<RegionCluster>();
+ CRef = new (Mem) RegionCluster(BVC, 10);
}
+ return *CRef;
}
+
+ void GenerateClusters() {
+ // Scan the entire set of bindings and make the region clusters.
+ for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){
+ AddToCluster(RI.getKey());
+ if (const MemRegion *R = RI.getData().getAsRegion()) {
+ // Generate a cluster, but don't add the region to the cluster
+ // if there aren't any bindings.
+ getCluster(R->getBaseRegion());
+ }
+ }
+ }
+
+ bool AddToWorkList(const MemRegion *R, RegionCluster &C) {
+ if (unsigned &visited = Visited[&C])
+ return false;
+ else
+ visited = 1;
+
+ WL.push_back(std::make_pair(R, &C));
+ return true;
+ }
+
+ bool AddToWorkList(BindingKey K) {
+ return AddToWorkList(K.getRegion());
+ }
+
+ bool AddToWorkList(const MemRegion *R) {
+ const MemRegion *baseR = R->getBaseRegion();
+ return AddToWorkList(baseR, getCluster(baseR));
+ }
+
+ void RunWorkList() {
+ while (!WL.empty()) {
+ const MemRegion *baseR;
+ RegionCluster *C;
+ llvm::tie(baseR, C) = WL.back();
+ WL.pop_back();
+
+ // First visit the cluster.
+ static_cast<DERIVED*>(this)->VisitCluster(baseR, C->begin(), C->end());
+
+ // Next, visit the region.
+ static_cast<DERIVED*>(this)->VisitRegion(baseR);
+ }
+ }
+
+public:
+ void VisitAddedToCluster(const MemRegion *baseR, RegionCluster &C) {}
+ void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E) {}
+ void VisitRegion(const MemRegion *baseR) {}
+};
}
//===----------------------------------------------------------------------===//
@@ -524,43 +571,28 @@
}
namespace {
-class InvalidateRegionsWorker : public ClusterAnalysis {
- typedef llvm::SmallVector<std::pair<const MemRegion *,RegionCluster*>, 10>
- WorkList;
-
+class InvalidateRegionsWorker : public ClusterAnalysis<InvalidateRegionsWorker>
+{
+ const Expr *Ex;
+ unsigned Count;
StoreManager::InvalidatedSymbols *IS;
- WorkList WL;
-
public:
InvalidateRegionsWorker(RegionStoreManager &rm,
- StoreManager::InvalidatedSymbols *is,
- ASTContext &ctx, ValueManager &valMgr)
- : ClusterAnalysis(rm, ctx, valMgr), IS(is) {}
-
- Store InvalidateRegions(Store store, const MemRegion * const *I,
- const MemRegion * const *E,
- const Expr *Ex, unsigned Count);
+ GRStateManager &stateMgr,
+ RegionBindings b,
+ const Expr *ex, unsigned count,
+ StoreManager::InvalidatedSymbols *is)
+ : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr, b),
+ Ex(ex), Count(count), IS(is) {}
+
+ void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E);
+ void VisitRegion(const MemRegion *baseR);
private:
- void AddToWorkList(BindingKey K);
- void AddToWorkList(const MemRegion *R);
void VisitBinding(SVal V);
};
}
-void InvalidateRegionsWorker::AddToWorkList(BindingKey K) {
- AddToWorkList(K.getRegion());
-}
-
-void InvalidateRegionsWorker::AddToWorkList(const MemRegion *R) {
- const MemRegion *baseR = R->getBaseRegion();
- RegionCluster **CPtr = getCluster(baseR);
- if (RegionCluster *C = *CPtr) {
- WL.push_back(std::make_pair(baseR, C));
- *CPtr = NULL;
- }
-}
-
void InvalidateRegionsWorker::VisitBinding(SVal V) {
// A symbol? Mark it touched by the invalidation.
if (IS)
@@ -589,105 +621,82 @@
}
}
-Store InvalidateRegionsWorker::InvalidateRegions(Store store,
- const MemRegion * const *I,
- const MemRegion * const *E,
- const Expr *Ex, unsigned Count)
-{
- RegionBindings B = RegionStoreManager::GetRegionBindings(store);
-
- // Scan the entire store and make the region clusters.
- GenerateClusters(B);
-
- // Add the cluster for I .. E to a worklist.
- for ( ; I != E; ++I)
- AddToWorkList(*I);
+void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
+ BindingKey *I, BindingKey *E) {
+ for ( ; I != E; ++I) {
+ // Get the old binding. Is it a region? If so, add it to the worklist.
+ const BindingKey &K = *I;
+ if (const SVal *V = RM.Lookup(B, K))
+ VisitBinding(*V);
+
+ B = RM.Remove(B, K);
+ }
+}
- while (!WL.empty()) {
- const MemRegion *baseR;
- RegionCluster *C;
- llvm::tie(baseR, C) = WL.back();
- WL.pop_back();
-
- for (RegionCluster::iterator I = C->begin(), E = C->end(); I != E; ++I) {
- BindingKey K = *I;
-
- // Get the old binding. Is it a region? If so, add it to the worklist.
- if (const SVal *V = RM.Lookup(B, K))
- VisitBinding(*V);
-
- B = RM.Remove(B, K);
- }
-
- // Now inspect the base region.
-
- if (IS) {
- // Symbolic region? Mark that symbol touched by the invalidation.
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
- IS->insert(SR->getSymbol());
- }
-
- // BlockDataRegion? If so, invalidate captured variables that are passed
- // by reference.
- if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) {
- for (BlockDataRegion::referenced_vars_iterator
- BI = BR->referenced_vars_begin(), BE = BR->referenced_vars_end() ;
- BI != BE; ++BI) {
- const VarRegion *VR = *BI;
- const VarDecl *VD = VR->getDecl();
- if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage())
- AddToWorkList(VR);
- }
- continue;
+void InvalidateRegionsWorker::VisitRegion(const MemRegion *baseR) {
+ if (IS) {
+ // Symbolic region? Mark that symbol touched by the invalidation.
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
+ IS->insert(SR->getSymbol());
+ }
+
+ // BlockDataRegion? If so, invalidate captured variables that are passed
+ // by reference.
+ if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) {
+ for (BlockDataRegion::referenced_vars_iterator
+ BI = BR->referenced_vars_begin(), BE = BR->referenced_vars_end() ;
+ BI != BE; ++BI) {
+ const VarRegion *VR = *BI;
+ const VarDecl *VD = VR->getDecl();
+ if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage())
+ AddToWorkList(VR);
}
+ return;
+ }
- if (isa<AllocaRegion>(baseR) || isa<SymbolicRegion>(baseR)) {
- // Invalidate the region by setting its default value to
- // conjured symbol. The type of the symbol is irrelavant.
- DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy,
- Count);
- B = RM.Add(B, baseR, BindingKey::Default, V);
- continue;
- }
+ if (isa<AllocaRegion>(baseR) || isa<SymbolicRegion>(baseR)) {
+ // Invalidate the region by setting its default value to
+ // conjured symbol. The type of the symbol is irrelavant.
+ DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy,
+ Count);
+ B = RM.Add(B, baseR, BindingKey::Default, V);
+ return;
+ }
- if (!baseR->isBoundable())
- continue;
+ if (!baseR->isBoundable())
+ return;
- const TypedRegion *TR = cast<TypedRegion>(baseR);
- QualType T = TR->getValueType(Ctx);
+ const TypedRegion *TR = cast<TypedRegion>(baseR);
+ QualType T = TR->getValueType(Ctx);
// Invalidate the binding.
- if (const RecordType *RT = T->getAsStructureType()) {
- const RecordDecl *RD = RT->getDecl()->getDefinition();
+ if (const RecordType *RT = T->getAsStructureType()) {
+ const RecordDecl *RD = RT->getDecl()->getDefinition();
// No record definition. There is nothing we can do.
- if (!RD) {
- B = RM.Remove(B, baseR);
- continue;
- }
+ if (!RD) {
+ B = RM.Remove(B, baseR);
+ return;
+ }
// Invalidate the region by setting its default value to
// conjured symbol. The type of the symbol is irrelavant.
- DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy,
- Count);
- B = RM.Add(B, baseR, BindingKey::Default, V);
- continue;
- }
+ DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy,
+ Count);
+ B = RM.Add(B, baseR, BindingKey::Default, V);
+ return;
+ }
- if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
+ if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
// Set the default value of the array to conjured symbol.
- DefinedOrUnknownSVal V =
- ValMgr.getConjuredSymbolVal(baseR, Ex, AT->getElementType(), Count);
- B = RM.Add(B, baseR, BindingKey::Default, V);
- continue;
- }
-
- DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, T, Count);
- assert(SymbolManager::canSymbolicate(T) || V.isUnknown());
- B = RM.Add(B, baseR, BindingKey::Direct, V);
+ DefinedOrUnknownSVal V =
+ ValMgr.getConjuredSymbolVal(baseR, Ex, AT->getElementType(), Count);
+ B = RM.Add(B, baseR, BindingKey::Default, V);
+ return;
}
- // Create a new state with the updated bindings.
- return B.getRoot();
+ DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, T, Count);
+ assert(SymbolManager::canSymbolicate(T) || V.isUnknown());
+ B = RM.Add(B, baseR, BindingKey::Direct, V);
}
Store RegionStoreManager::InvalidateRegions(Store store,
@@ -695,9 +704,21 @@
const MemRegion * const *E,
const Expr *Ex, unsigned Count,
InvalidatedSymbols *IS) {
- InvalidateRegionsWorker W(*this, IS, getContext(),
- StateMgr.getValueManager());
- return W.InvalidateRegions(store, I, E, Ex, Count);
+ InvalidateRegionsWorker W(*this, StateMgr,
+ RegionStoreManager::GetRegionBindings(store),
+ Ex, Count, IS);
+
+ // Scan the bindings and generate the clusters.
+ W.GenerateClusters();
+
+ // Add I .. E to the worklist.
+ for ( ; I != E; ++I)
+ W.AddToWorkList(*I);
+
+ W.RunWorkList();
+
+ // Return the new bindings.
+ return W.getRegionBindings().getRoot();
}
//===----------------------------------------------------------------------===//
@@ -1700,193 +1721,162 @@
// State pruning.
//===----------------------------------------------------------------------===//
-Store RegionStoreManager::RemoveDeadBindings(Store store, Stmt* Loc,
- SymbolReaper& SymReaper,
- llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
-{
- typedef std::pair<Store, const MemRegion *> RBDNode;
+namespace {
+class RemoveDeadBindingsWorker :
+ public ClusterAnalysis<RemoveDeadBindingsWorker> {
+ llvm::SmallVector<const SymbolicRegion*, 12> Postponed;
+ SymbolReaper &SymReaper;
+ Stmt *Loc;
+public:
+ RemoveDeadBindingsWorker(RegionStoreManager &rm, GRStateManager &stateMgr,
+ RegionBindings b, SymbolReaper &symReaper,
+ Stmt *loc)
+ : ClusterAnalysis<RemoveDeadBindingsWorker>(rm, stateMgr, b),
+ SymReaper(symReaper), Loc(loc) {}
+
+ // Called by ClusterAnalysis.
+ void VisitAddedToCluster(const MemRegion *baseR, RegionCluster &C);
+ void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E);
+ void VisitRegion(const MemRegion *baseR);
- RegionBindings B = GetRegionBindings(store);
+ bool UpdatePostponed();
+ void VisitBinding(SVal V);
+};
+}
- // The backmap from regions to subregions.
- llvm::OwningPtr<RegionStoreSubRegionMap>
- SubRegions(getRegionStoreSubRegionMap(store));
+void RemoveDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
+ RegionCluster &C) {
- // Do a pass over the regions in the store. For VarRegions we check if
- // the variable is still live and if so add it to the list of live roots.
- // For other regions we populate our region backmap.
- llvm::SmallVector<const MemRegion*, 10> IntermediateRoots;
+ if (const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
+ if (SymReaper.isLive(Loc, VR))
+ AddToWorkList(baseR, C);
- // Scan the direct bindings for "intermediate" roots.
- for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- const MemRegion *R = I.getKey().getRegion();
- IntermediateRoots.push_back(R);
+ return;
}
- // Process the "intermediate" roots to find if they are referenced by
- // real roots.
- llvm::SmallVector<RBDNode, 10> WorkList;
- llvm::SmallVector<RBDNode, 10> Postponed;
-
- llvm::DenseSet<const MemRegion*> IntermediateVisited;
-
- while (!IntermediateRoots.empty()) {
- const MemRegion* R = IntermediateRoots.back();
- IntermediateRoots.pop_back();
-
- if (IntermediateVisited.count(R))
- continue;
- IntermediateVisited.insert(R);
-
- if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
- if (SymReaper.isLive(Loc, VR))
- WorkList.push_back(std::make_pair(store, VR));
- continue;
- }
-
- if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) {
- llvm::SmallVectorImpl<RBDNode> &Q =
- SymReaper.isLive(SR->getSymbol()) ? WorkList : Postponed;
-
- Q.push_back(std::make_pair(store, SR));
-
- continue;
- }
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
+ if (SymReaper.isLive(SR->getSymbol()))
+ AddToWorkList(SR, C);
+ else
+ Postponed.push_back(SR);
- // Add the super region for R to the worklist if it is a subregion.
- if (const SubRegion* superR =
- dyn_cast<SubRegion>(cast<SubRegion>(R)->getSuperRegion()))
- IntermediateRoots.push_back(superR);
+ return;
}
+}
- // Enqueue the RegionRoots onto WorkList.
- for (llvm::SmallVectorImpl<const MemRegion*>::iterator I=RegionRoots.begin(),
- E=RegionRoots.end(); I!=E; ++I) {
- WorkList.push_back(std::make_pair(store, *I));
+void RemoveDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
+ BindingKey *I, BindingKey *E) {
+ for ( ; I != E; ++I) {
+ const MemRegion *R = I->getRegion();
+ if (R != baseR)
+ VisitRegion(R);
}
- RegionRoots.clear();
-
- llvm::DenseSet<RBDNode> Visited;
-
-tryAgain:
- while (!WorkList.empty()) {
- RBDNode N = WorkList.back();
- WorkList.pop_back();
-
- // Have we visited this node before?
- if (Visited.count(N))
- continue;
- Visited.insert(N);
-
- const MemRegion *R = N.second;
- Store store_N = N.first;
-
- // Enqueue subregions.
- RegionStoreSubRegionMap *M;
+}
- if (store == store_N)
- M = SubRegions.get();
- else {
- RegionStoreSubRegionMap *& SM = SC[store_N];
- if (!SM)
- SM = getRegionStoreSubRegionMap(store_N);
- M = SM;
- }
-
- if (const RegionStoreSubRegionMap::Set *S = M->getSubRegions(R))
- for (RegionStoreSubRegionMap::Set::iterator I = S->begin(), E = S->end();
- I != E; ++I)
- WorkList.push_back(std::make_pair(store_N, *I));
-
- // Enqueue the super region.
- if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
- const MemRegion *superR = SR->getSuperRegion();
- if (!isa<MemSpaceRegion>(superR)) {
- // If 'R' is a field or an element, we want to keep the bindings
- // for the other fields and elements around. The reason is that
- // pointer arithmetic can get us to the other fields or elements.
- assert(isa<FieldRegion>(R) || isa<ElementRegion>(R)
- || isa<ObjCIvarRegion>(R));
- WorkList.push_back(std::make_pair(store_N, superR));
- }
- }
+void RemoveDeadBindingsWorker::VisitBinding(SVal V) {
+ // Is it a LazyCompoundVal? All referenced regions are live as well.
+ if (const nonloc::LazyCompoundVal *LCS =
+ dyn_cast<nonloc::LazyCompoundVal>(&V)) {
- // Mark the symbol for any live SymbolicRegion as "live". This means we
- // should continue to track that symbol.
- if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
- SymReaper.markLive(SymR->getSymbol());
-
- // For BlockDataRegions, enqueue the VarRegions for variables marked
- // with __block (passed-by-reference).
- // via BlockDeclRefExprs.
- if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(R)) {
- for (BlockDataRegion::referenced_vars_iterator
- RI = BD->referenced_vars_begin(), RE = BD->referenced_vars_end();
- RI != RE; ++RI) {
- if ((*RI)->getDecl()->getAttr<BlocksAttr>())
- WorkList.push_back(std::make_pair(store_N, *RI));
- }
- // No possible data bindings on a BlockDataRegion. Continue to the
- // next region in the worklist.
- continue;
+ const MemRegion *LazyR = LCS->getRegion();
+ RegionBindings B = RegionStoreManager::GetRegionBindings(LCS->getStore());
+ for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){
+ const MemRegion *baseR = RI.getKey().getRegion();
+ if (cast<SubRegion>(baseR)->isSubRegionOf(LazyR))
+ VisitBinding(RI.getData());
}
+ return;
+ }
- RegionBindings B_N = GetRegionBindings(store_N);
-
- // Get the data binding for R (if any).
- Optional<SVal> V = getBinding(B_N, R);
-
- if (V) {
- // Check for lazy bindings.
- if (const nonloc::LazyCompoundVal *LCV =
- dyn_cast<nonloc::LazyCompoundVal>(V.getPointer())) {
+ // If V is a region, then add it to the worklist.
+ if (const MemRegion *R = V.getAsRegion())
+ AddToWorkList(R);
- const LazyCompoundValData *D = LCV->getCVData();
- WorkList.push_back(std::make_pair(D->getStore(), D->getRegion()));
- }
- else {
- // Update the set of live symbols.
- for (SVal::symbol_iterator SI=V->symbol_begin(), SE=V->symbol_end();
- SI!=SE;++SI)
- SymReaper.markLive(*SI);
-
- // If V is a region, then add it to the worklist.
- if (const MemRegion *RX = V->getAsRegion())
- WorkList.push_back(std::make_pair(store_N, RX));
- }
+ // Update the set of live symbols.
+ for (SVal::symbol_iterator SI=V.symbol_begin(), SE=V.symbol_end();
+ SI!=SE;++SI)
+ SymReaper.markLive(*SI);
+}
+
+void RemoveDeadBindingsWorker::VisitRegion(const MemRegion *R) {
+ // Mark this region "live" by adding it to the worklist. This will cause
+ // use to visit all regions in the cluster (if we haven't visited them
+ // already).
+ AddToWorkList(R);
+
+ // Mark the symbol for any live SymbolicRegion as "live". This means we
+ // should continue to track that symbol.
+ if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
+ SymReaper.markLive(SymR->getSymbol());
+
+ // For BlockDataRegions, enqueue the VarRegions for variables marked
+ // with __block (passed-by-reference).
+ // via BlockDeclRefExprs.
+ if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(R)) {
+ for (BlockDataRegion::referenced_vars_iterator
+ RI = BD->referenced_vars_begin(), RE = BD->referenced_vars_end();
+ RI != RE; ++RI) {
+ if ((*RI)->getDecl()->getAttr<BlocksAttr>())
+ AddToWorkList(*RI);
}
+
+ // No possible data bindings on a BlockDataRegion.
+ return;
}
+ // Get the data binding for R (if any).
+ if (Optional<SVal> V = RM.getBinding(B, R))
+ VisitBinding(*V);
+}
+
+bool RemoveDeadBindingsWorker::UpdatePostponed() {
// See if any postponed SymbolicRegions are actually live now, after
// having done a scan.
- for (llvm::SmallVectorImpl<RBDNode>::iterator I = Postponed.begin(),
- E = Postponed.end() ; I != E ; ++I) {
- if (const SymbolicRegion *SR = cast_or_null<SymbolicRegion>(I->second)) {
+ bool changed = false;
+
+ for (llvm::SmallVectorImpl<const SymbolicRegion*>::iterator
+ I = Postponed.begin(), E = Postponed.end() ; I != E ; ++I) {
+ if (const SymbolicRegion *SR = cast_or_null<SymbolicRegion>(*I)) {
if (SymReaper.isLive(SR->getSymbol())) {
- WorkList.push_back(*I);
- I->second = NULL;
+ changed |= AddToWorkList(SR);
+ *I = NULL;
}
}
}
- if (!WorkList.empty())
- goto tryAgain;
+ return changed;
+}
+
+Store RegionStoreManager::RemoveDeadBindings(Store store, Stmt* Loc,
+ SymbolReaper& SymReaper,
+ llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
+{
+ RegionBindings B = GetRegionBindings(store);
+ RemoveDeadBindingsWorker W(*this, StateMgr, B, SymReaper, Loc);
+ W.GenerateClusters();
+
+ // Enqueue the region roots onto the worklist.
+ for (llvm::SmallVectorImpl<const MemRegion*>::iterator I=RegionRoots.begin(),
+ E=RegionRoots.end(); I!=E; ++I)
+ W.AddToWorkList(*I);
+
+ do W.RunWorkList(); while (W.UpdatePostponed());
// We have now scanned the store, marking reachable regions and symbols
// as live. We now remove all the regions that are dead from the store
// as well as update DSymbols with the set symbols that are now dead.
- Store new_store = store;
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- const MemRegion* R = I.getKey().getRegion();
- // If this region live? Is so, none of its symbols are dead.
- if (Visited.count(std::make_pair(store, R)))
+ const BindingKey &K = I.getKey();
+
+ // If the cluster has been marked null, we know the region has been marked.
+ if (W.isVisited(K.getRegion()))
continue;
- // Remove this dead region from the store.
- new_store = Remove(new_store, I.getKey());
+ // Remove the dead entry.
+ B = Remove(B, K);
- // Mark all non-live symbols that this region references as dead.
- if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R))
+ // Mark all non-live symbols that this binding references as dead.
+ if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(K.getRegion()))
SymReaper.maybeDead(SymR->getSymbol());
SVal X = I.getData();
@@ -1895,9 +1885,10 @@
SymReaper.maybeDead(*SI);
}
- return new_store;
+ return B.getRoot();
}
+
GRState const *RegionStoreManager::EnterStackFrame(GRState const *state,
StackFrameContext const *frame) {
FunctionDecl const *FD = cast<FunctionDecl>(frame->getDecl());
More information about the cfe-commits
mailing list