bcraig created this revision.
bcraig added reviewers: zaks.anna, dcoughlin, jordan_rose.
bcraig added a subscriber: cfe-commits.

During the core analysis, ExplodedNodes are added to the ExplodedGraph, and 
those nodes are cached for deduplication purposes.

After core analysis, reports are generated.  Here, trimmed copies of the 
ExplodedGraph are made.  Since the ExplodedGraph has already been deduplicated, 
there is no need to deduplicate again.

This change makes it possible to add ExplodedNodes to an ExplodedGraph without 
the overhead of deduplication.  "Uncached" nodes also cannot be iterated over, 
but none of the report generation code attempts to iterate over all nodes.  
This change reduces the analysis time of a large .C file from 3m43.941s to 
3m40.256s (~1.6% speedup).  It should slightly reduce memory consumption.  
Gains should be roughly proportional to the number (and path length) of static 
analysis warnings.

This patch enables future work that should remove the need for an 
InterExplodedGraphMap inverse map.  I plan on using the (now unused) 
ExplodedNode link to connect new nodes to the original nodes.

http://reviews.llvm.org/D21229

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
  lib/StaticAnalyzer/Core/BugReporter.cpp
  lib/StaticAnalyzer/Core/ExplodedGraph.cpp

Index: lib/StaticAnalyzer/Core/ExplodedGraph.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -336,6 +336,14 @@
   return V;
 }
 
+ExplodedNode *ExplodedGraph::createUncachedNode(const ProgramPoint &L,
+                                                ProgramStateRef State,
+                                                bool IsSink) {
+  NodeTy *V = (NodeTy *) getAllocator().Allocate<NodeTy>();
+  new (V) NodeTy(L, State, IsSink);
+  return V;
+}
+
 std::unique_ptr<ExplodedGraph>
 ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
                     InterExplodedGraphMap *ForwardMap,
@@ -395,8 +403,7 @@
 
     // Create the corresponding node in the new graph and record the mapping
     // from the old node to the new node.
-    ExplodedNode *NewN = G->getNode(N->getLocation(), N->State, N->isSink(),
-                                    nullptr);
+    ExplodedNode *NewN = G->createUncachedNode(N->getLocation(), N->State, 
N->isSink());
     Pass2[N] = NewN;
 
     // Also record the reverse mapping from the new node to the old node.
Index: lib/StaticAnalyzer/Core/BugReporter.cpp
===================================================================
--- lib/StaticAnalyzer/Core/BugReporter.cpp
+++ lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2922,7 +2922,7 @@
   while (true) {
     // Create the equivalent node in the new graph with the same state
     // and location.
-    ExplodedNode *NewN = GNew->getNode(OrigN->getLocation(), OrigN->getState(),
+    ExplodedNode *NewN = GNew->createUncachedNode(OrigN->getLocation(), 
OrigN->getState(),
                                        OrigN->isSink());
 
     // Store the mapping to the original node.
Index: include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -295,6 +295,14 @@
                         bool IsSink = false,
                         bool* IsNew = nullptr);
 
+  /// \brief Create a node for a (Location, State) pair,
+  ///  but don't store it for deduplication later.  This
+  ///  is useful when copying an already completed
+  ///  ExplodedGraph for further processing.
+  ExplodedNode *createUncachedNode(const ProgramPoint &L,
+    ProgramStateRef State,
+    bool IsSink = false);
+
   std::unique_ptr<ExplodedGraph> MakeEmptyGraph() const {
     return llvm::make_unique<ExplodedGraph>();
   }


Index: lib/StaticAnalyzer/Core/ExplodedGraph.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -336,6 +336,14 @@
   return V;
 }
 
+ExplodedNode *ExplodedGraph::createUncachedNode(const ProgramPoint &L,
+                                                ProgramStateRef State,
+                                                bool IsSink) {
+  NodeTy *V = (NodeTy *) getAllocator().Allocate<NodeTy>();
+  new (V) NodeTy(L, State, IsSink);
+  return V;
+}
+
 std::unique_ptr<ExplodedGraph>
 ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
                     InterExplodedGraphMap *ForwardMap,
@@ -395,8 +403,7 @@
 
     // Create the corresponding node in the new graph and record the mapping
     // from the old node to the new node.
-    ExplodedNode *NewN = G->getNode(N->getLocation(), N->State, N->isSink(),
-                                    nullptr);
+    ExplodedNode *NewN = G->createUncachedNode(N->getLocation(), N->State, N->isSink());
     Pass2[N] = NewN;
 
     // Also record the reverse mapping from the new node to the old node.
Index: lib/StaticAnalyzer/Core/BugReporter.cpp
===================================================================
--- lib/StaticAnalyzer/Core/BugReporter.cpp
+++ lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2922,7 +2922,7 @@
   while (true) {
     // Create the equivalent node in the new graph with the same state
     // and location.
-    ExplodedNode *NewN = GNew->getNode(OrigN->getLocation(), OrigN->getState(),
+    ExplodedNode *NewN = GNew->createUncachedNode(OrigN->getLocation(), OrigN->getState(),
                                        OrigN->isSink());
 
     // Store the mapping to the original node.
Index: include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -295,6 +295,14 @@
                         bool IsSink = false,
                         bool* IsNew = nullptr);
 
+  /// \brief Create a node for a (Location, State) pair,
+  ///  but don't store it for deduplication later.  This
+  ///  is useful when copying an already completed
+  ///  ExplodedGraph for further processing.
+  ExplodedNode *createUncachedNode(const ProgramPoint &L,
+    ProgramStateRef State,
+    bool IsSink = false);
+
   std::unique_ptr<ExplodedGraph> MakeEmptyGraph() const {
     return llvm::make_unique<ExplodedGraph>();
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to