about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/mod.rs16
1 files changed, 13 insertions, 3 deletions
diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index 0d2ae115cb0..00913a483db 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -241,9 +241,19 @@ fn compress(
     v: PreorderIndex,
 ) {
     assert!(is_processed(v, lastlinked));
-    let u = ancestor[v];
-    if is_processed(u, lastlinked) {
-        compress(ancestor, lastlinked, semi, label, u);
+    // Compute the processed list of ancestors
+    //
+    // We use a heap stack here to avoid recursing too deeply, exhausting the
+    // stack space.
+    let mut stack: smallvec::SmallVec<[_; 8]> = smallvec::smallvec![v];
+    let mut u = ancestor[v];
+    while is_processed(u, lastlinked) {
+        stack.push(u);
+        u = ancestor[u];
+    }
+
+    // Then in reverse order, popping the stack
+    for &[v, u] in stack.array_windows().rev() {
         if semi[label[u]] < semi[label[v]] {
             label[v] = label[u];
         }