[cfe-commits] r47010 - in /cfe/trunk: Analysis/GRBlockCounter.cpp Analysis/GRConstants.cpp Analysis/GREngine.cpp include/clang/Analysis/PathSensitive/GRBlockCounter.h include/clang/Analysis/PathSensitive/GREngine.h include/clang/Analysis/PathSensitive/GRWorkList.h

Ted Kremenek kremenek at apple.com
Tue Feb 12 10:08:19 PST 2008


Author: kremenek
Date: Tue Feb 12 12:08:17 2008
New Revision: 47010

URL: http://llvm.org/viewvc/llvm-project?rev=47010&view=rev
Log:
Added GRBlockCounter class, which tracks the number of times blocks
have been visited in a path.  Added GRBlockCounter as an item to be
enqueued to the worklist.

Modified "ProcessBranch" in GRConstants to prune branches with symbolic
conditions that have been already taken.

Added:
    cfe/trunk/Analysis/GRBlockCounter.cpp
    cfe/trunk/include/clang/Analysis/PathSensitive/GRBlockCounter.h
Modified:
    cfe/trunk/Analysis/GRConstants.cpp
    cfe/trunk/Analysis/GREngine.cpp
    cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h
    cfe/trunk/include/clang/Analysis/PathSensitive/GRWorkList.h

Added: cfe/trunk/Analysis/GRBlockCounter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRBlockCounter.cpp?rev=47010&view=auto

==============================================================================
--- cfe/trunk/Analysis/GRBlockCounter.cpp (added)
+++ cfe/trunk/Analysis/GRBlockCounter.cpp Tue Feb 12 12:08:17 2008
@@ -0,0 +1,54 @@
+//==- GRBlockCounter.h - ADT for counting block visits -------------*- C++ -*-//
+//             
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines GRBlockCounter, an abstract data type used to count
+//  the number of times a given block has been visited along a path
+//  analyzed by GREngine.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/GRBlockCounter.h"
+#include "llvm/ADT/ImmutableMap.h"
+
+using namespace clang;
+
+typedef llvm::ImmutableMap<unsigned,unsigned> CountMap;
+
+static inline CountMap GetMap(void* D) {
+  return CountMap(static_cast<CountMap::TreeTy*>(D));
+}
+
+static inline CountMap::Factory& GetFactory(void* F) {
+  return *static_cast<CountMap::Factory*>(F);
+}
+
+unsigned GRBlockCounter::getNumVisited(unsigned BlockID) const {
+  CountMap M = GetMap(Data);
+  CountMap::TreeTy* T = M.SlimFind(BlockID);
+  return T ? T->getValue().second : 0;
+}
+
+GRBlockCounter::Factory::Factory(llvm::BumpPtrAllocator& Alloc) {
+  F = new CountMap::Factory(Alloc);
+}
+
+GRBlockCounter::Factory::~Factory() {
+  delete static_cast<CountMap*>(F);
+}
+
+GRBlockCounter
+GRBlockCounter::Factory::IncrementCount(GRBlockCounter BC, unsigned BlockID) {
+  return GRBlockCounter(GetFactory(F).Add(GetMap(BC.Data), BlockID,
+                                        BC.getNumVisited(BlockID)+1).getRoot());
+}
+
+GRBlockCounter
+GRBlockCounter::Factory::GetEmptyCounter() {
+  return GRBlockCounter(GetFactory(F).GetEmptyMap().getRoot());
+}

Modified: cfe/trunk/Analysis/GRConstants.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRConstants.cpp?rev=47010&r1=47009&r2=47010&view=diff

==============================================================================
--- cfe/trunk/Analysis/GRConstants.cpp (original)
+++ cfe/trunk/Analysis/GRConstants.cpp Tue Feb 12 12:08:17 2008
@@ -375,23 +375,45 @@
     }      
   }
 
-  // Process the true branch.
-  bool isFeasible = true;
+  // Get the current block counter.
+  GRBlockCounter BC = builder.getBlockCounter();
+    
+  unsigned NumVisited = BC.getNumVisited(builder.getTargetBlock(true)->getBlockID());
   
