[llvm] [NFC][CodeGen] Don't allow copying SUnit (PR #205213)

Arthur Eubanks via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 23 09:36:43 PDT 2026


https://github.com/aeubanks updated https://github.com/llvm/llvm-project/pull/205213

>From a8ef7f3b3baac82d619ce50614332fad5a471720 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Mon, 22 Jun 2026 23:06:01 +0000
Subject: [PATCH 1/2] [NFC][CodeGen] Don't allow copying SUnit

In preparation for #205171.
---
 llvm/include/llvm/CodeGen/ScheduleDAG.h       |  5 ++++
 llvm/lib/Target/AMDGPU/GCNILPSched.cpp        | 19 ++++++++-------
 llvm/lib/Target/AMDGPU/SIMachineScheduler.cpp | 23 +++++++++++++++----
 llvm/lib/Target/AMDGPU/SIMachineScheduler.h   |  5 +++-
 4 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/ScheduleDAG.h b/llvm/include/llvm/CodeGen/ScheduleDAG.h
index 902d6b83faadf..ee6bbdbffc119 100644
--- a/llvm/include/llvm/CodeGen/ScheduleDAG.h
+++ b/llvm/include/llvm/CodeGen/ScheduleDAG.h
@@ -357,6 +357,11 @@ class TargetRegisterInfo;
           isHeightCurrent(false), isNode(false), isInst(false),
           SchedulingPref(Sched::None) {}
 
+    SUnit(const SUnit &) = delete;
+    SUnit &operator=(const SUnit &) = delete;
+    SUnit(SUnit &&) = default;
+    SUnit &operator=(SUnit &&) = default;
+
     /// Boundary nodes are placeholders for the boundary of the
     /// scheduling region.
     ///
