[cfe-commits] r42446 - in /cfe/trunk: Analysis/DeadStores.cpp Analysis/LiveVariables.cpp include/clang/Analysis/LiveVariables.h
Ted Kremenek
kremenek at apple.com
Fri Sep 28 13:38:59 PDT 2007
Author: kremenek
Date: Fri Sep 28 15:38:59 2007
New Revision: 42446
URL: http://llvm.org/viewvc/llvm-project?rev=42446&view=rev
Log:
Significant cleanups and bug-fixes to LiveVariables. Uses new refactored
ExprDeclBitVector class for defining dataflow state.
Modified:
cfe/trunk/Analysis/DeadStores.cpp
cfe/trunk/Analysis/LiveVariables.cpp
cfe/trunk/include/clang/Analysis/LiveVariables.h
Modified: cfe/trunk/Analysis/DeadStores.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/DeadStores.cpp?rev=42446&r1=42445&r2=42446&view=diff
==============================================================================
--- cfe/trunk/Analysis/DeadStores.cpp (original)
+++ cfe/trunk/Analysis/DeadStores.cpp Fri Sep 28 15:38:59 2007
@@ -38,7 +38,7 @@
if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
// Is the variable NOT live? If so, flag a dead store.
- if (!Live(AD,DR->getDecl())) {
+ if (!Live(DR->getDecl(),AD)) {
SourceRange R = B->getRHS()->getSourceRange();
Diags.Report(DR->getSourceRange().Begin(), diag::warn_dead_store,
0, 0, &R, 1);
@@ -50,7 +50,7 @@
for (VarDecl* V = cast<VarDecl>(DS->getDecl()); V != NULL ;
V = cast_or_null<VarDecl>(V->getNextDeclarator())) {
if (Expr* E = V->getInit()) {
- if (!Live(AD,DS->getDecl())) {
+ if (!Live(DS->getDecl(),AD)) {
// Special case: check for initializations with constants.
//
// e.g. : int x = 0;
Modified: cfe/trunk/Analysis/LiveVariables.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/LiveVariables.cpp?rev=42446&r1=42445&r2=42446&view=diff
==============================================================================
--- cfe/trunk/Analysis/LiveVariables.cpp (original)
+++ cfe/trunk/Analysis/LiveVariables.cpp Fri Sep 28 15:38:59 2007
@@ -31,16 +31,18 @@
//===----------------------------------------------------------------------===//
namespace {
-struct RegisterDecls : public CFGRecStmtDeclVisitor<RegisterDecls> {
+class RegisterDeclsExprs : public CFGRecStmtDeclVisitor<RegisterDeclsExprs> {
LiveVariables::AnalysisDataTy& AD;
- void VisitVarDecl(VarDecl* VD) { AD.RegisterDecl(VD); }
-
- RegisterDecls(LiveVariables::AnalysisDataTy& ad) : AD(ad) {}
+public:
+ RegisterDeclsExprs(LiveVariables::AnalysisDataTy& ad) : AD(ad) {}
+
+ void VisitVarDecl(VarDecl* VD) { AD.Register(VD); }
+ void BlockStmt_VisitExpr(Expr* E) { AD.Register(E); }
};
} // end anonymous namespace
void LiveVariables::InitializeValues(const CFG& cfg) {
- RegisterDecls R(getAnalysisData());
+ RegisterDeclsExprs R(getAnalysisData());
cfg.VisitBlockStmts(R);
}
@@ -49,29 +51,38 @@
//===----------------------------------------------------------------------===//
namespace {
+
+static const bool Alive = true;
+static const bool Dead = false;
+
class TransferFuncs : public CFGStmtVisitor<TransferFuncs> {
LiveVariables::AnalysisDataTy& AD;
- LiveVariables::ValTy Live;
+ LiveVariables::ValTy LiveState;
+ bool ExprLiveness;
public:
- TransferFuncs(LiveVariables::AnalysisDataTy& ad) : AD(ad) {}
+ TransferFuncs(LiveVariables::AnalysisDataTy& ad) : AD(ad),
+ ExprLiveness(Dead) {}
- LiveVariables::ValTy& getVal() { return Live; }
+ LiveVariables::ValTy& getVal() { return LiveState; }
void VisitDeclRefExpr(DeclRefExpr* DR);
void VisitBinaryOperator(BinaryOperator* B);
void VisitAssign(BinaryOperator* B);
void VisitDeclStmt(DeclStmt* DS);
void VisitUnaryOperator(UnaryOperator* U);
- void VisitStmt(Stmt* S) { VisitChildren(S); }
+ void VisitStmt(Stmt* S);
+ void BlockStmt_VisitExpr(Expr *E);
+
void Visit(Stmt *S) {
- if (AD.Observer) AD.Observer->ObserveStmt(S,AD,Live);
+ if (AD.Observer) AD.Observer->ObserveStmt(S,AD,LiveState);
static_cast<CFGStmtVisitor<TransferFuncs>*>(this)->Visit(S);
}
};
+
void TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
if (VarDecl* V = dyn_cast<VarDecl>(DR->getDecl()))
- Live.set(AD[V]); // Register a use of the variable.
+ LiveState(V,AD) = Alive;
}
void TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
@@ -93,28 +104,27 @@
if (ParenExpr* P = dyn_cast<ParenExpr>(S)) { S=P->getSubExpr(); continue;}
else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S)) {
// Treat the --/++/& operator as a kill.
- Live.reset(AD[DR->getDecl()]);
- if (AD.Observer) AD.Observer->ObserverKill(DR);
- VisitDeclRefExpr(DR);
+ LiveState(DR->getDecl(),AD) = Dead;
+ if (AD.Observer) { AD.Observer->ObserverKill(DR); }
+ return VisitDeclRefExpr(DR);
}
- else Visit(S);
-
- break;
- }
- break;
+ else return Visit(S);
+ }
+
+ assert (false && "Unreachable.");
default:
- Visit(U->getSubExpr());
- break;
+ return Visit(U->getSubExpr());
}
}
void TransferFuncs::VisitAssign(BinaryOperator* B) {
Stmt* LHS = B->getLHS();
- if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) { // Assigning to a var?
- Live.reset(AD[DR->getDecl()]);
- if (AD.Observer) AD.Observer->ObserverKill(DR);
+ if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) { // Assigning to a var?
+ LiveState(DR->getDecl(),AD) = Dead;
+ if (AD.Observer) { AD.Observer->ObserverKill(DR); }
+
// Handle things like +=, etc., which also generate "uses"
// of a variable. Do this just by visiting the subexpression.
if (B->getOpcode() != BinaryOperator::Assign) Visit(LHS);
@@ -129,21 +139,34 @@
// Declarations effectively "kill" a variable since they cannot
// possibly be live before they are declared.
for (ScopedDecl* D = DS->getDecl(); D != NULL ; D = D->getNextDeclarator())
- Live.reset(AD[D]);
+ LiveState(D,AD) = Dead;
+}
+
+void TransferFuncs::VisitStmt(Stmt* S) {
+ if (AD.isTracked(static_cast<Expr*>(S))) return;
+ else VisitChildren(S);
+}
+
+void TransferFuncs::BlockStmt_VisitExpr(Expr* E) {
+ assert (AD.isTracked(E));
+ static_cast<CFGStmtVisitor<TransferFuncs>*>(this)->Visit(E);
}
+
} // end anonymous namespace
-namespace {
-struct Merge {
- void operator()(LiveVariables::ValTy& Dst, LiveVariables::ValTy& Src) {
- Src |= Dst;
- }
-};
-} // end anonymous namespace
+//===----------------------------------------------------------------------===//
+// Merge operator: if something is live on any successor block, it is live
+// in the current block (a set union).
+//===----------------------------------------------------------------------===//
namespace {
+typedef DeclBitVector_Types::Union Merge;
typedef DataflowSolver<LiveVariables,TransferFuncs,Merge> Solver;
-}
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// External interface to run Liveness analysis.
+//===----------------------------------------------------------------------===//
void LiveVariables::runOnCFG(const CFG& cfg) {
Solver S(*this);
@@ -164,11 +187,11 @@
//
bool LiveVariables::isLive(const CFGBlock* B, const VarDecl* D) const {
- return getBlockData(B)[ getAnalysisData()[D] ];
+ return getBlockData(B)(D,getAnalysisData());
}
bool LiveVariables::isLive(const ValTy& Live, const VarDecl* D) const {
- return Live[ getAnalysisData()[D] ];
+ return Live(D,getAnalysisData());
}
//===----------------------------------------------------------------------===//
@@ -178,8 +201,9 @@
void LiveVariables::dumpLiveness(const ValTy& V, SourceManager& SM) const {
const AnalysisDataTy& AD = getAnalysisData();
- for (AnalysisDataTy::iterator I = AD.begin(), E = AD.end(); I!=E; ++I)
- if (V[I->second]) {
+ for (AnalysisDataTy::decl_iterator I = AD.begin_decl(),
+ E = AD.end_decl(); I!=E; ++I)
+ if (V.getDeclBit(I->second)) {
SourceLocation PhysLoc = SM.getPhysicalLoc(I->first->getLocation());
fprintf(stderr, " %s <%s:%u:%u>\n",
Modified: cfe/trunk/include/clang/Analysis/LiveVariables.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/LiveVariables.h?rev=42446&r1=42445&r2=42446&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/LiveVariables.h (original)
+++ cfe/trunk/include/clang/Analysis/LiveVariables.h Fri Sep 28 15:38:59 2007
@@ -15,9 +15,8 @@
#define LLVM_CLANG_LIVEVARIABLES_H
#include "clang/AST/Decl.h"
+#include "clang/Analysis/ExprDeclBitVector.h"
#include "clang/Analysis/FlowSensitive/DataflowValues.h"
-#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/DenseMap.h"
namespace clang {
@@ -26,80 +25,30 @@
class SourceManager;
struct LiveVariables_ValueTypes {
- //===-----------------------------------------------------===//
- // AnalysisDataTy - Whole-function analysis meta data.
- //===-----------------------------------------------------===//
- class ObserverTy;
-
- class AnalysisDataTy {
- typedef llvm::DenseMap<const VarDecl*, unsigned> VMapTy;
- VMapTy M;
- unsigned NDecls;
- public:
- ObserverTy* Observer;
-
- AnalysisDataTy() : NDecls(0), Observer(NULL) {}
-
- bool Tracked(const VarDecl* VD) const { return M.find(VD) != M.end(); }
- void RegisterDecl(const VarDecl* VD) { if (!Tracked(VD)) M[VD] = NDecls++; }
+ struct ObserverTy;
- unsigned operator[](const VarDecl* VD) const {
- VMapTy::const_iterator I = M.find(VD);
- assert (I != M.end());
- return I->second;
- }
-
- unsigned operator[](const ScopedDecl* S) const {
- return (*this)[cast<VarDecl>(S)];
- }
- unsigned getNumDecls() const { return NDecls; }
-
- typedef VMapTy::const_iterator iterator;
- iterator begin() const { return M.begin(); }
- iterator end() const { return M.end(); }
- };
-
- //===-----------------------------------------------------===//
- // ValTy - Dataflow value.
- //===-----------------------------------------------------===//
- class ValTy {
- llvm::BitVector V;
- public:
- void copyValues(const ValTy& RHS) { V = RHS.V; }
+ // We need to keep track of both declarations and CFGBlock-level expressions,
+ // (so that we don't explore such expressions twice), but we only need
+ // liveness information for declarations (hence
+ // ValTy = DeclBitVector_Types::ValTy instead of
+ // ValTy = ExprDeclBitVector_Types::ValTy).
- bool operator==(const ValTy& RHS) const { return V == RHS.V; }
-
- void resetValues(const AnalysisDataTy& AD) {
- V.resize(AD.getNumDecls());
- V.reset();
- }
-
- llvm::BitVector::reference operator[](unsigned i) {
- assert (i < V.size() && "Liveness bitvector access is out-of-bounds.");
- return V[i];
- }
-
- const llvm::BitVector::reference operator[](unsigned i) const {
- return const_cast<ValTy&>(*this)[i];
- }
-
- bool operator()(const AnalysisDataTy& AD, const ScopedDecl* D) const {
- return (*this)[AD[D]];
- }
-
- ValTy& operator|=(ValTy& RHS) { V |= RHS.V; return *this; }
+ struct AnalysisDataTy : public ExprDeclBitVector_Types::AnalysisDataTy {
+ ObserverTy* Observer;
- void set(unsigned i) { V.set(i); }
- void reset(unsigned i) { V.reset(i); }
+ AnalysisDataTy() : Observer(NULL) {}
};
+
+ // We only keep actual dataflow state for declarations.
+ typedef DeclBitVector_Types::ValTy ValTy;
//===-----------------------------------------------------===//
// ObserverTy - Observer for uninitialized values queries.
//===-----------------------------------------------------===//
- class ObserverTy {
- public:
+
+ struct ObserverTy {
virtual ~ObserverTy() {}
/// ObserveStmt - A callback invoked right before invoking the
More information about the cfe-commits
mailing list