[clang][dataflow] Make limit on fixpoint-algorithm iterations proportional to size...
authorYitzhak Mandelbaum <yitzhakm@google.com>
Tue, 24 May 2022 19:04:54 +0000 (19:04 +0000)
committerYitzhak Mandelbaum <yitzhakm@google.com>
Tue, 24 May 2022 20:13:55 +0000 (20:13 +0000)
Currently, the maximum number of iterations of the loop for finding the fixpoint
of the dataflow analysis is set at 2^16. When things go wrong in an analysis,
this can be far too large.  This patch changes the limit to be proportional to
the size of the CFG, which will generally be far smaller than 2^16 (while still
maintaining 2^16 as the absolute limit).

Differential Revision: https://reviews.llvm.org/D126316

clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp

index aebc9dd..ee1723d 100644 (file)
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include <algorithm>
 #include <memory>
 #include <system_error>
 #include <utility>
@@ -330,10 +331,17 @@ runTypeErasedDataflowAnalysis(const ControlFlowContext &CFCtx,
   // converging. To limit the damage (infinite loops) that these bugs can cause,
   // limit the number of iterations.
   // FIXME: Consider making the maximum number of iterations configurable.
+  // FIXME: Consider restricting the number of backedges followed, rather than
+  // iterations.
   // FIXME: Set up statistics (see llvm/ADT/Statistic.h) to count average number
   // of iterations, number of functions that time out, etc.
+  static constexpr uint32_t MaxAverageVisitsPerBlock = 4;
+  static constexpr uint32_t AbsoluteMaxIterations = 1 << 16;
+  const uint32_t RelativeMaxIterations =
+      MaxAverageVisitsPerBlock * BlockStates.size();
+  const uint32_t MaxIterations =
+      std::min(RelativeMaxIterations, AbsoluteMaxIterations);
   uint32_t Iterations = 0;
-  static constexpr uint32_t MaxIterations = 1 << 16;
   while (const CFGBlock *Block = Worklist.dequeue()) {
     if (++Iterations > MaxIterations) {
       return llvm::createStringError(std::errc::timed_out,