[cfe-commits] r42099 - in /cfe/trunk: Analysis/DataflowSolver.h Analysis/UninitializedValues.cpp include/clang/Analysis/DataflowValues.h

Ted Kremenek kremenek at apple.com
Tue Sep 18 11:02:44 PDT 2007


Author: kremenek
Date: Tue Sep 18 13:02:44 2007
New Revision: 42099

URL: http://llvm.org/viewvc/llvm-project?rev=42099&view=rev
Log:
Modified DataFlowValues and DataflowSolver to associate dataflow value
with CFG *edges* instead of blocks.  This will fascilitate dataflow
analyses that are sensitive to block terminators, and also simplifies
some reasoning.

Updated UninitializedValues to comply to this new interface.

Modified:
    cfe/trunk/Analysis/DataflowSolver.h
    cfe/trunk/Analysis/UninitializedValues.cpp
    cfe/trunk/include/clang/Analysis/DataflowValues.h

Modified: cfe/trunk/Analysis/DataflowSolver.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/DataflowSolver.h?rev=42099&r1=42098&r2=42099&view=diff

==============================================================================
--- cfe/trunk/Analysis/DataflowSolver.h (original)
+++ cfe/trunk/Analysis/DataflowSolver.h Tue Sep 18 13:02:44 2007
@@ -61,7 +61,7 @@
 
   typedef typename _DFValuesTy::AnalysisDirTag   AnalysisDirTag;
   typedef typename _DFValuesTy::ValTy            ValTy;
-  typedef typename _DFValuesTy::BlockDataMapTy   BlockDataMapTy;
+  typedef typename _DFValuesTy::EdgeDataMapTy    EdgeDataMapTy;
 
   //===--------------------------------------------------------------------===//
   // External interface: constructing and running the solver.
@@ -75,8 +75,9 @@
   void runOnCFG(const CFG& cfg) {
     // Set initial dataflow values and boundary conditions.
     D.InitializeValues(cfg);     
-    // Tag dispatch to the kind of analysis we do: forward or backwards.
-    SolveDataflowEquations(cfg,typename _DFValuesTy::AnalysisDirTag());    
+    // Solve the dataflow equations.  This will populate D.EdgeDataMap
+    // with dataflow values.
+    SolveDataflowEquations(cfg);    
   }
   
   /// runOnBlock - Computes dataflow values for a given block.