-  StateTy St = Assume(PrevState, V, true, isFeasible);
+  if (isa<nonlval::ConcreteInt>(V) || 
+      BC.getNumVisited(builder.getTargetBlock(true)->getBlockID()) < 1) {
+    
+    // Process the true branch.
 
-  if (isFeasible)
-    builder.generateNode(St, true);
-  else {
-    builder.markInfeasible(true);
-    isFeasible = true;
+    bool isFeasible = true;
+    
+    StateTy St = Assume(PrevState, V, true, isFeasible);
+
+    if (isFeasible)
+      builder.generateNode(St, true);
+    else
+      builder.markInfeasible(true);
   }
+  else
+    builder.markInfeasible(true);
   
-  // Process the false branch.  
-  St = Assume(PrevState, V, false, isFeasible);
+  NumVisited = BC.getNumVisited(builder.getTargetBlock(true)->getBlockID());
+
   
-  if (isFeasible)
-    builder.generateNode(St, false);
+  if (isa<nonlval::ConcreteInt>(V) || 
+      BC.getNumVisited(builder.getTargetBlock(false)->getBlockID()) < 1) {
+    
+    // Process the false branch.  
+    
+    bool isFeasible = false;
+    
+    StateTy St = Assume(PrevState, V, false, isFeasible);
+    
+    if (isFeasible)
+      builder.generateNode(St, false);
+    else
+      builder.markInfeasible(false);
+  }
   else
     builder.markInfeasible(false);
 }

Modified: cfe/trunk/Analysis/GREngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GREngine.cpp?rev=47010&r1=47009&r2=47010&view=diff

==============================================================================
--- cfe/trunk/Analysis/GREngine.cpp (original)
+++ cfe/trunk/Analysis/GREngine.cpp Tue Feb 12 12:08:17 2008
@@ -71,6 +71,9 @@
     // starting location in the function.
     BlockEdge StartLoc(getCFG(), Entry, Succ);
     
+    // Set the current block counter to being empty.
+    WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
+    
     // Generate the root.
     GenerateNode(StartLoc, getInitialState());
   }