diff --git a/llvm/lib/Target/AMDGPU/GCNILPSched.cpp b/llvm/lib/Target/AMDGPU/GCNILPSched.cpp
index 79b4a68c6a44e..e1c2fdda9ba3b 100644
--- a/llvm/lib/Target/AMDGPU/GCNILPSched.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNILPSched.cpp
@@ -289,13 +289,13 @@ GCNILPScheduler::schedule(ArrayRef<const SUnit*> BotRoots,
                           const ScheduleDAG &DAG) {
   auto &SUnits = const_cast<ScheduleDAG&>(DAG).SUnits;
 
-  std::vector<SUnit> SUSavedCopy;
-  SUSavedCopy.resize(SUnits.size());
+  std::vector<unsigned> SavedNumSuccsLeft(SUnits.size());
+  std::vector<char> SavedIsScheduled(SUnits.size());
 
-  // we cannot save only those fields we touch: some of them are private
-  // so save units verbatim: this assumes SUnit should have value semantics
-  for (const SUnit &SU : SUnits)
-    SUSavedCopy[SU.NodeNum] = SU;
+  for (const SUnit &SU : SUnits) {
+    SavedNumSuccsLeft[SU.NodeNum] = SU.NumSuccsLeft;
+    SavedIsScheduled[SU.NodeNum] = SU.isScheduled;
+  }
 
   SUNumbers.assign(SUnits.size(), 0);
   for (const SUnit &SU : SUnits)
@@ -345,8 +345,11 @@ GCNILPScheduler::schedule(ArrayRef<const SUnit*> BotRoots,
   std::reverse(Schedule.begin(), Schedule.end());
 
   // restore units
-  for (auto &SU : SUnits)
-    SU = SUSavedCopy[SU.NodeNum];
+  for (auto &SU : SUnits) {
+    SU.isScheduled = SavedIsScheduled[SU.NodeNum];
+    SU.NumSuccsLeft = SavedNumSuccsLeft[SU.NodeNum];
+    SU.setHeightDirty();
+  }
 
   return Schedule;
 }
diff --git a/llvm/lib/Target/AMDGPU/SIMachineScheduler.cpp b/llvm/lib/Target/AMDGPU/SIMachineScheduler.cpp
index 8df55e65064a4..b0b1291a0ded1 100644
--- a/llvm/lib/Target/AMDGPU/SIMachineScheduler.cpp
+++ b/llvm/lib/Target/AMDGPU/SIMachineScheduler.cpp
@@ -1833,10 +1833,10 @@ void SIScheduleDAGMI::moveLowLatencies() {
 void SIScheduleDAGMI::restoreSULinksLeft() {
   for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
     SUnits[i].isScheduled = false;
-    SUnits[i].WeakPredsLeft = SUnitsLinksBackup[i].WeakPredsLeft;
-    SUnits[i].NumPredsLeft = SUnitsLinksBackup[i].NumPredsLeft;
-    SUnits[i].WeakSuccsLeft = SUnitsLinksBackup[i].WeakSuccsLeft;
-    SUnits[i].NumSuccsLeft = SUnitsLinksBackup[i].NumSuccsLeft;
+    SUnits[i].WeakPredsLeft = SUnitsWeakPredsLeftBackup[i];
+    SUnits[i].NumPredsLeft = SUnitsNumPredsLeftBackup[i];
+    SUnits[i].WeakSuccsLeft = SUnitsWeakSuccsLeftBackup[i];
+    SUnits[i].NumSuccsLeft = SUnitsNumSuccsLeftBackup[i];
   }
 }
 
@@ -1887,7 +1887,20 @@ void SIScheduleDAGMI::schedule()
 
   // Fill some stats to help scheduling.
 
-  SUnitsLinksBackup = SUnits;
+  SUnitsWeakPredsLeftBackup.clear();
+  SUnitsNumPredsLeftBackup.clear();
+  SUnitsWeakSuccsLeftBackup.clear();
+  SUnitsNumSuccsLeftBackup.clear();
+  SUnitsWeakPredsLeftBackup.reserve(SUnits.size());
+  SUnitsNumPredsLeftBackup.reserve(SUnits.size());
+  SUnitsWeakSuccsLeftBackup.reserve(SUnits.size());
+  SUnitsNumSuccsLeftBackup.reserve(SUnits.size());
+  for (const auto &SU : SUnits) {
+    SUnitsWeakPredsLeftBackup.push_back(SU.WeakPredsLeft);
+    SUnitsNumPredsLeftBackup.push_back(SU.NumPredsLeft);
+    SUnitsWeakSuccsLeftBackup.push_back(SU.WeakSuccsLeft);
+    SUnitsNumSuccsLeftBackup.push_back(SU.NumSuccsLeft);
+  }
   IsLowLatencySU.clear();
   LowLatencyOffset.clear();
   IsHighLatencySU.clear();
diff --git a/llvm/lib/Target/AMDGPU/SIMachineScheduler.h b/llvm/lib/Target/AMDGPU/SIMachineScheduler.h
index 1245774400af1..af349beb790ca 100644
--- a/llvm/lib/Target/AMDGPU/SIMachineScheduler.h
+++ b/llvm/lib/Target/AMDGPU/SIMachineScheduler.h
@@ -426,7 +426,10 @@ class SIScheduleDAGMI final : public ScheduleDAGMILive {
   const SIInstrInfo *SITII;
   const SIRegisterInfo *SITRI;
 
-  std::vector<SUnit> SUnitsLinksBackup;
+  std::vector<unsigned> SUnitsWeakPredsLeftBackup;
+  std::vector<unsigned> SUnitsNumPredsLeftBackup;
+  std::vector<unsigned> SUnitsWeakSuccsLeftBackup;
+  std::vector<unsigned> SUnitsNumSuccsLeftBackup;
 
   // For moveLowLatencies. After all Scheduling variants are tested.
   std::vector<unsigned> ScheduledSUnits;

>From 0f21ba2fd33c98648feddbd2856e9019816fff88 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Tue, 23 Jun 2026 16:36:26 +0000
Subject: [PATCH 2/2] address comments

---
 llvm/include/llvm/CodeGen/ScheduleDAG.h | 1 +
 llvm/lib/Target/AMDGPU/GCNILPSched.cpp  | 8 +++++---
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/ScheduleDAG.h b/llvm/include/llvm/CodeGen/ScheduleDAG.h
index ee6bbdbffc119..9ad33bb36e0a9 100644
--- a/llvm/include/llvm/CodeGen/ScheduleDAG.h
+++ b/llvm/include/llvm/CodeGen/ScheduleDAG.h
@@ -357,6 +357,7 @@ class TargetRegisterInfo;
           isHeightCurrent(false), isNode(false), isInst(false),
           SchedulingPref(Sched::None) {}
 
+    // Don't allow copying, SUnit can be very large.
     SUnit(const SUnit &) = delete;
     SUnit &operator=(const SUnit &) = delete;
     SUnit(SUnit &&) = default;
diff --git a/llvm/lib/Target/AMDGPU/GCNILPSched.cpp b/llvm/lib/Target/AMDGPU/GCNILPSched.cpp
index e1c2fdda9ba3b..a962f5f7fb17c 100644
--- a/llvm/lib/Target/AMDGPU/GCNILPSched.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNILPSched.cpp
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/ADT/BitVector.h"
 #include "llvm/CodeGen/ScheduleDAG.h"
 
 using namespace llvm;
@@ -290,11 +291,12 @@ GCNILPScheduler::schedule(ArrayRef<const SUnit*> BotRoots,
   auto &SUnits = const_cast<ScheduleDAG&>(DAG).SUnits;
 
   std::vector<unsigned> SavedNumSuccsLeft(SUnits.size());
-  std::vector<char> SavedIsScheduled(SUnits.size());
+  BitVector SavedIsScheduled(SUnits.size());
 
   for (const SUnit &SU : SUnits) {
     SavedNumSuccsLeft[SU.NodeNum] = SU.NumSuccsLeft;
-    SavedIsScheduled[SU.NodeNum] = SU.isScheduled;
+    if (SU.isScheduled)
+      SavedIsScheduled.set(SU.NodeNum);
   }
 
   SUNumbers.assign(SUnits.size(), 0);
@@ -346,7 +348,7 @@ GCNILPScheduler::schedule(ArrayRef<const SUnit*> BotRoots,
 
   // restore units
   for (auto &SU : SUnits) {
-    SU.isScheduled = SavedIsScheduled[SU.NodeNum];
+    SU.isScheduled = SavedIsScheduled.test(SU.NodeNum);
     SU.NumSuccsLeft = SavedNumSuccsLeft[SU.NodeNum];
     SU.setHeightDirty();
   }



More information about the llvm-commits mailing list