From 88a6b7fa80026e39a564567dac8c335daa6d41be Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 17 Jul 2008 18:38:48 +0000 Subject: [PATCH] Moved RemoveDeadBindings logic for the contents of 'Store' to a virtual RemoveDeadBindings method in StoreManager. llvm-svn: 53726 --- .../clang/Analysis/PathSensitive/Store.h | 17 +++- .../clang/Analysis/PathSensitive/ValueState.h | 14 ++- clang/lib/Analysis/BasicStore.cpp | 95 +++++++++++++++---- clang/lib/Analysis/ValueState.cpp | 86 ++++------------- 4 files changed, 122 insertions(+), 90 deletions(-) diff --git a/clang/include/clang/Analysis/PathSensitive/Store.h b/clang/include/clang/Analysis/PathSensitive/Store.h index adf9cf8eaec5..657ce8d954b0 100644 --- a/clang/include/clang/Analysis/PathSensitive/Store.h +++ b/clang/include/clang/Analysis/PathSensitive/Store.h @@ -15,18 +15,33 @@ #define LLVM_CLANG_ANALYSIS_STORE_H #include "clang/Analysis/PathSensitive/RValues.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/DenseSet.h" +#include namespace clang { typedef const void* Store; +class LiveVariables; +class Stmt; class StoreManager { public: + typedef llvm::SmallSet LiveSymbolsTy; + typedef llvm::DenseSet DeadSymbolsTy; + typedef std::vector DeclRootsTy; + virtual ~StoreManager() {} - virtual RVal GetRVal(Store St, LVal LV, QualType T) = 0; + virtual RVal GetRVal(Store St, LVal LV, QualType T = QualType()) = 0; virtual Store SetRVal(Store St, LVal LV, RVal V) = 0; virtual Store Remove(Store St, LVal LV) = 0; virtual Store getInitialStore() = 0; + + virtual Store RemoveDeadBindings(Store store, Stmt* Loc, + const LiveVariables& Live, + DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols, + DeadSymbolsTy& DSymbols) = 0; }; } // end clang namespace diff --git a/clang/include/clang/Analysis/PathSensitive/ValueState.h b/clang/include/clang/Analysis/PathSensitive/ValueState.h index 36bfdff5b936..ea86dfbf353e 100644 --- a/clang/include/clang/Analysis/PathSensitive/ValueState.h +++ b/clang/include/clang/Analysis/PathSensitive/ValueState.h @@ -31,7 +31,6 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/DenseSet.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" @@ -57,7 +56,7 @@ public: typedef llvm::ImmutableSet IntSetTy; typedef llvm::ImmutableMap ConstNotEqTy; typedef llvm::ImmutableMap ConstEqTy; - + private: void operator=(const ValueState& R) const; @@ -128,6 +127,7 @@ public: // Iterators. + // FIXME: We'll be removing the VarBindings iterator very soon. Right now // it assumes that Store is a VarBindingsTy. typedef llvm::ImmutableMap VarBindingsTy; @@ -140,6 +140,7 @@ public: VarBindingsTy B(static_cast(St)); return B.end(); } + typedef Environment::seb_iterator seb_iterator; seb_iterator seb_begin() const { return Env.seb_begin(); } @@ -184,6 +185,7 @@ template<> struct GRTrait { class ValueStateManager { + private: EnvironmentManager EnvMgr; llvm::OwningPtr StMgr; @@ -204,6 +206,10 @@ private: /// Alloc - A BumpPtrAllocator to allocate states. llvm::BumpPtrAllocator& Alloc; + /// DRoots - A vector to hold of worklist used by RemoveDeadSymbols. + /// This vector is persistent because it is reused over and over. + StoreManager::DeclRootsTy DRoots; + private: Environment RemoveBlkExpr(const Environment& Env, Expr* E) { @@ -232,11 +238,11 @@ public: BasicValueFactory& getBasicValueFactory() { return BasicVals; } SymbolManager& getSymbolManager() { return SymMgr; } - typedef llvm::DenseSet DeadSymbolsTy; + typedef StoreManager::DeadSymbolsTy DeadSymbolsTy; const ValueState* RemoveDeadBindings(const ValueState* St, Stmt* Loc, const LiveVariables& Liveness, - DeadSymbolsTy& DeadSymbols); + DeadSymbolsTy& DeadSyms); const ValueState* RemoveSubExprBindings(const ValueState* St) { ValueState NewSt = *St; diff --git a/clang/lib/Analysis/BasicStore.cpp b/clang/lib/Analysis/BasicStore.cpp index 38c1db70f15b..64a230975f09 100644 --- a/clang/lib/Analysis/BasicStore.cpp +++ b/clang/lib/Analysis/BasicStore.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Analysis/PathSensitive/BasicStore.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/Support/Compiler.h" @@ -34,6 +35,15 @@ public: virtual Store getInitialStore() { return VBFactory.GetEmptyMap().getRoot(); } + + virtual Store RemoveDeadBindings(Store store, Stmt* Loc, + const LiveVariables& Live, + DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols, + DeadSymbolsTy& DSymbols); + + static inline VarBindingsTy GetVarBindings(Store store) { + return VarBindingsTy(static_cast(store)); + } }; } // end anonymous namespace @@ -108,34 +118,85 @@ RVal BasicStoreManager::GetRVal(Store St, LVal LV, QualType T) { return UnknownVal(); } -Store BasicStoreManager::SetRVal(Store St, LVal LV, RVal V) { - - VarBindingsTy B(static_cast(St)); - - switch (LV.getSubKind()) { - - case lval::DeclValKind: +Store BasicStoreManager::SetRVal(Store store, LVal LV, RVal V) { + switch (LV.getSubKind()) { + case lval::DeclValKind: { + VarBindingsTy B = GetVarBindings(store); return V.isUnknown() ? VBFactory.Remove(B,cast(LV).getDecl()).getRoot() : VBFactory.Add(B, cast(LV).getDecl(), V).getRoot(); - + } default: assert ("SetRVal for given LVal type not yet implemented."); - return St; + return store; } } -Store BasicStoreManager::Remove(Store St, LVal LV) { - - VarBindingsTy B(static_cast(St)); - +Store BasicStoreManager::Remove(Store store, LVal LV) { switch (LV.getSubKind()) { - - case lval::DeclValKind: + case lval::DeclValKind: { + VarBindingsTy B = GetVarBindings(store); return VBFactory.Remove(B,cast(LV).getDecl()).getRoot(); - + } default: assert ("Remove for given LVal type not yet implemented."); - return St; + return store; } } + +Store BasicStoreManager::RemoveDeadBindings(Store store, + Stmt* Loc, + const LiveVariables& Liveness, + DeclRootsTy& DRoots, + LiveSymbolsTy& LSymbols, + DeadSymbolsTy& DSymbols) { + + VarBindingsTy B = GetVarBindings(store); + typedef RVal::symbol_iterator symbol_iterator; + + // Iterate over the variable bindings. + for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I) + if (Liveness.isLive(Loc, I.getKey())) { + DRoots.push_back(I.getKey()); + RVal X = I.getData(); + + for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI) + LSymbols.insert(*SI); + } + + // Scan for live variables and live symbols. + llvm::SmallPtrSet Marked; + + while (!DRoots.empty()) { + ValueDecl* V = DRoots.back(); + DRoots.pop_back(); + + if (Marked.count(V)) + continue; + + Marked.insert(V); + + RVal X = GetRVal(store, lval::DeclVal(cast(V)), QualType()); + + for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI) + LSymbols.insert(*SI); + + if (!isa(X)) + continue; + + const lval::DeclVal& LVD = cast(X); + DRoots.push_back(LVD.getDecl()); + } + + // Remove dead variable bindings. + for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I) + if (!Marked.count(I.getKey())) { + store = Remove(store, lval::DeclVal(I.getKey())); + RVal X = I.getData(); + + for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI) + if (!LSymbols.count(*SI)) DSymbols.insert(*SI); + } + + return store; +} diff --git a/clang/lib/Analysis/ValueState.cpp b/clang/lib/Analysis/ValueState.cpp index 72ff498adbe2..ca78faf34911 100644 --- a/clang/lib/Analysis/ValueState.cpp +++ b/clang/lib/Analysis/ValueState.cpp @@ -33,20 +33,21 @@ const llvm::APSInt* ValueState::getSymVal(SymbolID sym) const { const ValueState* ValueStateManager::RemoveDeadBindings(const ValueState* St, Stmt* Loc, const LiveVariables& Liveness, - DeadSymbolsTy& DeadSymbols) { + DeadSymbolsTy& DSymbols) { // This code essentially performs a "mark-and-sweep" of the VariableBindings. // The roots are any Block-level exprs and Decls that our liveness algorithm // tells us are live. We then see what Decls they may reference, and keep // those around. This code more than likely can be made faster, and the // frequency of which this method is called should be experimented with - // for optimum performance. - - llvm::SmallVector WList; - llvm::SmallPtrSet Marked; - llvm::SmallSet MarkedSymbols; + // for optimum performance. + DRoots.clear(); + StoreManager::LiveSymbolsTy LSymbols; ValueState NewSt = *St; + + // FIXME: Put this in environment. + // Clean up the environment. // Drop bindings for subexpressions. NewSt.Env = EnvMgr.RemoveSubExprBindings(NewSt.Env); @@ -62,12 +63,12 @@ ValueStateManager::RemoveDeadBindings(const ValueState* St, Stmt* Loc, if (isa(X)) { lval::DeclVal LV = cast(X); - WList.push_back(LV.getDecl()); + DRoots.push_back(LV.getDecl()); } for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); SI != SE; ++SI) { - MarkedSymbols.insert(*SI); + LSymbols.insert(*SI); } } else { @@ -80,69 +81,18 @@ ValueStateManager::RemoveDeadBindings(const ValueState* St, Stmt* Loc, } } - // Iterate over the variable bindings. - - for (ValueState::vb_iterator I = St->vb_begin(), E = St->vb_end(); I!=E ; ++I) - if (Liveness.isLive(Loc, I.getKey())) { - WList.push_back(I.getKey()); - - RVal X = I.getData(); - - for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); - SI != SE; ++SI) { - MarkedSymbols.insert(*SI); - } - } - - // Perform the mark-and-sweep. - - while (!WList.empty()) { - - ValueDecl* V = WList.back(); - WList.pop_back(); - - if (Marked.count(V)) - continue; - - Marked.insert(V); - - RVal X = GetRVal(St, lval::DeclVal(cast(V))); - - for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); - SI != SE; ++SI) { - MarkedSymbols.insert(*SI); - } - - if (!isa(X)) - continue; - - const lval::DeclVal& LVD = cast(X); - WList.push_back(LVD.getDecl()); - } + // Clean up the store. + DSymbols.clear(); + NewSt.St = StMgr->RemoveDeadBindings(St->getStore(), Loc, Liveness, DRoots, + LSymbols, DSymbols); - // Remove dead variable bindings. - - DeadSymbols.clear(); - - for (ValueState::vb_iterator I = St->vb_begin(), E = St->vb_end(); I!=E ; ++I) - if (!Marked.count(I.getKey())) { - NewSt.St = StMgr->Remove(NewSt.St, lval::DeclVal(I.getKey())); - - RVal X = I.getData(); - - for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); - SI != SE; ++SI) - if (!MarkedSymbols.count(*SI)) DeadSymbols.insert(*SI); - } - - // Remove dead symbols. - + // Remove the dead symbols from the symbol tracker. for (ValueState::ce_iterator I = St->ce_begin(), E=St->ce_end(); I!=E; ++I) { SymbolID sym = I.getKey(); - if (!MarkedSymbols.count(sym)) { - DeadSymbols.insert(sym); + if (!LSymbols.count(sym)) { + DSymbols.insert(sym); NewSt.ConstEq = CEFactory.Remove(NewSt.ConstEq, sym); } } @@ -151,8 +101,8 @@ ValueStateManager::RemoveDeadBindings(const ValueState* St, Stmt* Loc, SymbolID sym = I.getKey(); - if (!MarkedSymbols.count(sym)) { - DeadSymbols.insert(sym); + if (!LSymbols.count(sym)) { + DSymbols.insert(sym); NewSt.ConstNotEq = CNEFactory.Remove(NewSt.ConstNotEq, sym); } }