@@ -78,6 +81,11 @@
   while (Steps && WList->hasWork()) {
     --Steps;
     const GRWorkListUnit& WU = WList->Dequeue();
+    
+    // Set the current block counter.
+    WList->setBlockCounter(WU.getBlockCounter());
+
+    // Retrieve the node.
     ExplodedNodeImpl* Node = WU.getNode();
     
     // Dispatch on the location type.
@@ -138,6 +146,12 @@
 void GREngineImpl::HandleBlockEntrance(const BlockEntrance& L,
                                        ExplodedNodeImpl* Pred) {
   
+  // Increment the block counter.
+  GRBlockCounter Counter = WList->getBlockCounter();
+  Counter = BCounterFactory.IncrementCount(Counter, L.getBlock()->getBlockID());
+  WList->setBlockCounter(Counter);
+  
+  // Process the entrance of the block.  
   if (Stmt* S = L.getFirstStmt()) {
     GRStmtNodeBuilderImpl Builder(L.getBlock(), 0, Pred, this);
     ProcessStmt(S, Builder);
@@ -196,7 +210,7 @@
                                 ExplodedNodeImpl* Pred) {
   assert (B->succ_size() == 2);
 
-  GRBranchNodeBuilderImpl Builder(B, *(B->succ_begin()), *(B->succ_begin()+1), 
+  GRBranchNodeBuilderImpl Builder(B, *(B->succ_begin()), *(B->succ_begin()+1),
                                   Pred, this);
   
   ProcessBranch(Cond, Term, Builder);
@@ -244,7 +258,7 @@
   }
   
   // Only add 'Node' to the worklist if it was freshly generated.
-  if (IsNew) WList->Enqueue(GRWorkListUnit(Node));
+  if (IsNew) WList->Enqueue(Node);
 }
 
 GRStmtNodeBuilderImpl::GRStmtNodeBuilderImpl(CFGBlock* b, unsigned idx,
@@ -325,5 +339,5 @@
   if (!GeneratedFalse) generateNodeImpl(Pred->State, false);
   
   for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
-    if (!(*I)->isSink()) Eng.WList->Enqueue(GRWorkListUnit(*I));
+    if (!(*I)->isSink()) Eng.WList->Enqueue(*I);
 }

Added: cfe/trunk/include/clang/Analysis/PathSensitive/GRBlockCounter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRBlockCounter.h?rev=47010&view=auto

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRBlockCounter.h (added)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRBlockCounter.h Tue Feb 12 12:08:17 2008
@@ -0,0 +1,50 @@
+//==- GRBlockCounter.h - ADT for counting block visits -------------*- C++ -*-//
+//             
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines GRBlockCounter, an abstract data type used to count
+//  the number of times a given block has been visited along a path
+//  analyzed by GREngine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_GRBLOCKCOUNTER
+#define LLVM_CLANG_ANALYSIS_GRBLOCKCOUNTER
+
+namespace llvm {
+  class BumpPtrAllocator;
+}
+
+namespace clang {
+
+class GRBlockCounter {
+  void* Data;
+  
+  GRBlockCounter(void* D) : Data(D) {}  
+
+public:
+  GRBlockCounter() : Data(0) {}
+  
+  unsigned getNumVisited(unsigned BlockID) const;
+  
+  class Factory {
+    void* F;
+  public:
+    Factory(llvm::BumpPtrAllocator& Alloc);
+    ~Factory();
+    
+    GRBlockCounter GetEmptyCounter();
+    GRBlockCounter IncrementCount(GRBlockCounter BC, unsigned BlockID);
+  };
+  
+  friend class Factory;
+};
+
+} // end clang namespace
+  
+#endif

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h?rev=47010&r1=47009&r2=47010&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h Tue Feb 12 12:08:17 2008
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 //
 //  This file defines a generic engine for intraprocedural, path-sensitive,
-//  dataflow analysis via graph reachability engine.
+//  dataflow analysis via graph reachability.
 //
 //===----------------------------------------------------------------------===//
 
@@ -17,6 +17,7 @@
 
 #include "clang/Analysis/PathSensitive/ExplodedGraph.h"
 #include "clang/Analysis/PathSensitive/GRWorkList.h"
+#include "clang/Analysis/PathSensitive/GRBlockCounter.h"
 #include "llvm/ADT/OwningPtr.h"
 
 namespace clang {
@@ -47,7 +48,12 @@
   ///  the order that nodes are processed.
   GRWorkList* WList;
   
-  void GenerateNode(const ProgramPoint& Loc, void* State, 
+  /// BCounterFactory - A factory object for created GRBlockCounter objects.
+  ///   These are used to record for key nodes in the ExplodedGraph the
+  ///   number of times different CFGBlocks have been visited along a path.
+  GRBlockCounter::Factory BCounterFactory;
+  
+  void GenerateNode(const ProgramPoint& Loc, void* State,
                     ExplodedNodeImpl* Pred = NULL);
   
   /// getInitialState - Gets the void* representing the initial 'state'
@@ -78,7 +84,8 @@
   GREngineImpl& operator=(const GREngineImpl&);
   
 protected:  
-  GREngineImpl(ExplodedGraphImpl* g, GRWorkList* wl) : G(g), WList(wl) {}
+  GREngineImpl(ExplodedGraphImpl* g, GRWorkList* wl)
+    : G(g), WList(wl), BCounterFactory(g->getAllocator()) {}
   
 public:
   /// ExecuteWorkList - Run the worklist algorithm for a maximum number of
@@ -183,8 +190,13 @@
   
   ExplodedNodeImpl* getPredecessor() const { return Pred; }
   const ExplodedGraphImpl& getGraph() const { return *Eng.G; }
+  GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
     
-  ExplodedNodeImpl* generateNodeImpl(void* State, bool branch);  
+  ExplodedNodeImpl* generateNodeImpl(void* State, bool branch);
+  
+  CFGBlock* getTargetBlock(bool branch) const {
+    return branch ? DstT : DstF;
+  }    
   
   void markInfeasible(bool branch) {
     if (branch) GeneratedTrue = true;
@@ -221,6 +233,14 @@
     return static_cast<NodeTy*>(NB.generateNodeImpl(state, branch));
   }
   
+  GRBlockCounter getBlockCounter() const {
+    return NB.getBlockCounter();
+  }
+  
+  CFGBlock* getTargetBlock(bool branch) const {
+    return NB.getTargetBlock(branch);
+  }
+  
   inline void markInfeasible(bool branch) {
     NB.markInfeasible(branch);
   }

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRWorkList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRWorkList.h?rev=47010&r1=47009&r2=47010&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRWorkList.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRWorkList.h Tue Feb 12 12:08:17 2008
@@ -15,39 +15,59 @@
 #ifndef LLVM_CLANG_ANALYSIS_GRWORKLIST
 #define LLVM_CLANG_ANALYSIS_GRWORKLIST
 
+#include "clang/Analysis/PathSensitive/GRBlockCounter.h"
+
 namespace clang {  
 
 class ExplodedNodeImpl;
   
 class GRWorkListUnit {
   ExplodedNodeImpl* Node;
+  GRBlockCounter Counter;
   CFGBlock* Block;
   unsigned BlockIdx;
   
 public:
-  GRWorkListUnit(ExplodedNodeImpl* N, CFGBlock* B, unsigned idx)
-  : Node(N), Block(B), BlockIdx(idx) {}
-  
-  explicit GRWorkListUnit(ExplodedNodeImpl* N)
-  : Node(N), Block(NULL), BlockIdx(0) {}
-  
-  ExplodedNodeImpl* getNode()  const { return Node; }    
-  CFGBlock*         getBlock() const { return Block; }
-  unsigned          getIndex() const { return BlockIdx; }
+  GRWorkListUnit(ExplodedNodeImpl* N, GRBlockCounter C,
+                 CFGBlock* B, unsigned idx)
+  : Node(N),
+    Counter(C),
+    Block(B),
+    BlockIdx(idx) {}
+  
+  explicit GRWorkListUnit(ExplodedNodeImpl* N, GRBlockCounter C)
+  : Node(N),
+    Counter(C),
+    Block(NULL),
+    BlockIdx(0) {}
+  
+  ExplodedNodeImpl* getNode()         const { return Node; }
+  GRBlockCounter    getBlockCounter() const { return Counter; }
+  CFGBlock*         getBlock()        const { return Block; }
+  unsigned          getIndex()        const { return BlockIdx; }
 };
 
 class GRWorkList {
+  GRBlockCounter CurrentCounter;
 public:
   virtual ~GRWorkList();
   virtual bool hasWork() const = 0;
+    
   virtual void Enqueue(const GRWorkListUnit& U) = 0;
 
-  void Enqueue(ExplodedNodeImpl* N, CFGBlock& B, unsigned idx) {
-    Enqueue(GRWorkListUnit(N,&B,idx));
+  void Enqueue(ExplodedNodeImpl* N, CFGBlock& B, unsigned idx) {    
+    Enqueue(GRWorkListUnit(N, CurrentCounter, &B, idx));
+  }
+  
+  void Enqueue(ExplodedNodeImpl* N) {
+    Enqueue(GRWorkListUnit(N, CurrentCounter));
   }
   
   virtual GRWorkListUnit Dequeue() = 0;
   
+  void setBlockCounter(GRBlockCounter C) { CurrentCounter = C; }
+  GRBlockCounter getBlockCounter() const { return CurrentCounter; }
+  
   static GRWorkList* MakeDFS(); 
 };
 } // end clang namespace  





More information about the cfe-commits mailing list