r214064 - Factoring DataflowWorklist out of LiveVariables and UninitializedValues analyses

Artyom Skrobov Artyom.Skrobov at arm.com
Mon Jul 28 01:47:39 PDT 2014


Author: askrobov
Date: Mon Jul 28 03:47:38 2014
New Revision: 214064

URL: http://llvm.org/viewvc/llvm-project?rev=214064&view=rev
Log:
Factoring DataflowWorklist out of LiveVariables and UninitializedValues analyses

Added:
    cfe/trunk/include/clang/Analysis/Analyses/DataflowWorklist.h
    cfe/trunk/lib/Analysis/DataflowWorklist.cpp
Modified:
    cfe/trunk/lib/Analysis/CMakeLists.txt
    cfe/trunk/lib/Analysis/LiveVariables.cpp
    cfe/trunk/lib/Analysis/UninitializedValues.cpp

Added: cfe/trunk/include/clang/Analysis/Analyses/DataflowWorklist.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/DataflowWorklist.h?rev=214064&view=auto
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/DataflowWorklist.h (added)
+++ cfe/trunk/include/clang/Analysis/Analyses/DataflowWorklist.h Mon Jul 28 03:47:38 2014
@@ -0,0 +1,53 @@
+//===- DataflowWorklist.h - worklist for dataflow analysis --------*- C++ --*-//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// DataflowWorklist is used in LiveVariables and UninitializedValues analyses
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DATAFLOW_WORKLIST
+#define LLVM_CLANG_DATAFLOW_WORKLIST
+
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+
+namespace clang {
+
+class DataflowWorklist {
+  PostOrderCFGView::iterator PO_I, PO_E;
+  PostOrderCFGView::BlockOrderCompare comparator;
+  SmallVector<const CFGBlock *, 20> worklist;
+  llvm::BitVector enqueuedBlocks;
+
+  DataflowWorklist(const CFG &cfg, PostOrderCFGView &view)
+    : PO_I(view.begin()), PO_E(view.end()),
+      comparator(view.getComparator()),
+      enqueuedBlocks(cfg.getNumBlockIDs(), true) {
+        // Treat the first block as already analyzed.
+        if (PO_I != PO_E) {
+          assert(*PO_I == &cfg.getEntry());
+          enqueuedBlocks[(*PO_I)->getBlockID()] = false;
+          ++PO_I;
+        }
+      }
+
+public:
+  DataflowWorklist(const CFG &cfg, AnalysisDeclContext &Ctx)
+    : DataflowWorklist(cfg, *Ctx.getAnalysis<PostOrderCFGView>()) {}
+
+  void enqueueBlock(const CFGBlock *block);
+  void enqueuePredecessors(const CFGBlock *block);
+  void enqueueSuccessors(const CFGBlock *block);
+  const CFGBlock *dequeue();
+
+  void sortWorklist();
+};
+
+} // end clang namespace
+
+#endif

