[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