@@ -85,7 +86,7 @@
   ///  only be used for querying the dataflow values within a block with
   ///  and Observer object.
   void runOnBlock(const CFGBlock* B) {
-    if (D.getBlockDataMap().find(B) == D.getBlockDataMap().end())
+    if (!hasData(B,AnalysisDirTag()))
       return;
       
     TransferFuncsTy TF (D.getAnalysisData());
@@ -98,39 +99,11 @@
   
 private:
  
-  /// SolveDataflowEquations (FORWARD ANALYSIS) - Perform the actual
-  ///  worklist algorithm to compute dataflow values.
-  void SolveDataflowEquations(const CFG& cfg, dataflow::forward_analysis_tag) {
-    // Create the worklist.
-    DataflowWorkListTy WorkList;
-    
-    // Enqueue the ENTRY block.
-    WorkList.enqueue(&cfg.getEntry());
-    
-    // Create the state for transfer functions.
-    TransferFuncsTy TF(D.getAnalysisData());
-    
-    // Process the worklist until it is empty.    
-    while (!WorkList.isEmpty()) {
-      const CFGBlock* B = WorkList.dequeue();
-      // If the dataflow values at the block's exit have changed,
-      // enqueue all successor blocks onto the worklist to have
-      // their values updated.
-      if (ProcessBlock(B,TF,AnalysisDirTag()))
-        for (CFGBlock::const_succ_iterator I=B->succ_begin(), E=B->succ_end();
-             I != E; ++I)
-          WorkList.enqueue(*I);    
-    }
-  }       
-  
-  /// SolveDataflowEquations (BACKWARD ANALYSIS) - Perform the actual
+  /// SolveDataflowEquations - Perform the actual
   ///  worklist algorithm to compute dataflow values.  
-  void SolveDataflowEquations(const CFG& cfg, dataflow::backward_analysis_tag) {
-    // Create the worklist.
-    DataflowWorkListTy WorkList;
-    
-    // Enqueue the EXIT block.
-    WorkList.enqueue(&cfg.getExit());
+  void SolveDataflowEquations(const CFG& cfg) {
+
+    EnqueueFirstBlock(cfg,AnalysisDirTag());
     
     // Create the state for transfer functions.
     TransferFuncsTy TF(D.getAnalysisData());
@@ -141,16 +114,22 @@
       // If the dataflow values at the block's entry have changed,
       // enqueue all predecessor blocks onto the worklist to have
       // their values updated.
-      if (ProcessBlock(B,TF,AnalysisDirTag()))
-        for (CFGBlock::const_pred_iterator I=B->pred_begin(), E=B->pred_end();
-             I != E; ++I)
-          WorkList.enqueue(*I);    
+      ProcessBlock(B,TF,AnalysisDirTag());
+      UpdateEdges(B,TF.getVal(),AnalysisDirTag());
     }
   }
   
+  void EnqueueFirstBlock(const CFG& cfg, dataflow::forward_analysis_tag) {
+    WorkList.enqueue(&cfg.getEntry());
+  }
+  
+  void EnqueueFirstBlock(const CFG& cfg, dataflow::backward_analysis_tag) {
+    WorkList.enqueue(&cfg.getExit());
+  }  
+  
   /// ProcessBlock (FORWARD ANALYSIS) - Process the transfer functions
   ///  for a given block based on a forward analysis.
-  bool ProcessBlock(const CFGBlock* B, TransferFuncsTy& TF,
+  void ProcessBlock(const CFGBlock* B, TransferFuncsTy& TF,
                     dataflow::forward_analysis_tag) {
     
     ValTy& V = TF.getVal();
@@ -159,12 +138,12 @@
     V.resetValues(D.getAnalysisData());
     MergeOperatorTy Merge;
   
-    BlockDataMapTy& M = D.getBlockDataMap();
+    EdgeDataMapTy& M = D.getEdgeDataMap();
     bool firstMerge = true;
   
     for (CFGBlock::const_pred_iterator I=B->pred_begin(), 
                                       E=B->pred_end(); I!=E; ++I) {
-      typename BlockDataMapTy::iterator BI = M.find(*I);
+      typename EdgeDataMapTy::iterator BI = M.find(CFG::Edge(*I,B));
       if (BI != M.end()) {
         if (firstMerge) {
           firstMerge = false;
@@ -177,14 +156,12 @@
 
     // Process the statements in the block in the forward direction.
     for (CFGBlock::const_iterator I=B->begin(), E=B->end(); I!=E; ++I)
-      TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
-      
-    return UpdateBlockValue(B,V);
+      TF.BlockStmt_Visit(const_cast<Stmt*>(*I));      
   }
   
   /// ProcessBlock (BACKWARD ANALYSIS) - Process the transfer functions
   ///  for a given block based on a forward analysis.
-  bool ProcessBlock(const CFGBlock* B, TransferFuncsTy& TF,
+  void ProcessBlock(const CFGBlock* B, TransferFuncsTy& TF,
                     dataflow::backward_analysis_tag) {
     
     ValTy& V = TF.getVal();
@@ -193,12 +170,12 @@
     V.resetValues(D.getAnalysisData());
     MergeOperatorTy Merge;
     
-    BlockDataMapTy& M = D.getBlockDataMap();
+    EdgeDataMapTy& M = D.getEdgeDataMap();
     bool firstMerge = true;
 
     for (CFGBlock::const_succ_iterator I=B->succ_begin(), 
                                        E=B->succ_end(); I!=E; ++I) {
-      typename BlockDataMapTy::iterator BI = M.find(*I);
+      typename EdgeDataMapTy::iterator BI = M.find(CFG::Edge(B,*I));
       if (BI != M.end()) {
         if (firstMerge) {
           firstMerge = false;
@@ -211,34 +188,81 @@
     
     // Process the statements in the block in the forward direction.
     for (CFGBlock::const_reverse_iterator I=B->begin(), E=B->end(); I!=E; ++I)
-      TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
-    
-    return UpdateBlockValue(B,V);                        
+      TF.BlockStmt_Visit(const_cast<Stmt*>(*I));    
+  }
+
+  /// UpdateEdges (FORWARD ANALYSIS) - After processing the transfer
+  ///   functions for a block, update the dataflow value associated with the
+  ///   block's outgoing edges.  Enqueue any successor blocks for an
+  ///   outgoing edge whose value has changed.  
+  void UpdateEdges(const CFGBlock* B, ValTy& V,dataflow::forward_analysis_tag) {    
+    for (CFGBlock::const_succ_iterator I=B->succ_begin(), E=B->succ_end();
+          I!=E; ++I) {
+                    
+      CFG::Edge E(B,*I);
+      UpdateEdgeValue(E,V,*I);
+    }
   }
   
-  /// UpdateBlockValue - After processing the transfer functions for a block,
-  ///  update the dataflow value associated with the block.  Return true
-  ///  if the block's value has changed.  We do lazy instantiation of block
-  ///  values, so if the block value has not been previously computed we
-  ///  obviously return true.
-  bool UpdateBlockValue(const CFGBlock* B, ValTy& V) {
-    BlockDataMapTy& M = D.getBlockDataMap();
-    typename BlockDataMapTy::iterator I = M.find(B);
-    
+  /// UpdateEdges (BACKWARD ANALYSIS) - After processing the transfer
+  ///   functions for a block, update the dataflow value associated with the
+  ///   block's incoming edges.  Enqueue any predecessor blocks for an
+  ///   outgoing edge whose value has changed.  
+  void UpdateEdges(const CFGBlock* B, ValTy& V,dataflow::backward_analysis_tag){      
+    for (CFGBlock::const_pred_iterator I=B->succ_begin(), E=B->succ_end();
+         I!=E; ++I) {
+      
+      CFG::Edge E(*I,B);
+      UpdateEdgeValue(E,V,*I);
+    }
+  }
+  
+  /// UpdateEdgeValue - Update the value associated with a given edge.
+  void UpdateEdgeValue(CFG::Edge& E, ValTy& V, const CFGBlock* TargetBlock) {
+  
+    EdgeDataMapTy& M = D.getEdgeDataMap();
+    typename EdgeDataMapTy::iterator I = M.find(E);
+      
     if (I == M.end()) {
-      M[B].copyValues(V);
-      return true;
+      // First value for this edge.
+      M[E].copyValues(V);
+      WorkList.enqueue(TargetBlock);
     }
     else if (!V.equal(I->second)) {
       I->second.copyValues(V);
-      return true;
+      WorkList.enqueue(TargetBlock);
     }
+  }
+  
+  /// hasData (FORWARD ANALYSIS) - Is there any dataflow values associated
+  ///  with the incoming edges of a block?
+  bool hasData(const CFGBlock* B, dataflow::forward_analysis_tag) {  
+    EdgeDataMapTy& M = D.getEdgeDataMap();
+
+    for (CFGBlock::const_pred_iterator I=B->pred_begin(), E=B->pred_end();
+         I!=E; ++I)
+      if (M.find(CFG::Edge(*I,B)) != M.end())
+        return true;
+        
+    return false;
+  }
+  
+  /// hasData (BACKWARD ANALYSIS) - Is there any dataflow values associated
+  ///  with the outgoing edges of a block?
+  bool hasData(const CFGBlock* B, dataflow::backward_analysis_tag) {  
+    EdgeDataMapTy& M = D.getEdgeDataMap();
+    
+    for (CFGBlock::const_succ_iterator I=B->succ_begin(), E=B->succ_end();
+         I!=E; ++I)
+      if (M.find(CFG::Edge(B,*I)) != M.end())
+        return true;
     
     return false;
   }
 
 private:
   DFValuesTy& D;
+  DataflowWorkListTy WorkList;
 };  
   
 

Modified: cfe/trunk/Analysis/UninitializedValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/UninitializedValues.cpp?rev=42099&r1=42098&r2=42099&view=diff

==============================================================================
--- cfe/trunk/Analysis/UninitializedValues.cpp (original)
+++ cfe/trunk/Analysis/UninitializedValues.cpp Tue Sep 18 13:02:44 2007
@@ -73,10 +73,6 @@
   for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
     for (CFGBlock::const_iterator BI=I->begin(), BE=I->end(); BI!=BE; ++BI)
       R.BlockStmt_Visit(*BI);
-  
-  // Initialize the values of the last block.
-//  UninitializedValues::ValTy& V = getBlockDataMap()[&cfg.getEntry()];
-//  V.resetValues(getAnalysisData());
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/include/clang/Analysis/DataflowValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/DataflowValues.h?rev=42099&r1=42098&r2=42099&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/DataflowValues.h (original)
+++ cfe/trunk/include/clang/Analysis/DataflowValues.h Tue Sep 18 13:02:44 2007
@@ -19,22 +19,57 @@
 #include "clang/AST/CFG.h"
 #include "llvm/ADT/DenseMap.h"
 
-namespace clang {
+//===----------------------------------------------------------------------===//
+// DenseMapInfo for CFG::Edge for use with DenseMap
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+  
+  template <> struct DenseMapInfo<clang::CFG::Edge> {
+    static inline clang::CFG::Edge getEmptyKey() { 
+      return clang::CFG::Edge(NULL,NULL); 
+    }
+    
+    static inline clang::CFG::Edge getTombstoneKey() {
+      return clang::CFG::Edge(NULL,reinterpret_cast<clang::CFGBlock*>(-1));      
+    }
+    
+    static unsigned getHashValue(const clang::CFG::Edge& E) {
+      const clang::CFGBlock* P1 = E.getSrc();
+      const clang::CFGBlock* P2 = E.getDst();  
+      return (reinterpret_cast<unsigned>(P1) >> 4) ^
+      (reinterpret_cast<unsigned>(P1) >> 9) ^
+      (reinterpret_cast<unsigned>(P2) >> 5) ^
+      (reinterpret_cast<unsigned>(P2) >> 10);
+    }
+    
+    static bool isEqual(const clang::CFG::Edge& LHS,
+                        const clang::CFG::Edge& RHS) {                        
+      return LHS == RHS;
+    }
+    
+    static bool isPod() { return true; }
+  };
+  
+} // end namespace llvm
 
+//===----------------------------------------------------------------------===//
+/// Dataflow Directional Tag Classes.  These are used for tag dispatching
+///  within the dataflow solver/transfer functions to determine what direction
+///  a dataflow analysis flows.
+//===----------------------------------------------------------------------===//   
+
+namespace clang {
 namespace dataflow {
-  
-  //===----------------------------------------------------------------------===//
-  /// Dataflow Directional Tag Classes.  These are used for tag dispatching
-  ///  within the dataflow solver/transfer functions to determine what direction
-  ///  a dataflow analysis flows.
-  //===----------------------------------------------------------------------===//   
-  
   struct forward_analysis_tag {};
   struct backward_analysis_tag {};
-  
 } // end namespace dataflow
     
 
+//===----------------------------------------------------------------------===//
+/// DataflowValues.  Container class to store dataflow values for a CFG.
+//===----------------------------------------------------------------------===//   
+  
 template <typename ValueTypes,
           typename _AnalysisDirTag = dataflow::forward_analysis_tag >
 class DataflowValues {
@@ -46,8 +81,8 @@
 public:
   typedef typename ValueTypes::ValTy               ValTy;
   typedef typename ValueTypes::AnalysisDataTy      AnalysisDataTy;  
-  typedef _AnalysisDirTag                          AnalysisDirTag;  
-  typedef llvm::DenseMap<const CFGBlock*, ValTy>   BlockDataMapTy;
+  typedef _AnalysisDirTag                          AnalysisDirTag;
+  typedef llvm::DenseMap<CFG::Edge, ValTy>         EdgeDataMapTy;
 
   //===--------------------------------------------------------------------===//
   // Predicates.
@@ -55,19 +90,15 @@
 
 public:
   /// isForwardAnalysis - Returns true if the dataflow values are computed
-  ///  from a forward analysis.  If this returns true, the value returned
-  ///  from getBlockData() is the dataflow values associated with the END of
-  ///  the block.
+  ///  from a forward analysis.
   bool isForwardAnalysis() { return isForwardAnalysis(AnalysisDirTag()); }
   
   /// isBackwardAnalysis - Returns true if the dataflow values are computed
-  ///  from a backward analysis.  If this returns true, the value returned
-  ///  from getBlockData() is the dataflow values associated with the ENTRY of
-  ///  the block.
+  ///  from a backward analysis.
   bool isBackwardAnalysis() { return !isForwardAnalysis(); }
   
 private:
-  bool isForwardAnalysis(dataflow::forward_analysis_tag) { return true; }
+  bool isForwardAnalysis(dataflow::forward_analysis_tag)  { return true; }
   bool isForwardAnalysis(dataflow::backward_analysis_tag) { return false; }  
   
   //===--------------------------------------------------------------------===//
@@ -79,25 +110,25 @@
   ///  dataflow analysis.  This method is usually specialized by subclasses.
   void InitializeValues(const CFG& cfg) {};  
 
-  /// getBlockData - Retrieves the dataflow values associated with a 
+  /// getEdgeData - Retrieves the dataflow values associated with a 
   ///  specified CFGBlock.  If the dataflow analysis is a forward analysis,
   ///  this data is associated with the END of the block.  If the analysis
   ///  is a backwards analysis, it is associated with the ENTRY of the block.
-  ValTy& getBlockData(const CFGBlock* B) {
-    typename BlockDataMapTy::iterator I = BlockDataMap.find(B);
-    assert (I != BlockDataMap.end() && "No data associated with CFGBlock.");
+  ValTy& getEdgeData(const CFG::Edge& E) {
+    typename EdgeDataMapTy::iterator I = EdgeDataMap.find(E);
+    assert (I != EdgeDataMap.end() && "No data associated with Edge.");
     return I->second;
   }
   
-  const ValTy& getBlockData(const CFGBlock*) const {
-    return reinterpret_cast<DataflowValues*>(this)->getBlockData();
+  const ValTy& getEdgeData(const CFG::Edge& E) const {
+    return reinterpret_cast<DataflowValues*>(this)->getEdgeData(E);
   }  
   
-  /// getBlockDataMap - Retrieves the internal map between CFGBlocks and
+  /// getEdgeDataMap - Retrieves the internal map between CFGBlocks and
   ///  dataflow values.  Usually used by a dataflow solver to compute
   ///  values for blocks.
-  BlockDataMapTy& getBlockDataMap() { return BlockDataMap; }
-  const BlockDataMapTy& getBlockDataMap() const { return BlockDataMap; }
+  EdgeDataMapTy& getEdgeDataMap() { return EdgeDataMap; }
+  const EdgeDataMapTy& getEdgeDataMap() const { return EdgeDataMap; }
 
   /// getAnalysisData - Retrieves the meta data associated with a 
   ///  dataflow analysis for analyzing a particular CFG.  
@@ -111,7 +142,7 @@
   //===--------------------------------------------------------------------===//
   
 protected:
-  BlockDataMapTy     BlockDataMap;
+  EdgeDataMapTy      EdgeDataMap;
   AnalysisDataTy     AnalysisData;
 };          
 





More information about the cfe-commits mailing list