[PATCH] D33584: Remove a quadratic behavior in assert-enabled builds

Adam Nemet via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu May 25 21:39:10 PDT 2017


anemet created this revision.

GVN propagates the equivalence from a condition into the blocks guarded by the
condition.  E.g. for 'if (a == 7) { ... }', 'a' will be replaced in the block
with 7.  It does this by replacing all the uses of 'a' that are dominated by
the true edge.

For a switch with N cases and U uses of the value, this will mean N * U calls
to dominates.  Asserting isSingleEdge in dominates make this N^2 * U because
this function checks for the uniqueness of the edge. I.e. traverses each edge
between the SwitchInst's block and the cases.

This moves the full check under EXPENSIVE_CHECKS and only asserts isSingleEdge
if there are less then 50 edges to check.  This brings build time down by an
order of magnitude for an input that has ~10k cases in a switch statement.


https://reviews.llvm.org/D33584

Files:
  include/llvm/IR/Dominators.h
  lib/IR/Dominators.cpp


Index: lib/IR/Dominators.cpp
===================================================================
--- lib/IR/Dominators.cpp
+++ lib/IR/Dominators.cpp
@@ -120,6 +120,21 @@
   return &*I == Def;
 }
 
+/// \brief A cheaper version of linear BasicBlockEdge::isSingleEdge that may
+/// report a single edge for a SwitchInst even though there are actually
+/// multiple edges.
+static bool maybeSingleEdge(const BasicBlockEdge &BBE) {
+#ifdef EXPENSIVE_CHECKS
+  bool CheckSingleEdge = true;
+#else
+  // This removes a noticeable quadratic behavior with asserts enabled when GVN
+  // propagates equality for a switch statement with a large number of cases.
+  bool CheckSingleEdge =
+      BBE.getStart()->getTerminator()->getNumSuccessors() < 50;
+#endif
+  return !CheckSingleEdge || BBE.isSingleEdge();
+}
+
 // true if Def would dominate a use in any instruction in UseBB.
 // note that dominates(Def, Def->getParent()) is false.
 bool DominatorTree::dominates(const Instruction *Def,
@@ -153,7 +168,7 @@
   // Assert that we have a single edge. We could handle them by simply
   // returning false, but since isSingleEdge is linear on the number of
   // edges, the callers can normally handle them more efficiently.
-  assert(BBE.isSingleEdge() &&
+  assert(maybeSingleEdge(BBE) &&
          "This function is not efficient in handling multiple edges");
 
   // If the BB the edge ends in doesn't dominate the use BB, then the
@@ -204,7 +219,7 @@
   // Assert that we have a single edge. We could handle them by simply
   // returning false, but since isSingleEdge is linear on the number of
   // edges, the callers can normally handle them more efficiently.
-  assert(BBE.isSingleEdge() &&
+  assert(maybeSingleEdge(BBE) &&
          "This function is not efficient in handling multiple edges");
 
   Instruction *UserInst = cast<Instruction>(U.getUser());
Index: include/llvm/IR/Dominators.h
===================================================================
--- include/llvm/IR/Dominators.h
+++ include/llvm/IR/Dominators.h
@@ -66,6 +66,7 @@
     return End;
   }
 
+  /// Check if this is the only edge between Start and End.
   bool isSingleEdge() const;
 };
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D33584.100363.patch
Type: text/x-patch
Size: 2169 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170526/3b191a5f/attachment.bin>


More information about the llvm-commits mailing list