Moved RemoveDeadBindings logic for the contents of 'Store' to a virtual RemoveDeadBindings method in StoreManager.

llvm-svn: 53726
This commit is contained in:
Ted Kremenek 2008-07-17 18:38:48 +00:00
parent 9ace803308
commit 88a6b7fa80
4 changed files with 122 additions and 90 deletions

View File

@ -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 <vector>
namespace clang {
typedef const void* Store;
class LiveVariables;
class Stmt;
class StoreManager {
public:
typedef llvm::SmallSet<SymbolID, 20> LiveSymbolsTy;
typedef llvm::DenseSet<SymbolID> DeadSymbolsTy;
typedef std::vector<ValueDecl*> 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

View File

@ -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<llvm::APSInt*> IntSetTy;
typedef llvm::ImmutableMap<SymbolID,IntSetTy> ConstNotEqTy;
typedef llvm::ImmutableMap<SymbolID,const llvm::APSInt*> 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<VarDecl*,RVal> VarBindingsTy;
@ -140,6 +140,7 @@ public:
VarBindingsTy B(static_cast<const VarBindingsTy::TreeTy*>(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<ValueState*> {
class ValueStateManager {
private:
EnvironmentManager EnvMgr;
llvm::OwningPtr<StoreManager> 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<SymbolID> 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;

View File

@ -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<const VarBindingsTy::TreeTy*>(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<const VarBindingsTy::TreeTy*>(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<lval::DeclVal>(LV).getDecl()).getRoot()
: VBFactory.Add(B, cast<lval::DeclVal>(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<const VarBindingsTy::TreeTy*>(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<lval::DeclVal>(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<ValueDecl*, 10> 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<VarDecl>(V)), QualType());
for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
LSymbols.insert(*SI);
if (!isa<lval::DeclVal>(X))
continue;
const lval::DeclVal& LVD = cast<lval::DeclVal>(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;
}

View File

@ -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<ValueDecl*, 10> WList;
llvm::SmallPtrSet<ValueDecl*, 10> Marked;
llvm::SmallSet<SymbolID, 20> 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<lval::DeclVal>(X)) {
lval::DeclVal LV = cast<lval::DeclVal>(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<VarDecl>(V)));
for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
SI != SE; ++SI) {
MarkedSymbols.insert(*SI);
}
if (!isa<lval::DeclVal>(X))
continue;
const lval::DeclVal& LVD = cast<lval::DeclVal>(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);
}
}