Modified: cfe/trunk/lib/Analysis/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=214064&r1=214063&r2=214064&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CMakeLists.txt (original)
+++ cfe/trunk/lib/Analysis/CMakeLists.txt Mon Jul 28 03:47:38 2014
@@ -12,6 +12,7 @@ add_clang_library(clangAnalysis
   CocoaConventions.cpp
   Consumed.cpp
   Dominators.cpp
+  DataflowWorklist.cpp
   FormatString.cpp
   LiveVariables.cpp
   ObjCNoReturn.cpp

Added: cfe/trunk/lib/Analysis/DataflowWorklist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/DataflowWorklist.cpp?rev=214064&view=auto
==============================================================================
--- cfe/trunk/lib/Analysis/DataflowWorklist.cpp (added)
+++ cfe/trunk/lib/Analysis/DataflowWorklist.cpp Mon Jul 28 03:47:38 2014
@@ -0,0 +1,92 @@
+//===- DataflowWorklist.cpp - worklist for dataflow analysis ------*- C++ --*-//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// DataflowWorklist is used in LiveVariables and UninitializedValues analyses
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Analyses/DataflowWorklist.h"
+
+using namespace clang;
+
+// Marking a block as enqueued means that it cannot be re-added to the worklist,
+// but it doesn't control when the algorithm terminates.
+// Initially, enqueuedBlocks is set to true for all blocks;
+// that's not because everything is added initially to the worklist,
+// but instead, to cause the forward analysis to follow the reverse post order
+// until we enqueue something on the worklist. 
+void DataflowWorklist::enqueueBlock(const clang::CFGBlock *block) {
+  if (block && !enqueuedBlocks[block->getBlockID()]) {
+    enqueuedBlocks[block->getBlockID()] = true;
+    worklist.push_back(block);
+  }
+}
+
+// The forward analysis alternates between essentially two worklists.
+// A prioritization worklist (SmallVector<const CFGBlock *> worklist)
+// is consulted first, and if it's empty, we consult the reverse
+// post-order traversal (PostOrderCFGView::iterator PO_I).
+// The prioritization worklist is used to prioritize analyzing from
+// the beginning, or to prioritize updates fed by back edges.
+// Typically, what gets enqueued on the worklist are back edges, which
+// we want to prioritize analyzing first, because that causes dataflow facts
+// to flow up the graph, which we then want to propagate forward.
+// In practice this can cause the analysis to converge much faster.  
+void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) {
+  for (CFGBlock::const_succ_iterator I = block->succ_begin(),
+       E = block->succ_end(); I != E; ++I) {
+    enqueueBlock(*I);
+  }
+}
+
+// The reverse analysis uses a simple re-sorting of the worklist to
+// reprioritize it.  It's not as efficient as the two-worklists approach,
+// but it isn't performance sensitive since it's used by the static analyzer,
+// and the static analyzer does far more work that dwarfs the work done here.
+// TODO: It would still be nice to use the same approach for both analyses.
+void DataflowWorklist::enqueuePredecessors(const clang::CFGBlock *block) {
+  const unsigned OldWorklistSize = worklist.size();
+  for (CFGBlock::const_pred_iterator I = block->pred_begin(),
+       E = block->pred_end(); I != E; ++I) {
+    enqueueBlock(*I);
+  }
+
+  if (OldWorklistSize == 0 || OldWorklistSize == worklist.size())
+    return;
+
+  sortWorklist();
+}
+
+const CFGBlock *DataflowWorklist::dequeue() {
+  const CFGBlock *B = nullptr;
+
+  // First dequeue from the worklist.  This can represent
+  // updates along backedges that we want propagated as quickly as possible.
+  if (!worklist.empty())
+    B = worklist.pop_back_val();
+
+  // Next dequeue from the initial reverse post order.  This is the
+  // theoretical ideal in the presence of no back edges.
+  else if (PO_I != PO_E) {
+    B = *PO_I;
+    ++PO_I;
+  }
+  else {
+    return nullptr;
+  }
+
+  assert(enqueuedBlocks[B->getBlockID()] == true);
+  enqueuedBlocks[B->getBlockID()] = false;
+  return B;
+}
+
+void DataflowWorklist::sortWorklist() {
+  std::sort(worklist.begin(), worklist.end(), comparator);
+}
+

Modified: cfe/trunk/lib/Analysis/LiveVariables.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/LiveVariables.cpp?rev=214064&r1=214063&r2=214064&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/LiveVariables.cpp (original)
+++ cfe/trunk/lib/Analysis/LiveVariables.cpp Mon Jul 28 03:47:38 2014
@@ -14,11 +14,10 @@
 #include "clang/Analysis/Analyses/LiveVariables.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtVisitor.h"
