[PATCH] D61397: [DAGCombiner] Limit number of nodes to explore, to avoid quadratic compile time.

Florian Hahn via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed May 1 13:22:54 PDT 2019


fhahn created this revision.
fhahn added reviewers: niravd, spatel, craig.topper.
Herald added subscribers: dexonsmith, hiraditya, mehdi_amini.
Herald added a project: LLVM.

When combining stores at the moment, we iterate over all nodes in a
chain for each store, which leads to quadratic compile times for large
basic blocks with a large number of stores.

Similarly, when simplifying TokenFactors, we potentially iterate over all
operands of a large number of TokenFactors. This also causes quadratic
compile times in some cases.

Similarly, parallelizing store chains also has the potential to cause
compile time problems.

This patch adds some limits to the number of nodes explored for the
cases mentioned above. The limits help to reduce the compile-time in the
backend for a very large input file by 10x (~28000s to ~2800s). Also,
with those limits, only CINT2000/176.gcc/176.gcc and CINT2006/403.gcc/403.gcc
have any codegen differences with -Oz & LTO, for the test-suite, with
SPEC2000 and SPEC2006.

I will continue exploring algorithmic improvements in this area, but
those limits should help avoiding huge compile times in a few edge
cases.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D61397

Files:
  llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp


Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -1764,6 +1764,12 @@
 }
 
 SDValue DAGCombiner::visitTokenFactor(SDNode *N) {
+  // Limit the number of nodes to explore, to avoid quadratic compile times.
+  // The limit helps to limit compile time for basic blocks with a large number
+  // of stores.
+  if (N->getNumOperands() > 1000)
+    return SDValue();
+
   // If N has two operands, where one has an input chain equal to the other,
   // the 'other' chain is redundant.
   if (N->getNumOperands() == 2) {
@@ -14837,9 +14843,15 @@
 
   RootNode = St->getChain().getNode();
 
+  // Limit the number of nodes to explore, to avoid quadratic compile times.
+  // The limit helps to limit compile time for basic blocks with a large number
+  // of stores.
+  unsigned MaxNumberOfNodesToCheck = 200;
   if (LoadSDNode *Ldn = dyn_cast<LoadSDNode>(RootNode)) {
     RootNode = Ldn->getChain().getNode();
-    for (auto I = RootNode->use_begin(), E = RootNode->use_end(); I != E; ++I)
+    for (auto I = RootNode->use_begin(), E = RootNode->use_end(); I != E; ++I) {
+      if (!MaxNumberOfNodesToCheck--)
+        break;
       if (I.getOperandNo() == 0 && isa<LoadSDNode>(*I)) // walk down chain
         for (auto I2 = (*I)->use_begin(), E2 = (*I)->use_end(); I2 != E2; ++I2)
           if (I2.getOperandNo() == 0)
@@ -14849,15 +14861,21 @@
               if (CandidateMatch(OtherST, Ptr, PtrDiff))
                 StoreNodes.push_back(MemOpLink(OtherST, PtrDiff));
             }
-  } else
-    for (auto I = RootNode->use_begin(), E = RootNode->use_end(); I != E; ++I)
-      if (I.getOperandNo() == 0)
+    }
+  } else {
+    for (auto I = RootNode->use_begin(), E = RootNode->use_end(); I != E; ++I) {
+      if (!MaxNumberOfNodesToCheck--)
+        break;
+      if (I.getOperandNo() == 0) {
         if (StoreSDNode *OtherST = dyn_cast<StoreSDNode>(*I)) {
           BaseIndexOffset Ptr;
           int64_t PtrDiff;
           if (CandidateMatch(OtherST, Ptr, PtrDiff))
             StoreNodes.push_back(MemOpLink(OtherST, PtrDiff));
         }
+      }
+    }
+  }
 }
 
 // We need to check that merging these stores does not cause a loop in
@@ -19978,7 +19996,13 @@
   // Add ST's interval.
   Intervals.insert(0, (St->getMemoryVT().getSizeInBits() + 7) / 8, Unit);
 
+  // Limit the number of chains to explore, to avoid quadratic compile times.
+  // The limit helps to limit compile time for basic blocks with a large number
+  // of stores.
+  unsigned MaxNumberOfChains = 200;
   while (StoreSDNode *Chain = dyn_cast<StoreSDNode>(STChain->getChain())) {
+    if (!MaxNumberOfChains--)
+      break;
     // If the chain has more than one use, then we can't reorder the mem ops.
     if (!SDValue(Chain, 0)->hasOneUse())
       break;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D61397.197626.patch
Type: text/x-patch
Size: 2924 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190501/b45ce26b/attachment.bin>


More information about the llvm-commits mailing list