[llvm] [ScheduleDAG] Add a reachability cache to amortize DFS calls (PR #195079)

James Molloy via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 30 06:36:01 PDT 2026


https://github.com/jmolloy updated https://github.com/llvm/llvm-project/pull/195079

>From 0ac46155bfff8820fd109d0da0d1d79c15cac489 Mon Sep 17 00:00:00 2001
From: James Molloy <jmolloy at google.com>
Date: Thu, 30 Apr 2026 12:53:23 +0000
Subject: [PATCH 1/2] [ScheduleDAG] Add a reachability cache to amortize DFS
 calls

ScheduleDAGTopologicalSort::IsReachable falls out to a DFS on its
slow path. For some connectivity patterns this can result in ~quadratic
behavior.

Add a cache of {A, B} -> Reachable(A, B). This is invalidated whenever
AddPred or InitDAGTopologicalSorting is called.

For an antagnostic testcase, SelectionDAG time went from 1300s to 250s.

No testcase as no functional change, performance only.
---
 llvm/include/llvm/CodeGen/ScheduleDAG.h | 3 +++
 llvm/lib/CodeGen/ScheduleDAG.cpp        | 6 ++++++
 2 files changed, 9 insertions(+)

diff --git a/llvm/include/llvm/CodeGen/ScheduleDAG.h b/llvm/include/llvm/CodeGen/ScheduleDAG.h
index b84f8b99a06e2..2803ba091eac3 100644
--- a/llvm/include/llvm/CodeGen/ScheduleDAG.h
+++ b/llvm/include/llvm/CodeGen/ScheduleDAG.h
@@ -747,6 +747,9 @@ class TargetRegisterInfo;
     std::vector<int> Node2Index;
     /// a set of nodes visited during a DFS traversal.
     BitVector Visited;
+    /// Cache of reachability queries. {A, B} -> true if B is reachable from A.
+    /// The keys are topological indices.
+    DenseMap<std::pair<int, int>, bool> Reachable;
 
     /// Makes a DFS traversal and mark all nodes affected by the edge insertion.
     /// These nodes will later get new topological indexes by means of the Shift
diff --git a/llvm/lib/CodeGen/ScheduleDAG.cpp b/llvm/lib/CodeGen/ScheduleDAG.cpp
index 7dd4aa2d63c7b..71eaee2c60ca7 100644
--- a/llvm/lib/CodeGen/ScheduleDAG.cpp
+++ b/llvm/lib/CodeGen/ScheduleDAG.cpp
@@ -467,6 +467,7 @@ void ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() {
   // Cancel pending updates, mark as valid.
   Dirty = false;
   Updates.clear();
+  Reachable.clear();
 
   unsigned DAGSize = SUnits.size();
   std::vector<SUnit*> WorkList;
@@ -562,6 +563,7 @@ void ScheduleDAGTopologicalSort::AddPred(SUnit *Y, SUnit *X) {
   }
 
   NumNewPredsAdded++;
+  Reachable.clear();
 }
 
 void ScheduleDAGTopologicalSort::RemovePred(SUnit *M, SUnit *N) {
@@ -734,9 +736,13 @@ bool ScheduleDAGTopologicalSort::IsReachable(const SUnit *SU,
   bool HasLoop = false;
   // Is Ord(TargetSU) < Ord(SU) ?
   if (LowerBound < UpperBound) {
+    if (auto It = Reachable.find({LowerBound, UpperBound}); It != Reachable.end()) {
+      return It->second;
+    }
     Visited.reset();
     // There may be a path from TargetSU to SU. Check for it.
     DFS(TargetSU, UpperBound, HasLoop);
+    Reachable[{LowerBound, UpperBound}] = HasLoop;
   }
   return HasLoop;
 }

>From 74f1e4b1a1b39baec48e92e488b809f2ccea04ee Mon Sep 17 00:00:00 2001
From: James Molloy <jmolloy at google.com>
Date: Thu, 30 Apr 2026 13:07:12 +0000
Subject: [PATCH 2/2] fixup: formatting

---
 llvm/lib/CodeGen/ScheduleDAG.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/ScheduleDAG.cpp b/llvm/lib/CodeGen/ScheduleDAG.cpp
index 71eaee2c60ca7..dc9ecdf98a7c8 100644
--- a/llvm/lib/CodeGen/ScheduleDAG.cpp
+++ b/llvm/lib/CodeGen/ScheduleDAG.cpp
@@ -736,7 +736,8 @@ bool ScheduleDAGTopologicalSort::IsReachable(const SUnit *SU,
   bool HasLoop = false;
   // Is Ord(TargetSU) < Ord(SU) ?
   if (LowerBound < UpperBound) {
-    if (auto It = Reachable.find({LowerBound, UpperBound}); It != Reachable.end()) {
+    if (auto It = Reachable.find({LowerBound, UpperBound});
+        It != Reachable.end()) {
       return It->second;
     }
     Visited.reset();



More information about the llvm-commits mailing list