[PATCH] D21430: Use a much more efficient (linear instead of quadratic?) algorithm for computing the height: standard DFS mincost algorithm for a DAG.

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 16 04:05:23 PDT 2016


chandlerc created this revision.
chandlerc added a subscriber: llvm-commits.
Herald added subscribers: mcrosier, MatzeB.

Not only is the old algorithm essentially BFS instead of DFS, it weirdly
can mark heights as dirty which then walks preds. Very strang. I think
a direct DFS that just computes the height of everything in the DAG from
the bottom up and avoids re-computing already computed heights is much
easier to understand.

For test/CodeGen/AMDGPU/spill-scavenge-offset.ll, prior to it having any
scheduler turned off, computing the height was over 25% of the runtime.
With this patch, it is completely gone. I'm measuring improvements from
32s to 24s (25%) in debug builds and 4.5s to 3.17s (30%) in an optimized
build for thes test.

Glancing at it, the depth computation probably needs the same treatment,
but I've not yet found a test that exercises this (I've not looked too
hard yet though).

As with my prior patch, this impacts both SDAG scheduling and MI
scheduling, but for different reasons -- in this case, both schedulers
call the ScheduleDAG's getHeight routine heavily and were causing it
show up in profiles for spill-scavenge-offset.ll.

http://reviews.llvm.org/D21430

Files:
  lib/CodeGen/ScheduleDAG.cpp

Index: lib/CodeGen/ScheduleDAG.cpp
===================================================================
--- lib/CodeGen/ScheduleDAG.cpp
+++ lib/CodeGen/ScheduleDAG.cpp
@@ -290,34 +290,68 @@
 /// ComputeHeight - Calculate the maximal path from the node to the entry.
 ///
 void SUnit::ComputeHeight() {
-  SmallVector<SUnit*, 8> WorkList;
-  WorkList.push_back(this);
-  do {
-    SUnit *Cur = WorkList.back();
+  if (Succs.empty()) {
+    Height = 0;
+    isHeightCurrent = true;
+    return;
+  }
 
-    bool Done = true;
-    unsigned MaxSuccHeight = 0;
-    for (SUnit::const_succ_iterator I = Cur->Succs.begin(),
-         E = Cur->Succs.end(); I != E; ++I) {
+  SmallVector<std::pair<SUnit *, SUnit::const_succ_iterator>, 8> Stack;
+#ifndef NDEBUG
+  SmallPtrSet<SUnit *, 8> Visited;
+  Visited.insert(this);
+#endif
+  Height = 0;
+  SUnit *Cur = this;
+  SUnit::const_succ_iterator I = Succs.begin();
+  for (;;) {
+    assert(!Cur->isHeightCurrent &&
+           "No need to compute the height once current!");
+
+    SUnit::const_succ_iterator E = Cur->Succs.end();
+    assert(I != E && "Got an end iterator into the stack!");
+
+    do {
       SUnit *SuccSU = I->getSUnit();
-      if (SuccSU->isHeightCurrent)
-        MaxSuccHeight = std::max(MaxSuccHeight,
-                                 SuccSU->Height + I->getLatency());
-      else {
-        Done = false;
-        WorkList.push_back(SuccSU);
+      assert(!Visited.count(SuccSU) && "Found a cycle!");
+
+      if (!SuccSU->isHeightCurrent) {
+        if (SuccSU->Succs.empty()) {
+          SuccSU->Height = 0;
+          SuccSU->isHeightCurrent = true;
+        } else {
+          // We have a successor without a current height.
+          // Push the current position onto the stack and process that
+          // successor.
+          Stack.push_back({Cur, I});
+          Cur = SuccSU;
+#ifndef NDEBUG
+          Visited.insert(Cur);
+#endif
+          I = Cur->Succs.begin();
+          E = Cur->Succs.end();
+          continue;
+        }
       }
-    }
 
-    if (Done) {
-      WorkList.pop_back();
-      if (MaxSuccHeight != Cur->Height) {
-        Cur->setHeightDirty();
-        Cur->Height = MaxSuccHeight;
-      }
-      Cur->isHeightCurrent = true;
-    }
-  } while (!WorkList.empty());
+      // Max the current height against this successor's height.
+      Cur->Height = std::max(Cur->Height, SuccSU->Height + I->getLatency());
+      ++I;
+    } while (I != E);
+
+    // We've examined all successors of this SU, our height is now current.
+    Cur->isHeightCurrent = true;
+
+    // If there are no further nodes to process, we're finished.
+    if (Stack.empty())
+      return;
+
+    // Otherwise pop the stack and continue.
+#ifndef NDEBUG
+    Visited.erase(Cur);
+#endif
+    std::tie(Cur, I) = Stack.pop_back_val();
+  }
 }
 
 void SUnit::biasCriticalPath() {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D21430.60961.patch
Type: text/x-patch
Size: 2866 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160616/a6cb1a59/attachment.bin>


More information about the llvm-commits mailing list