[llvm] [AMDGPU] Move stress options into getMaxNumVectorRegs/getBaseMaxNumSGPRs (PR #214762)
Romanov Vlad via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 11 05:38:30 PDT 2026
https://github.com/romanovvlad updated https://github.com/llvm/llvm-project/pull/214762
>From 5c0c2e51b9b49814e5b18235fd00caaf30a64ef1 Mon Sep 17 00:00:00 2001
From: Vlad <Vladislav.Romanov at amd.com>
Date: Fri, 7 Aug 2026 05:40:32 -0500
Subject: [PATCH 1/2] [AMDGPU] Move stress options into
getMaxNumVectorRegs/getBaseMaxNumSGPRs
Move -amdgpu-stress-{vgpr,agpr,sgpr} options from
SIRegisterInfo::getReservedRegs into GCNSubtarget functions so that all
downstream consumers (NSA reassign, MFMA rewrite, scheduler) see the
stress limits, not just the reserved-reg path.
The function hierarchy is refactored so getMaxNumVectorRegs is the
primary computation point: it computes the occupancy budget, applies any
amdgpu-num-vgpr attribute override, splits VGPRs/AGPRs, then applies
stress overrides last.
---
llvm/lib/Target/AMDGPU/GCNSubtarget.cpp | 45 ++++++++++++++++++-----
llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp | 20 ----------
2 files changed, 35 insertions(+), 30 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp b/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp
index 1c0e718bd8d97..8f3955b4346ab 100644
--- a/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp
@@ -53,6 +53,18 @@ static cl::opt<unsigned>
cl::desc("Number of addresses from which to enable MIMG NSA."),
cl::init(2), cl::Hidden);
+static cl::opt<unsigned> StressVGPRLimit(
+ "amdgpu-stress-vgpr", cl::Hidden, cl::init(0),
+ cl::desc("Limit VGPRs to N arch registers"));
+
+static cl::opt<unsigned> StressAGPRLimit(
+ "amdgpu-stress-agpr", cl::Hidden, cl::init(0),
+ cl::desc("Limit AGPRs to N registers"));
+
+static cl::opt<unsigned> StressSGPRLimit(
+ "amdgpu-stress-sgpr", cl::Hidden, cl::init(0),
+ cl::desc("Limit SGPRs to N registers"));
+
GCNSubtarget::~GCNSubtarget() = default;
static AMDGPUSubtarget::Generation computeDefaultGeneration(const Triple &TT) {
@@ -571,6 +583,10 @@ unsigned GCNSubtarget::getBaseMaxNumSGPRs(
MaxNumSGPRs = Requested;
}
+ // Stress test: override SGPR limit.
+ if (StressSGPRLimit.getNumOccurrences())
+ MaxNumSGPRs = StressSGPRLimit;
+
if (hasSGPRInitBug())
MaxNumSGPRs = AMDGPU::IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG;
@@ -630,6 +646,18 @@ unsigned GCNSubtarget::getBaseMaxNumVGPRs(
}
unsigned GCNSubtarget::getMaxNumVGPRs(const Function &F) const {
+ auto [VGPRs, AGPRs] = getMaxNumVectorRegs(F);
+ // On gfx90a+ VGPRs and AGPRs share a unified register file.
+ // On gfx908 they are independent, so only VGPRs count toward the budget.
+ return hasGFX90AInsts() ? VGPRs + AGPRs : VGPRs;
+}
+
+unsigned GCNSubtarget::getMaxNumVGPRs(const MachineFunction &MF) const {
+ return getMaxNumVGPRs(MF.getFunction());
+}
+
+std::pair<unsigned, unsigned>
+GCNSubtarget::getMaxNumVectorRegs(const Function &F) const {
// Temporarily check both the attribute and the subtarget feature, until the
// latter is removed.
unsigned DynamicVGPRBlockSize = AMDGPU::getDynamicVGPRBlockSize(F);
@@ -637,18 +665,9 @@ unsigned GCNSubtarget::getMaxNumVGPRs(const Function &F) const {
DynamicVGPRBlockSize = getDynamicVGPRBlockSize();
std::pair<unsigned, unsigned> Waves = getWavesPerEU(F);
- return getBaseMaxNumVGPRs(
+ const unsigned MaxVectorRegs = getBaseMaxNumVGPRs(
F, {getMinNumVGPRs(Waves.second, DynamicVGPRBlockSize),
getMaxNumVGPRs(Waves.first, DynamicVGPRBlockSize)});
-}
-
-unsigned GCNSubtarget::getMaxNumVGPRs(const MachineFunction &MF) const {
- return getMaxNumVGPRs(MF.getFunction());
-}
-
-std::pair<unsigned, unsigned>
-GCNSubtarget::getMaxNumVectorRegs(const Function &F) const {
- const unsigned MaxVectorRegs = getMaxNumVGPRs(F);
unsigned MaxNumVGPRs = MaxVectorRegs;
unsigned MaxNumAGPRs = 0;
@@ -700,6 +719,12 @@ GCNSubtarget::getMaxNumVectorRegs(const Function &F) const {
MaxNumAGPRs = MaxNumVGPRs = MaxVectorRegs;
}
+ // Stress test: override VGPR/AGPR limits.
+ if (StressVGPRLimit.getNumOccurrences())
+ MaxNumVGPRs = StressVGPRLimit;
+ if (StressAGPRLimit.getNumOccurrences())
+ MaxNumAGPRs = StressAGPRLimit;
+
return std::pair(MaxNumVGPRs, MaxNumAGPRs);
}
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index a3d6509628d50..12965056f6ec9 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -40,18 +40,6 @@ static cl::opt<bool> EnableSpillCFISavedRegs(
cl::desc("Enable spilling the registers required for CFI emission"),
cl::ReallyHidden, cl::init(false), cl::ZeroOrMore);
-static cl::opt<unsigned> StressVGPRLimit(
- "amdgpu-stress-vgpr", cl::Hidden, cl::init(0),
- cl::desc("Limit VGPRs to N registers by reserving the rest"));
-
-static cl::opt<unsigned> StressAGPRLimit(
- "amdgpu-stress-agpr", cl::Hidden, cl::init(0),
- cl::desc("Limit AGPRs to N registers by reserving the rest"));
-
-static cl::opt<unsigned> StressSGPRLimit(
- "amdgpu-stress-sgpr", cl::Hidden, cl::init(0),
- cl::desc("Limit SGPRs to N registers by reserving the rest"));
-
std::array<std::vector<int16_t>, 32> SIRegisterInfo::RegSplitParts;
std::array<std::array<uint16_t, 32>, 9> SIRegisterInfo::SubRegFromChannelTable;
@@ -656,8 +644,6 @@ BitVector SIRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
// Reserve SGPRs.
//
unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
- if (StressSGPRLimit.getNumOccurrences() && StressSGPRLimit < MaxNumSGPRs)
- MaxNumSGPRs = StressSGPRLimit;
unsigned TotalNumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
for (const TargetRegisterClass &RC : regclasses()) {
if (RC.isBaseClass() && isSGPRClass(&RC)) {
@@ -715,12 +701,6 @@ BitVector SIRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
//
auto [MaxNumVGPRs, MaxNumAGPRs] = ST.getMaxNumVectorRegs(MF.getFunction());
- // Stress test: override VGPR/AGPR limits.
- if (StressVGPRLimit.getNumOccurrences() && StressVGPRLimit < MaxNumVGPRs)
- MaxNumVGPRs = StressVGPRLimit;
- if (StressAGPRLimit.getNumOccurrences() && StressAGPRLimit < MaxNumAGPRs)
- MaxNumAGPRs = StressAGPRLimit;
-
for (const TargetRegisterClass &RC : regclasses()) {
if (RC.isBaseClass() && isVGPRClass(&RC)) {
unsigned NumRegs = divideCeil(getRegSizeInBits(RC), 32);
>From c0b968af4fbc847960397afce7e78d639dccd276 Mon Sep 17 00:00:00 2001
From: Vlad <Vladislav.Romanov at amd.com>
Date: Tue, 11 Aug 2026 07:32:45 -0500
Subject: [PATCH 2/2] fix formatting
---
llvm/lib/Target/AMDGPU/GCNSubtarget.cpp | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp b/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp
index 8f3955b4346ab..25796e540ee03 100644
--- a/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp
@@ -53,17 +53,17 @@ static cl::opt<unsigned>
cl::desc("Number of addresses from which to enable MIMG NSA."),
cl::init(2), cl::Hidden);
-static cl::opt<unsigned> StressVGPRLimit(
- "amdgpu-stress-vgpr", cl::Hidden, cl::init(0),
- cl::desc("Limit VGPRs to N arch registers"));
+static cl::opt<unsigned>
+ StressVGPRLimit("amdgpu-stress-vgpr", cl::Hidden, cl::init(0),
+ cl::desc("Limit VGPRs to N arch registers"));
-static cl::opt<unsigned> StressAGPRLimit(
- "amdgpu-stress-agpr", cl::Hidden, cl::init(0),
- cl::desc("Limit AGPRs to N registers"));
+static cl::opt<unsigned>
+ StressAGPRLimit("amdgpu-stress-agpr", cl::Hidden, cl::init(0),
+ cl::desc("Limit AGPRs to N registers"));
-static cl::opt<unsigned> StressSGPRLimit(
- "amdgpu-stress-sgpr", cl::Hidden, cl::init(0),
- cl::desc("Limit SGPRs to N registers"));
+static cl::opt<unsigned>
+ StressSGPRLimit("amdgpu-stress-sgpr", cl::Hidden, cl::init(0),
+ cl::desc("Limit SGPRs to N registers"));
GCNSubtarget::~GCNSubtarget() = default;
More information about the llvm-commits
mailing list