-#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/Analyses/DataflowWorklist.h"
 #include "clang/Analysis/AnalysisContext.h"
 #include "clang/Analysis/CFG.h"
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/PostOrderIterator.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <vector>
@@ -26,59 +25,6 @@
 using namespace clang;
 
 namespace {
-
-class DataflowWorklist {
-  SmallVector<const CFGBlock *, 20> worklist;
-  llvm::BitVector enqueuedBlocks;
-  PostOrderCFGView *POV;
-public:
-  DataflowWorklist(const CFG &cfg, AnalysisDeclContext &Ctx)
-    : enqueuedBlocks(cfg.getNumBlockIDs()),
-      POV(Ctx.getAnalysis<PostOrderCFGView>()) {}
-  
-  void enqueueBlock(const CFGBlock *block);
-  void enqueuePredecessors(const CFGBlock *block);
-
-  const CFGBlock *dequeue();
-
-  void sortWorklist();
-};
-
-}
-
-void DataflowWorklist::enqueueBlock(const clang::CFGBlock *block) {
-  if (block && !enqueuedBlocks[block->getBlockID()]) {
-    enqueuedBlocks[block->getBlockID()] = true;
-    worklist.push_back(block);
-  }
-}
-
-void DataflowWorklist::enqueuePredecessors(const clang::CFGBlock *block) {
-  const unsigned OldWorklistSize = worklist.size();
-  for (CFGBlock::const_pred_iterator I = block->pred_begin(),
-       E = block->pred_end(); I != E; ++I) {
-    enqueueBlock(*I);
-  }
-  
-  if (OldWorklistSize == 0 || OldWorklistSize == worklist.size())
-    return;
-
-  sortWorklist();
-}
-
-void DataflowWorklist::sortWorklist() {
-  std::sort(worklist.begin(), worklist.end(), POV->getComparator());
-}
-
-const CFGBlock *DataflowWorklist::dequeue() {
-  if (worklist.empty())
-    return nullptr;
-  const CFGBlock *b = worklist.pop_back_val();
-  enqueuedBlocks[b->getBlockID()] = false;
-  return b;
-}
-
-namespace {
 class LiveVariablesImpl {
 public:  
   AnalysisDeclContext &analysisContext;

Modified: cfe/trunk/lib/Analysis/UninitializedValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/UninitializedValues.cpp?rev=214064&r1=214063&r2=214064&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/UninitializedValues.cpp (original)
+++ cfe/trunk/lib/Analysis/UninitializedValues.cpp Mon Jul 28 03:47:38 2014
@@ -15,7 +15,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/StmtVisitor.h"
-#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/Analyses/DataflowWorklist.h"
 #include "clang/Analysis/Analyses/UninitializedValues.h"
 #include "clang/Analysis/AnalysisContext.h"
 #include "clang/Analysis/CFG.h"
@@ -199,66 +199,6 @@ ValueVector::reference CFGBlockValues::o
 }
 
 //------------------------------------------------------------------------====//
-// Worklist: worklist for dataflow analysis.
-//====------------------------------------------------------------------------//
-
-namespace {
-class DataflowWorklist {
-  PostOrderCFGView::iterator PO_I, PO_E;
-  SmallVector<const CFGBlock *, 20> worklist;
-  llvm::BitVector enqueuedBlocks;
-public:
-  DataflowWorklist(const CFG &cfg, PostOrderCFGView &view)
-    : PO_I(view.begin()), PO_E(view.end()),
-      enqueuedBlocks(cfg.getNumBlockIDs(), true) {
-        // Treat the first block as already analyzed.
-        if (PO_I != PO_E) {
-          assert(*PO_I == &cfg.getEntry());
-          enqueuedBlocks[(*PO_I)->getBlockID()] = false;
-          ++PO_I;
-        }
-      }
-  
-  void enqueueSuccessors(const CFGBlock *block);
-  const CFGBlock *dequeue();
-};
-}
-
-void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) {
-  for (CFGBlock::const_succ_iterator I = block->succ_begin(),
-       E = block->succ_end(); I != E; ++I) {
-    const CFGBlock *Successor = *I;
-    if (!Successor || enqueuedBlocks[Successor->getBlockID()])
-      continue;
-    worklist.push_back(Successor);
-    enqueuedBlocks[Successor->getBlockID()] = true;
-  }
-}
-
-const CFGBlock *DataflowWorklist::dequeue() {
-  const CFGBlock *B = nullptr;
-
-  // First dequeue from the worklist.  This can represent
-  // updates along backedges that we want propagated as quickly as possible.
-  if (!worklist.empty())
-    B = worklist.pop_back_val();
-
-  // Next dequeue from the initial reverse post order.  This is the
-  // theoretical ideal in the presence of no back edges.
-  else if (PO_I != PO_E) {
-    B = *PO_I;
-    ++PO_I;
-  }
-  else {
-    return nullptr;
-  }
-
-  assert(enqueuedBlocks[B->getBlockID()] == true);
-  enqueuedBlocks[B->getBlockID()] = false;
-  return B;
-}
-
-//------------------------------------------------------------------------====//
 // Classification of DeclRefExprs as use or initialization.
 //====------------------------------------------------------------------------//
 
@@ -831,7 +771,7 @@ void clang::runUninitializedVariablesAna
   }
 
   // Proceed with the workist.
-  DataflowWorklist worklist(cfg, *ac.getAnalysis<PostOrderCFGView>());
+  DataflowWorklist worklist(cfg, ac);
   llvm::BitVector previouslyVisited(cfg.getNumBlockIDs());
   worklist.enqueueSuccessors(&cfg.getEntry());
   llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false);





More information about the cfe-commits mailing list