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.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47010 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Analysis/GRBlockCounter.cpp b/Analysis/GRBlockCounter.cpp
new file mode 100644
index 0000000..def87c2
--- /dev/null
+++ b/Analysis/GRBlockCounter.cpp
@@ -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());
+}
diff --git a/Analysis/GRConstants.cpp b/Analysis/GRConstants.cpp
index 4ae9077..8b94aaa 100644
--- a/Analysis/GRConstants.cpp
+++ b/Analysis/GRConstants.cpp
@@ -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);
 }
diff --git a/Analysis/GREngine.cpp b/Analysis/GREngine.cpp
index e3b238a..9858f24 100644
--- a/Analysis/GREngine.cpp
+++ b/Analysis/GREngine.cpp
@@ -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);
 }