]> granicus.if.org Git - clang/commitdiff
[analyzer] Experiment with an iteration order only based on location, and not using...
authorGeorge Karpenkov <ekarpenkov@apple.com>
Thu, 11 Oct 2018 22:59:59 +0000 (22:59 +0000)
committerGeorge Karpenkov <ekarpenkov@apple.com>
Thu, 11 Oct 2018 22:59:59 +0000 (22:59 +0000)
Differential Revision: https://reviews.llvm.org/D53058

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@344313 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
lib/StaticAnalyzer/Core/CoreEngine.cpp
lib/StaticAnalyzer/Core/WorkList.cpp

index 715cc2bf23e410681e980e4ef46a0dc5c8593507..8f2a27dfbfaa26ed6d10780d4c263ba9adb6d0d2 100644 (file)
@@ -186,6 +186,7 @@ public:
     BFS,
     UnexploredFirst,
     UnexploredFirstQueue,
+    UnexploredFirstLocationQueue,
     BFSBlockDFSContents,
     NotSet
   };
index 07edd35ff9440f3bee363e66891112d48bb1d3fd..ef3c2694b2836037eccf83b38c9d8dddafa3698b 100644 (file)
@@ -85,6 +85,7 @@ public:
   static std::unique_ptr<WorkList> makeBFSBlockDFSContents();
   static std::unique_ptr<WorkList> makeUnexploredFirst();
   static std::unique_ptr<WorkList> makeUnexploredFirstPriorityQueue();
+  static std::unique_ptr<WorkList> makeUnexploredFirstPriorityLocationQueue();
 };
 
 } // end ento namespace
index c910d31d4bf14ac1eeca907c93c54e53c25f78a0..ac8d4d6b3e076d71c24c90c501173bc907e14ff9 100644 (file)
@@ -77,6 +77,8 @@ AnalyzerOptions::getExplorationStrategy() {
                   ExplorationStrategyKind::UnexploredFirst)
             .Case("unexplored_first_queue",
                   ExplorationStrategyKind::UnexploredFirstQueue)
+            .Case("unexplored_first_location_queue",
+                  ExplorationStrategyKind::UnexploredFirstLocationQueue)
             .Case("bfs_block_dfs_contents",
                   ExplorationStrategyKind::BFSBlockDFSContents)
             .Default(ExplorationStrategyKind::NotSet);
index e5a5296e0272bc797a293b847e192bc004ac87ba..e76314972f3e54dbf633796a3d42b26b62649a31 100644 (file)
@@ -53,7 +53,8 @@ STATISTIC(NumPathsExplored,
 // Core analysis engine.
 //===----------------------------------------------------------------------===//
 
-static std::unique_ptr<WorkList> generateWorkList(AnalyzerOptions &Opts) {
+static std::unique_ptr<WorkList> generateWorkList(AnalyzerOptions &Opts,
+                                                  SubEngine &subengine) {
   switch (Opts.getExplorationStrategy()) {
     case AnalyzerOptions::ExplorationStrategyKind::DFS:
       return WorkList::makeDFS();
@@ -65,6 +66,8 @@ static std::unique_ptr<WorkList> generateWorkList(AnalyzerOptions &Opts) {
       return WorkList::makeUnexploredFirst();
     case AnalyzerOptions::ExplorationStrategyKind::UnexploredFirstQueue:
       return WorkList::makeUnexploredFirstPriorityQueue();
+    case AnalyzerOptions::ExplorationStrategyKind::UnexploredFirstLocationQueue:
+      return WorkList::makeUnexploredFirstPriorityLocationQueue();
     default:
       llvm_unreachable("Unexpected case");
   }
@@ -72,7 +75,7 @@ static std::unique_ptr<WorkList> generateWorkList(AnalyzerOptions &Opts) {
 
 CoreEngine::CoreEngine(SubEngine &subengine, FunctionSummariesTy *FS,
                        AnalyzerOptions &Opts)
-    : SubEng(subengine), WList(generateWorkList(Opts)),
+    : SubEng(subengine), WList(generateWorkList(Opts, subengine)),
       BCounterFactory(G.getAllocator()), FunctionSummaries(FS) {}
 
 /// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
index 4b227375da9b290436ab0da6004405fd692311aa..9eb3ee87fb767e1f661442684ee8a98998adfead 100644 (file)
@@ -252,3 +252,63 @@ public:
 std::unique_ptr<WorkList> WorkList::makeUnexploredFirstPriorityQueue() {
   return llvm::make_unique<UnexploredFirstPriorityQueue>();
 }
+
+namespace {
+class UnexploredFirstPriorityLocationQueue : public WorkList {
+  using LocIdentifier = int;
+
+  // How many times each location was visited.
+  // Is signed because we negate it later in order to have a reversed
+  // comparison.
+  using VisitedTimesMap = llvm::DenseMap<LocIdentifier, int>;
+
+  // Compare by number of times the location was visited first (negated
+  // to prefer less often visited locations), then by insertion time (prefer
+  // expanding nodes inserted sooner first).
+  using QueuePriority = std::pair<int, unsigned long>;
+  using QueueItem = std::pair<WorkListUnit, QueuePriority>;
+
+  struct ExplorationComparator {
+    bool operator() (const QueueItem &LHS, const QueueItem &RHS) {
+      return LHS.second < RHS.second;
+    }
+  };
+
+  // Number of inserted nodes, used to emulate DFS ordering in the priority
+  // queue when insertions are equal.
+  unsigned long Counter = 0;
+
+  // Number of times a current location was reached.
+  VisitedTimesMap NumReached;
+
+  // The top item is the largest one.
+  llvm::PriorityQueue<QueueItem, std::vector<QueueItem>, ExplorationComparator>
+      queue;
+
+public:
+  bool hasWork() const override {
+    return !queue.empty();
+  }
+
+  void enqueue(const WorkListUnit &U) override {
+    const ExplodedNode *N = U.getNode();
+    unsigned NumVisited = 0;
+    if (auto BE = N->getLocation().getAs<BlockEntrance>())
+      NumVisited = NumReached[BE->getBlock()->getBlockID()]++;
+
+    queue.push(std::make_pair(U, std::make_pair(-NumVisited, ++Counter)));
+  }
+
+  WorkListUnit dequeue() override {
+    QueueItem U = queue.top();
+    queue.pop();
+    return U.first;
+  }
+
+};
+
+}
+
+std::unique_ptr<WorkList> WorkList::makeUnexploredFirstPriorityLocationQueue() {
+  return llvm::make_unique<UnexploredFirstPriorityLocationQueue>();
+}