[llvm] [AMDGPU][CodeGen] Incrementally update reserved regs for SIPreAllocateWWMRegs pass in RegisterClassInfo (PR #212201)

Nikhil Kotikalapudi via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 2 17:47:49 PDT 2026


https://github.com/nkotikal updated https://github.com/llvm/llvm-project/pull/212201

>From a4caf3d1597943f39f008609b9f8ae5214c55d08 Mon Sep 17 00:00:00 2001
From: Nikhil Kotikalapudi <Nikhil.Kotikalapudi at amd.com>
Date: Mon, 27 Jul 2026 02:29:54 -0500
Subject: [PATCH 1/6] added updateReservedRegs method to rci cpp file to update
 reservation bitvector without invalidating full object

---
 llvm/include/llvm/CodeGen/RegisterClassInfo.h | 10 +++
 llvm/lib/CodeGen/RegisterClassInfo.cpp        | 74 ++++++++++++++++++-
 2 files changed, 83 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/CodeGen/RegisterClassInfo.h b/llvm/include/llvm/CodeGen/RegisterClassInfo.h
index 256277832db24..995cb6b28e2c2 100644
--- a/llvm/include/llvm/CodeGen/RegisterClassInfo.h
+++ b/llvm/include/llvm/CodeGen/RegisterClassInfo.h
@@ -98,6 +98,16 @@ class RegisterClassInfo {
   LLVM_ABI void runOnMachineFunction(const MachineFunction &MF,
                                      bool Rev = false);
 
+  /// allows modification of current reserved register vector
+  /// without invalidating RCI and triggering recomputation.
+  /// prereqs for use:
+  ///     RCI already initialized,
+  ///     the caller updated MRI's reserved vector (only adding reservations)
+  ///     note: target information, callee-saved regs, cost, and alloc order
+  ///     must not change.
+  ///     input: MRI's current frozen vector
+  LLVM_ABI void updateReservedRegs(const BitVector &ReservedInput);
+
   LLVM_ABI bool invalidate(MachineFunction &, const PreservedAnalyses &PA,
                            MachineFunctionAnalysisManager::Invalidator &) {
     auto PAC = PA.getChecker<MachineRegisterClassAnalysis>();
diff --git a/llvm/lib/CodeGen/RegisterClassInfo.cpp b/llvm/lib/CodeGen/RegisterClassInfo.cpp
index f4b9e8d9b1704..b575e39600834 100644
--- a/llvm/lib/CodeGen/RegisterClassInfo.cpp
+++ b/llvm/lib/CodeGen/RegisterClassInfo.cpp
@@ -123,6 +123,78 @@ void RegisterClassInfo::runOnMachineFunction(const MachineFunction &mf,
   }
 }
 
+void RegisterClassInfo::updateReservedRegs(const BitVector &ReservedInput) {
+  assert(MF && TRI && RegClass &&
+         "RegisterClassInfo must be initialized before updating reserved regs");
+  assert(ReservedInput.size() == Reserved.size() &&
+         "Reserved register bit vectors must have the same size");
+  assert(Reserved.subsetOf(ReservedInput) &&
+         "updateReservedRegs cannot remove reserved registers");
+  if (ReservedInput == Reserved)
+    return;
+
+  // subtracts reserved set from input set to get newly reserved regs
+  BitVector NewReservations = ReservedInput;
+  NewReservations.reset(Reserved);
+
+  Reserved = ReservedInput;
+
+  // Pressure limits depend on the number of allocatable registers.
+  std::fill_n(PSetLimits.get(), TRI->getNumRegPressureSets(), 0);
+
+  // NumRegs may hide entries beyond the stress limit, so those orders cannot
+  // safely be compacted using only their visible prefix.
+  if (StressRA) {
+    ++Tag;
+    return;
+  }
+
+  for (const TargetRegisterClass &RC : TRI->regclasses()) {
+    RCInfo &Info = RegClass[RC.getID()];
+    Info.ProperSubClass = false;
+
+    // Stale entries will be computed lazily with the new Reserved vector.
+    if (Info.Tag != Tag)
+      continue;
+
+    unsigned NewNumRegs = 0;
+    uint8_t MinCost = uint8_t(~0u);
+    uint8_t LastCost = uint8_t(~0u);
+    unsigned LastCostChange = 0;
+
+    for (unsigned I = 0; I != Info.NumRegs; ++I) {
+      MCPhysReg PhysReg = Info.Order[I];
+      if (NewReservations.test(PhysReg))
+        continue;
+
+      uint8_t Cost = RegCosts[PhysReg];
+      MinCost = std::min(MinCost, Cost);
+      if (Cost != LastCost)
+        LastCostChange = NewNumRegs;
+
+      Info.Order[NewNumRegs++] = PhysReg;
+      LastCost = Cost;
+    }
+
+    Info.NumRegs = NewNumRegs;
+    Info.MinCost = MinCost;
+    Info.LastCostChange = LastCostChange;
+  }
+
+  // ProperSubClass depends on both this class and its superclass counts, so
+  // calculate it only after all valid orders have been compacted.
+  for (const TargetRegisterClass &RC : TRI->regclasses()) {
+    RCInfo &Info = RegClass[RC.getID()];
+    if (Info.Tag != Tag)
+      continue;
+
+    if (const TargetRegisterClass *Super =
+            TRI->getLargestLegalSuperClass(&RC, *MF))
+      if (Super != &RC && getNumAllocatableRegs(Super) > Info.NumRegs)
+        Info.ProperSubClass = true;
+  }
+}
+
 /// compute - Compute the preferred allocation order for RC with reserved
 /// registers filtered out. Volatile registers come first followed by CSR
 /// aliases ordered according to the CSR order specified by the target.
@@ -181,6 +253,7 @@ void RegisterClassInfo::compute(const TargetRegisterClass *RC) const {
     RCI.NumRegs = StressRA;
 
   // Check if RC is a proper sub-class.
+  RCI.ProperSubClass = false;
   if (const TargetRegisterClass *Super =
           TRI->getLargestLegalSuperClass(RC, *MF))
     if (Super != RC && getNumAllocatableRegs(Super) > RCI.NumRegs)
@@ -206,7 +279,6 @@ void RegisterClassInfo::compute(const TargetRegisterClass *RC) const {
 unsigned RegisterClassInfo::computePSetLimit(unsigned Idx) const {
   const TargetRegisterClass *RC = TRI->getLargestRegClassForRegPressureSet(Idx);
   assert(RC && "Failed to find register class");
-  compute(RC);
   unsigned NAllocatableRegs = getNumAllocatableRegs(RC);
   unsigned RegPressureSetLimit = TRI->getRegPressureSetLimit(*MF, Idx);
   // If all the regs are reserved, return raw RegPressureSetLimit.

>From 2cdf9866bb2bb2c1d19ee87efa6a35ae2dbf9694 Mon Sep 17 00:00:00 2001
From: Nikhil Kotikalapudi <Nikhil.Kotikalapudi at amd.com>
Date: Mon, 27 Jul 2026 03:26:51 -0500
Subject: [PATCH 2/6] used new function in SIPreAllocateWWMRegs, test
 validation

---
 llvm/include/llvm/CodeGen/RegisterClassInfo.h |  4 +--
 llvm/lib/CodeGen/RegisterClassInfo.cpp        | 14 ++++----
 .../Target/AMDGPU/SIPreAllocateWWMRegs.cpp    | 29 ++++++-----------
 ...i-pre-allocate-wwm-regs-invalidate-rci.mir | 32 -------------------
 .../si-pre-allocate-wwm-regs-preserve-rci.mir | 27 ++++++++++++++++
 5 files changed, 46 insertions(+), 60 deletions(-)
 delete mode 100644 llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-invalidate-rci.mir
 create mode 100644 llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir

diff --git a/llvm/include/llvm/CodeGen/RegisterClassInfo.h b/llvm/include/llvm/CodeGen/RegisterClassInfo.h
index 995cb6b28e2c2..53e7faba12555 100644
--- a/llvm/include/llvm/CodeGen/RegisterClassInfo.h
+++ b/llvm/include/llvm/CodeGen/RegisterClassInfo.h
@@ -99,10 +99,10 @@ class RegisterClassInfo {
                                      bool Rev = false);
 
   /// allows modification of current reserved register vector
-  /// without invalidating RCI and triggering recomputation.
+  /// without invalidating RCI and triggering recomputation when possible
   /// prereqs for use:
   ///     RCI already initialized,
-  ///     the caller updated MRI's reserved vector (only adding reservations)
+  ///     the caller updated MRI's reserved vector
   ///     note: target information, callee-saved regs, cost, and alloc order
   ///     must not change.
   ///     input: MRI's current frozen vector
diff --git a/llvm/lib/CodeGen/RegisterClassInfo.cpp b/llvm/lib/CodeGen/RegisterClassInfo.cpp
index b575e39600834..fcb2f6f8d65e7 100644
--- a/llvm/lib/CodeGen/RegisterClassInfo.cpp
+++ b/llvm/lib/CodeGen/RegisterClassInfo.cpp
@@ -128,11 +128,12 @@ void RegisterClassInfo::updateReservedRegs(const BitVector &ReservedInput) {
          "RegisterClassInfo must be initialized before updating reserved regs");
   assert(ReservedInput.size() == Reserved.size() &&
          "Reserved register bit vectors must have the same size");
-  assert(Reserved.subsetOf(ReservedInput) &&
-         "updateReservedRegs cannot remove reserved registers");
   if (ReservedInput == Reserved)
     return;
 
+  // Cached orders cannot regain unreserved registers; recompute them lazily.
+  bool OnlyNewReservations = Reserved.subsetOf(ReservedInput);
+
   // subtracts reserved set from input set to get newly reserved regs
   BitVector NewReservations = ReservedInput;
   NewReservations.reset(Reserved);
@@ -144,19 +145,21 @@ void RegisterClassInfo::updateReservedRegs(const BitVector &ReservedInput) {
 
   // NumRegs may hide entries beyond the stress limit, so those orders cannot
   // safely be compacted using only their visible prefix.
-  if (StressRA) {
+  if (!OnlyNewReservations || StressRA) {
     ++Tag;
     return;
   }
 
   for (const TargetRegisterClass &RC : TRI->regclasses()) {
     RCInfo &Info = RegClass[RC.getID()];
-    Info.ProperSubClass = false;
 
-    // Stale entries will be computed lazily with the new Reserved vector.
+    // skip if class info is out of date
     if (Info.Tag != Tag)
       continue;
 
+    // Recomputed below, once every order has been narrowed.
+    Info.ProperSubClass = false;
+
     unsigned NewNumRegs = 0;
     uint8_t MinCost = uint8_t(~0u);
     uint8_t LastCost = uint8_t(~0u);
@@ -253,7 +256,6 @@ void RegisterClassInfo::compute(const TargetRegisterClass *RC) const {
     RCI.NumRegs = StressRA;
 
   // Check if RC is a proper sub-class.
-  RCI.ProperSubClass = false;
   if (const TargetRegisterClass *Super =
           TRI->getLargestLegalSuperClass(RC, *MF))
     if (Super != RC && getNumAllocatableRegs(Super) > RCI.NumRegs)
diff --git a/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp b/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp
index bf484cef98da4..c7ed1b0d02e6b 100644
--- a/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp
+++ b/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp
@@ -17,13 +17,11 @@
 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
 #include "SIMachineFunctionInfo.h"
 #include "llvm/ADT/PostOrderIterator.h"
-#include "llvm/CodeGen/LiveDebugVariables.h"
 #include "llvm/CodeGen/LiveIntervals.h"
 #include "llvm/CodeGen/LiveRegMatrix.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/RegisterClassInfo.h"
-#include "llvm/CodeGen/SlotIndexes.h"
 #include "llvm/CodeGen/VirtRegMap.h"
 #include "llvm/InitializePasses.h"
 
@@ -45,7 +43,7 @@ class SIPreAllocateWWMRegs {
   LiveIntervals *LIS;
   LiveRegMatrix *Matrix;
   VirtRegMap *VRM;
-  const RegisterClassInfo &RegClassInfo;
+  RegisterClassInfo &RegClassInfo;
 
   std::vector<unsigned> RegsToRewrite;
 #ifndef NDEBUG
@@ -56,7 +54,7 @@ class SIPreAllocateWWMRegs {
 
 public:
   SIPreAllocateWWMRegs(LiveIntervals *LIS, LiveRegMatrix *Matrix,
-                       VirtRegMap *VRM, const RegisterClassInfo &RCI)
+                       VirtRegMap *VRM, RegisterClassInfo &RCI)
       : LIS(LIS), Matrix(Matrix), VRM(VRM), RegClassInfo(RCI) {}
   bool run(MachineFunction &MF);
 };
@@ -73,14 +71,8 @@ class SIPreAllocateWWMRegsLegacy : public MachineFunctionPass {
     AU.addRequired<LiveIntervalsWrapperPass>();
     AU.addRequired<VirtRegMapWrapperLegacy>();
     AU.addRequired<LiveRegMatrixWrapperLegacy>();
-    // TODO: Update RCI with the additional reserved registers the pass sets.
     AU.addRequired<MachineRegisterClassInfoWrapperPass>();
-    AU.setPreservesCFG();
-    AU.addPreserved<LiveIntervalsWrapperPass>();
-    AU.addPreserved<SlotIndexesWrapperPass>();
-    AU.addPreserved<VirtRegMapWrapperLegacy>();
-    AU.addPreserved<LiveRegMatrixWrapperLegacy>();
-    AU.addPreserved<LiveDebugVariablesWrapperLegacy>();
+    AU.setPreservesAll();
     MachineFunctionPass::getAnalysisUsage(AU);
   }
 };
@@ -175,8 +167,10 @@ void SIPreAllocateWWMRegs::rewriteRegs(MachineFunction &MF) {
 
   RegsToRewrite.clear();
 
-  // Update the set of reserved registers to include WWM ones.
+  // Update the set of reserved registers to include WWM ones 
+  // without unnecessarily invalidating RegClassInfo
   MRI->freezeReservedRegs();
+  RegClassInfo.updateReservedRegs(MRI->getReservedRegs());
 }
 
 #ifndef NDEBUG
@@ -208,7 +202,7 @@ bool SIPreAllocateWWMRegsLegacy::runOnMachineFunction(MachineFunction &MF) {
   auto *LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
   auto *Matrix = &getAnalysis<LiveRegMatrixWrapperLegacy>().getLRM();
   auto *VRM = &getAnalysis<VirtRegMapWrapperLegacy>().getVRM();
-  const auto &RCI = getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI();
+  auto &RCI = getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI();
   return SIPreAllocateWWMRegs(LIS, Matrix, VRM, RCI).run(MF);
 }
 
@@ -280,12 +274,7 @@ SIPreAllocateWWMRegsPass::run(MachineFunction &MF,
   auto *LIS = &MFAM.getResult<LiveIntervalsAnalysis>(MF);
   auto *Matrix = &MFAM.getResult<LiveRegMatrixAnalysis>(MF);
   auto *VRM = &MFAM.getResult<VirtRegMapAnalysis>(MF);
-  const auto &RCI = MFAM.getResult<MachineRegisterClassAnalysis>(MF);
+  auto &RCI = MFAM.getResult<MachineRegisterClassAnalysis>(MF);
   SIPreAllocateWWMRegs(LIS, Matrix, VRM, RCI).run(MF);
-  // The pass reserves WWM registers, invalidating RegisterClassInfo's
-  // allocation order, so it cannot be preserved (see the legacy
-  // getAnalysisUsage above).
-  PreservedAnalyses PA = PreservedAnalyses::all();
-  PA.abandon<MachineRegisterClassAnalysis>();
-  return PA;
+  return PreservedAnalyses::all();
 }
diff --git a/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-invalidate-rci.mir b/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-invalidate-rci.mir
deleted file mode 100644
index 6571294bac741..0000000000000
--- a/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-invalidate-rci.mir
+++ /dev/null
@@ -1,32 +0,0 @@
-# RUN: llc -mtriple=amdgpu7.00-amd-amdhsa -passes="require<machine-register-class-info>,si-pre-allocate-wwm-regs,require<machine-register-class-info>" -debug-pass-manager -filetype=null %s 2>&1 | FileCheck %s
-
-# INFO: Test that MachineRegisterClassInfo is not preserved in WWM preallocation
-
-# CHECK: Running analysis: MachineRegisterClassAnalysis on test_wwm_reserved
-# CHECK: Running pass: SIPreAllocateWWMRegsPass on test_wwm_reserved
-# CHECK: Invalidating analysis: MachineRegisterClassAnalysis on test_wwm_reserved
-# CHECK: Running analysis: MachineRegisterClassAnalysis on test_wwm_reserved
-
----
-name: test_wwm_reserved
-tracksRegLiveness: true
-frameInfo:
-  maxAlignment: 4
-stack:
-  - { id: 0, type: spill-slot, size: 4, alignment: 4, stack-id: sgpr-spill }
-machineFunctionInfo:
-  isEntryFunction: false
-  scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
-  stackPtrOffsetReg: '$sgpr32'
-  frameOffsetReg: '$sgpr33'
-  hasSpilledSGPRs: true
-body: |
-  bb.0:
-    liveins: $sgpr4, $vgpr2_vgpr3
-    SI_SPILL_S32_SAVE killed $sgpr4, %stack.0, implicit $exec, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $sgpr32
-    S_NOP 0
-    renamable $sgpr4 = SI_SPILL_S32_RESTORE %stack.0, implicit $exec, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $sgpr32
-    %0:vgpr_32 = V_MOV_B32_e32 20, implicit $exec
-    GLOBAL_STORE_DWORD $vgpr2_vgpr3, %0:vgpr_32, 0, 0, implicit $exec
-    SI_RETURN
-...
diff --git a/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir b/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir
new file mode 100644
index 0000000000000..9b2793795e35c
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir
@@ -0,0 +1,27 @@
+# RUN: llc -mtriple=amdgpu9.0a -passes="require<machine-register-class-info>,si-pre-allocate-wwm-regs,require<machine-register-class-info>" -debug-pass-manager -filetype=null %s 2>&1 | FileCheck %s
+# RUN: llc -mtriple=amdgpu9.0a -passes=si-pre-allocate-wwm-regs -o - %s | FileCheck %s --check-prefix=MIR
+
+# INFO: Test that WWM preallocation updates MachineRegisterClassInfo in place
+# instead of invalidating it, so the analysis is not recomputed afterwards.
+
+# CHECK: Running analysis: MachineRegisterClassAnalysis on test_wwm_reserved
+# CHECK: Running pass: SIPreAllocateWWMRegsPass on test_wwm_reserved
+# CHECK-NOT: Invalidating analysis: MachineRegisterClassAnalysis on test_wwm_reserved
+# CHECK-NOT: Running analysis: MachineRegisterClassAnalysis on test_wwm_reserved
+
+# MIR: wwmReservedRegs:
+# MIR-NEXT: - '$vgpr0'
+
+---
+name: test_wwm_reserved
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr1
+    %0:vgpr_32 = IMPLICIT_DEF
+    renamable $sgpr4_sgpr5 = ENTER_STRICT_WWM -1, implicit-def $exec, implicit-def $scc, implicit $exec
+    %1:vgpr_32 = V_MOV_B32_e32 0, implicit $exec
+    %2:vgpr_32 = V_MOV_B32_dpp %1, %0, 323, 12, 15, 0, implicit $exec
+    $exec = EXIT_STRICT_WWM killed renamable $sgpr4_sgpr5
+    %3:vgpr_32 = COPY %0
+...

>From 5d78fe86233a25883ee105e70f89055928b71e17 Mon Sep 17 00:00:00 2001
From: Nikhil Kotikalapudi <Nikhil.Kotikalapudi at amd.com>
Date: Mon, 27 Jul 2026 03:57:51 -0500
Subject: [PATCH 3/6] format fix

---
 llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp               | 2 +-
 .../CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir  | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp b/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp
index c7ed1b0d02e6b..f8bb13172d724 100644
--- a/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp
+++ b/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp
@@ -167,7 +167,7 @@ void SIPreAllocateWWMRegs::rewriteRegs(MachineFunction &MF) {
 
   RegsToRewrite.clear();
 
-  // Update the set of reserved registers to include WWM ones 
+  // Update the set of reserved registers to include WWM ones
   // without unnecessarily invalidating RegClassInfo
   MRI->freezeReservedRegs();
   RegClassInfo.updateReservedRegs(MRI->getReservedRegs());
diff --git a/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir b/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir
index 9b2793795e35c..703fe595b3cad 100644
--- a/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir
+++ b/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir
@@ -1,5 +1,5 @@
-# RUN: llc -mtriple=amdgpu9.0a -passes="require<machine-register-class-info>,si-pre-allocate-wwm-regs,require<machine-register-class-info>" -debug-pass-manager -filetype=null %s 2>&1 | FileCheck %s
-# RUN: llc -mtriple=amdgpu9.0a -passes=si-pre-allocate-wwm-regs -o - %s | FileCheck %s --check-prefix=MIR
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -passes="require<machine-register-class-info>,si-pre-allocate-wwm-regs,require<machine-register-class-info>" -debug-pass-manager -filetype=null %s 2>&1 | FileCheck %s
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -passes=si-pre-allocate-wwm-regs -o - %s | FileCheck %s --check-prefix=MIR
 
 # INFO: Test that WWM preallocation updates MachineRegisterClassInfo in place
 # instead of invalidating it, so the analysis is not recomputed afterwards.

>From de9ab11538b0152db507cb5a9f0fa7db9071edf4 Mon Sep 17 00:00:00 2001
From: Nikhil Kotikalapudi <Nikhil.Kotikalapudi at amd.com>
Date: Mon, 27 Jul 2026 09:52:24 -0500
Subject: [PATCH 4/6] comments fix

---
 llvm/include/llvm/CodeGen/RegisterClassInfo.h   | 15 +++++++--------
 llvm/lib/CodeGen/RegisterClassInfo.cpp          |  4 ++--
 llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp |  2 +-
 3 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/RegisterClassInfo.h b/llvm/include/llvm/CodeGen/RegisterClassInfo.h
index 53e7faba12555..cd5c62add4a67 100644
--- a/llvm/include/llvm/CodeGen/RegisterClassInfo.h
+++ b/llvm/include/llvm/CodeGen/RegisterClassInfo.h
@@ -98,14 +98,13 @@ class RegisterClassInfo {
   LLVM_ABI void runOnMachineFunction(const MachineFunction &MF,
                                      bool Rev = false);
 
-  /// allows modification of current reserved register vector
-  /// without invalidating RCI and triggering recomputation when possible
-  /// prereqs for use:
-  ///     RCI already initialized,
-  ///     the caller updated MRI's reserved vector
-  ///     note: target information, callee-saved regs, cost, and alloc order
-  ///     must not change.
-  ///     input: MRI's current frozen vector
+  /// Update cached register class information using \p ReservedInput, MRI's
+  /// current frozen reserved-register set. Cached orders are compacted when
+  /// only registers are added and `-stress-regalloc` is disabled; otherwise,
+  /// they are invalidated and recomputed on demand.
+  ///
+  /// RegisterClassInfo must be initialized. Target information, callee-saved
+  /// registers, register costs, and allocation orders must remain unchanged.
   LLVM_ABI void updateReservedRegs(const BitVector &ReservedInput);
 
   LLVM_ABI bool invalidate(MachineFunction &, const PreservedAnalyses &PA,
diff --git a/llvm/lib/CodeGen/RegisterClassInfo.cpp b/llvm/lib/CodeGen/RegisterClassInfo.cpp
index fcb2f6f8d65e7..2b39ba13d4ccb 100644
--- a/llvm/lib/CodeGen/RegisterClassInfo.cpp
+++ b/llvm/lib/CodeGen/RegisterClassInfo.cpp
@@ -134,7 +134,7 @@ void RegisterClassInfo::updateReservedRegs(const BitVector &ReservedInput) {
   // Cached orders cannot regain unreserved registers; recompute them lazily.
   bool OnlyNewReservations = Reserved.subsetOf(ReservedInput);
 
-  // subtracts reserved set from input set to get newly reserved regs
+  // Subtract the old set to find newly reserved registers.
   BitVector NewReservations = ReservedInput;
   NewReservations.reset(Reserved);
 
@@ -153,7 +153,7 @@ void RegisterClassInfo::updateReservedRegs(const BitVector &ReservedInput) {
   for (const TargetRegisterClass &RC : TRI->regclasses()) {
     RCInfo &Info = RegClass[RC.getID()];
 
-    // skip if class info is out of date
+    // Skip stale class information.
     if (Info.Tag != Tag)
       continue;
 
diff --git a/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp b/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp
index f8bb13172d724..4c47728851591 100644
--- a/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp
+++ b/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp
@@ -168,7 +168,7 @@ void SIPreAllocateWWMRegs::rewriteRegs(MachineFunction &MF) {
   RegsToRewrite.clear();
 
   // Update the set of reserved registers to include WWM ones
-  // without unnecessarily invalidating RegClassInfo
+  // without unnecessarily invalidating RegClassInfo.
   MRI->freezeReservedRegs();
   RegClassInfo.updateReservedRegs(MRI->getReservedRegs());
 }

>From 47afed3814d4a62168daab861b08bc0578cfd75b Mon Sep 17 00:00:00 2001
From: Nikhil Kotikalapudi <Nikhil.Kotikalapudi at amd.com>
Date: Sun, 2 Aug 2026 16:39:28 -0500
Subject: [PATCH 5/6] replaced check-not with exhaustive order check

---
 .../si-pre-allocate-wwm-regs-preserve-rci.mir | 30 ++++++++++++++-----
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir b/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir
index 703fe595b3cad..ff07f41b18373 100644
--- a/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir
+++ b/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir
@@ -1,13 +1,29 @@
-# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -passes="require<machine-register-class-info>,si-pre-allocate-wwm-regs,require<machine-register-class-info>" -debug-pass-manager -filetype=null %s 2>&1 | FileCheck %s
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -passes="require<machine-register-class-info>,si-pre-allocate-wwm-regs,require<machine-register-class-info>" -debug-pass-manager -o /dev/null %s 2>&1 | FileCheck %s
 # RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -passes=si-pre-allocate-wwm-regs -o - %s | FileCheck %s --check-prefix=MIR
 
-# INFO: Test that WWM preallocation updates MachineRegisterClassInfo in place
-# instead of invalidating it, so the analysis is not recomputed afterwards.
+# Test that WWM preallocation updates MachineRegisterClassInfo in place instead
+# of invalidating it. The pass manager log is matched in full, so the second
+# require<machine-register-class-info> is shown to run without recomputing
+# MachineRegisterClassAnalysis.
 
-# CHECK: Running analysis: MachineRegisterClassAnalysis on test_wwm_reserved
-# CHECK: Running pass: SIPreAllocateWWMRegsPass on test_wwm_reserved
-# CHECK-NOT: Invalidating analysis: MachineRegisterClassAnalysis on test_wwm_reserved
-# CHECK-NOT: Running analysis: MachineRegisterClassAnalysis on test_wwm_reserved
+# CHECK:      Running analysis: MachineModuleAnalysis on [module]
+# CHECK-NEXT: Running analysis: InnerAnalysisManagerProxy<llvm::AnalysisManager<llvm::Function>, llvm::Module> on [module]
+# CHECK-NEXT: Running analysis: MachineFunctionAnalysis on test_wwm_reserved
+# CHECK-NEXT: Running analysis: OuterAnalysisManagerProxy<llvm::AnalysisManager<llvm::Module>, llvm::Function> on test_wwm_reserved
+# CHECK-NEXT: Running analysis: InnerAnalysisManagerProxy<llvm::AnalysisManager<llvm::MachineFunction>, llvm::Function> on test_wwm_reserved
+# CHECK-NEXT: Running pass: RequireAnalysisPass<llvm::MachineRegisterClassAnalysis, llvm::MachineFunction> on test_wwm_reserved
+# CHECK-NEXT: Running analysis: MachineRegisterClassAnalysis on test_wwm_reserved
+# CHECK-NEXT: Running pass: SIPreAllocateWWMRegsPass on test_wwm_reserved
+# CHECK-NEXT: Running analysis: LiveIntervalsAnalysis on test_wwm_reserved
+# CHECK-NEXT: Running analysis: MachineDominatorTreeAnalysis on test_wwm_reserved
+# CHECK-NEXT: Running analysis: SlotIndexesAnalysis on test_wwm_reserved
+# CHECK-NEXT: Running analysis: LiveRegMatrixAnalysis on test_wwm_reserved
+# CHECK-NEXT: Running analysis: VirtRegMapAnalysis on test_wwm_reserved
+# CHECK-NEXT: Running pass: RequireAnalysisPass<llvm::MachineRegisterClassAnalysis, llvm::MachineFunction> on test_wwm_reserved
+# CHECK-NEXT: Running pass: PrintMIRPreparePass on [module]
+# CHECK-NEXT: Running pass: MachineVerifierPass on test_wwm_reserved
+# CHECK-NEXT: Running pass: PrintMIRPass on test_wwm_reserved
+# CHECK-NEXT: Running analysis: FunctionAnalysisManagerMachineFunctionProxy on test_wwm_reserved
 
 # MIR: wwmReservedRegs:
 # MIR-NEXT: - '$vgpr0'

>From a72eae27fca81b03f152b3d1d16de7a438a7df00 Mon Sep 17 00:00:00 2001
From: Nikhil Kotikalapudi <Nikhil.Kotikalapudi at amd.com>
Date: Sun, 2 Aug 2026 19:47:35 -0500
Subject: [PATCH 6/6] reduced window for pass manager log check, alias testing

---
 .../si-pre-allocate-wwm-regs-preserve-rci.mir | 57 +++++++++++--------
 1 file changed, 34 insertions(+), 23 deletions(-)

diff --git a/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir b/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir
index ff07f41b18373..ba4590792c0e0 100644
--- a/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir
+++ b/llvm/test/CodeGen/AMDGPU/si-pre-allocate-wwm-regs-preserve-rci.mir
@@ -1,33 +1,42 @@
-# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -passes="require<machine-register-class-info>,si-pre-allocate-wwm-regs,require<machine-register-class-info>" -debug-pass-manager -o /dev/null %s 2>&1 | FileCheck %s
-# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -passes=si-pre-allocate-wwm-regs -o - %s | FileCheck %s --check-prefix=MIR
-
-# Test that WWM preallocation updates MachineRegisterClassInfo in place instead
-# of invalidating it. The pass manager log is matched in full, so the second
-# require<machine-register-class-info> is shown to run without recomputing
-# MachineRegisterClassAnalysis.
-
-# CHECK:      Running analysis: MachineModuleAnalysis on [module]
-# CHECK-NEXT: Running analysis: InnerAnalysisManagerProxy<llvm::AnalysisManager<llvm::Function>, llvm::Module> on [module]
-# CHECK-NEXT: Running analysis: MachineFunctionAnalysis on test_wwm_reserved
-# CHECK-NEXT: Running analysis: OuterAnalysisManagerProxy<llvm::AnalysisManager<llvm::Module>, llvm::Function> on test_wwm_reserved
-# CHECK-NEXT: Running analysis: InnerAnalysisManagerProxy<llvm::AnalysisManager<llvm::MachineFunction>, llvm::Function> on test_wwm_reserved
-# CHECK-NEXT: Running pass: RequireAnalysisPass<llvm::MachineRegisterClassAnalysis, llvm::MachineFunction> on test_wwm_reserved
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a \
+# RUN:   -passes="require<machine-register-class-info>,si-pre-allocate-wwm-regs,require<machine-register-class-info>" \
+# RUN:   -debug-pass-manager -o /dev/null %s 2>&1 | FileCheck %s
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a \
+# RUN:   -passes=si-pre-allocate-wwm-regs -o - %s | FileCheck %s --check-prefix=MIR
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a \
+# RUN:   -passes="si-pre-allocate-wwm-regs,greedy<vgpr>,virt-reg-rewriter" \
+# RUN:   -o - %s | FileCheck %s --check-prefix=ALIAS
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a \
+# RUN:   -passes="greedy<vgpr>,virt-reg-rewriter" \
+# RUN:   -o - %s | FileCheck %s --check-prefix=NO-WWM
+
+# Verify that SIPreAllocateWWMRegsPass updates the
+# MachineRegisterClassAnalysis result in place. The second require must reuse
+# the result computed by the first.
+
+# CHECK:      Running pass: RequireAnalysisPass<llvm::MachineRegisterClassAnalysis, llvm::MachineFunction> on test_wwm_reserved
 # CHECK-NEXT: Running analysis: MachineRegisterClassAnalysis on test_wwm_reserved
 # CHECK-NEXT: Running pass: SIPreAllocateWWMRegsPass on test_wwm_reserved
-# CHECK-NEXT: Running analysis: LiveIntervalsAnalysis on test_wwm_reserved
-# CHECK-NEXT: Running analysis: MachineDominatorTreeAnalysis on test_wwm_reserved
-# CHECK-NEXT: Running analysis: SlotIndexesAnalysis on test_wwm_reserved
-# CHECK-NEXT: Running analysis: LiveRegMatrixAnalysis on test_wwm_reserved
-# CHECK-NEXT: Running analysis: VirtRegMapAnalysis on test_wwm_reserved
-# CHECK-NEXT: Running pass: RequireAnalysisPass<llvm::MachineRegisterClassAnalysis, llvm::MachineFunction> on test_wwm_reserved
+# CHECK:      Running pass: RequireAnalysisPass<llvm::MachineRegisterClassAnalysis, llvm::MachineFunction> on test_wwm_reserved
 # CHECK-NEXT: Running pass: PrintMIRPreparePass on [module]
-# CHECK-NEXT: Running pass: MachineVerifierPass on test_wwm_reserved
-# CHECK-NEXT: Running pass: PrintMIRPass on test_wwm_reserved
-# CHECK-NEXT: Running analysis: FunctionAnalysisManagerMachineFunctionProxy on test_wwm_reserved
 
 # MIR: wwmReservedRegs:
 # MIR-NEXT: - '$vgpr0'
 
+# Verify that reserving $vgpr0 for WWM also reserves the aliasing tuple
+# $vgpr0_vgpr1. The allocator must assign %4 to the next available tuple.
+
+# ALIAS:      $vgpr0 = V_MOV_B32_e32 0, implicit $exec
+# ALIAS:      $exec = EXIT_STRICT_WWM killed renamable $sgpr4_sgpr5
+# ALIAS-NEXT: renamable $vgpr1_vgpr2 = IMPLICIT_DEF
+# ALIAS-NEXT: S_NOP 0, implicit killed renamable $vgpr1_vgpr2
+
+# Without WWM preallocation, the allocator must assign %4 to the first tuple.
+
+# NO-WWM:      $exec = EXIT_STRICT_WWM killed renamable $sgpr4_sgpr5
+# NO-WWM-NEXT: renamable $vgpr0_vgpr1 = IMPLICIT_DEF
+# NO-WWM-NEXT: S_NOP 0, implicit killed renamable $vgpr0_vgpr1
+
 ---
 name: test_wwm_reserved
 tracksRegLiveness: true
@@ -40,4 +49,6 @@ body: |
     %2:vgpr_32 = V_MOV_B32_dpp %1, %0, 323, 12, 15, 0, implicit $exec
     $exec = EXIT_STRICT_WWM killed renamable $sgpr4_sgpr5
     %3:vgpr_32 = COPY %0
+    %4:vreg_64 = IMPLICIT_DEF
+    S_NOP 0, implicit %4
 ...



More information about the llvm-commits mailing list