[llvm] [AMDGPU] Expose buffer resource num_records width in TargetParser (PR #220103)
Krzysztof Drewniak via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 10 12:52:26 PDT 2026
https://github.com/krzysz00 updated https://github.com/llvm/llvm-project/pull/220103
>From 32073c3d11881ce436d460df9ec2b105f86539e9 Mon Sep 17 00:00:00 2001
From: Krzysztof Drewniak <Krzysztof.Drewniak at amd.com>
Date: Mon, 31 Aug 2026 19:32:14 +0000
Subject: [PATCH 1/3] [AMDGPU] Expose buffer resource num_records width in
TargetParser
This also fixes the conflict in gfx12.
Co-Authored-By: Claude Opus 5 (1M context) <noreply at anthropic.com>
---
llvm/include/llvm/TargetParser/AMDGPUTargetParser.h | 6 ++++++
llvm/lib/Target/AMDGPU/AMDGPU.td | 2 +-
llvm/lib/TargetParser/AMDGPUTargetParser.cpp | 13 +++++++++++++
.../utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp | 3 ++-
4 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h b/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
index 3f74320675d12..f4b3ecaf93d08 100644
--- a/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
+++ b/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
@@ -212,6 +212,12 @@ constexpr unsigned getNumWorkGroupSIMDs(bool FullSIMDMode) {
/// \returns Minimum number of waves per execution unit.
constexpr unsigned getMinWavesPerEU() { return 1; }
+/// \returns Number of bits in the num_records field is a buffer resource,
+/// or nullopt if the target is too generic to have a fixed value for that.
+LLVM_ABI std::optional<unsigned> getBufferResourceNumRecordsWidth(GPUKind AK);
+LLVM_ABI std::optional<unsigned>
+getBufferResourceNumRecordsWidth(Triple::SubArchType SubArch);
+
/// \returns Maximum number of waves per execution unit without any kind of
/// limitation.
LLVM_ABI unsigned getMaxWavesPerEU(GPUKind AK);
diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td
index 6df3cb2761616..0e91855eacd41 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPU.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPU.td
@@ -1791,7 +1791,6 @@ def FeatureGFX12 : GCNSubtargetFeatureGeneration<"GFX12",
FeatureMinimum3Maximum3F32, FeatureMinimum3Maximum3F16,
FeatureAgentScopeFineGrainedRemoteMemoryAtomics, FeatureFlatOffsetBits24,
FeatureFlatSignedOffset, FeatureInstCacheLineSize128,
- Feature32BitNumRecordsBufferResource,
FeatureMaxWavesPerEU16
]
>;
@@ -2293,6 +2292,7 @@ def FeatureISAVersion11_7_Generic: FeatureSet<
def FeatureISAVersion12 : FeatureSet<
[FeatureGFX12,
+ Feature32BitNumRecordsBufferResource,
FeatureSupportsWave64, FeatureSupportsWGP,
FeatureBackOffBarrier,
FeatureAddressableLocalMemorySize65536,
diff --git a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
index bf6acf0774215..2b50d8be327e8 100644
--- a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
+++ b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
@@ -42,6 +42,7 @@ struct GPUInfo {
uint8_t MaxWavesPerEU;
uint32_t MaxHWAddressableLocalMemorySize;
uint8_t LDSBankCount;
+ uint8_t BufferResourceNumRecordsWidth;
};
// Per-GPU data for the R600 GPUKinds.
@@ -485,6 +486,18 @@ unsigned AMDGPU::getLDSBankCount(Triple::SubArchType SubArch) {
return getLDSBankCount(getGPUKindFromSubArch(SubArch));
}
+std::optional<unsigned> AMDGPU::getBufferResourceNumRecordsWidth(GPUKind AK) {
+ const GPUInfo *Info = getAMDGPUInfo(AK);
+ if (!Info)
+ return std::nullopt;
+ return Info->BufferResourceNumRecordsWidth;
+}
+
+std::optional<unsigned>
+AMDGPU::getBufferResourceNumRecordsWidth(Triple::SubArchType SubArch) {
+ return getBufferResourceNumRecordsWidth(getGPUKindFromSubArch(SubArch));
+}
+
unsigned AMDGPU::getMaxWavesPerEU(GPUKind AK) {
const GPUInfo *Info = getAMDGPUInfo(AK);
return Info ? Info->MaxWavesPerEU : 10;
diff --git a/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp b/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
index d4a5f3084af75..21d7aa51de321 100644
--- a/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
@@ -610,7 +610,8 @@ emitAMDGPUTable(raw_ostream &OS, const RecordKeeper &RK,
OS << ", " << Names.GetOrAddStringOffset(Family) << ", "
<< getFeatureValue(R, "MaxWavesPerEU", 10) << ", "
<< getFeatureValue(R, "AddressableLocalMemorySize", 32768) << ", "
- << getFeatureValue(R, "LDSBankCount", 32) << "},\n";
+ << getFeatureValue(R, "LDSBankCount", 32) << ", "
+ << getFeatureValue(R, "BufferResourceNumRecordsWidth", 32) << "},\n";
}
OS << "};\n"
"#endif // GET_AMDGPU_GPU_TABLE\n\n";
>From 64a1e0f85c01a3ae49e63aafddcc026c0aef7a18 Mon Sep 17 00:00:00 2001
From: Krzysztof Drewniak <Krzysztof.Drewniak at amd.com>
Date: Tue, 1 Sep 2026 22:06:39 +0000
Subject: [PATCH 2/3] Review feedback
---
.../llvm/TargetParser/AMDGPUTargetParser.h | 4 +-
llvm/lib/TargetParser/AMDGPUTargetParser.cpp | 2 +-
.../TargetParser/TargetParserTest.cpp | 38 +++++++++++++++++++
.../TableGen/Basic/AMDGPUTargetDefEmitter.cpp | 2 +-
4 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h b/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
index f4b3ecaf93d08..b46a23ad1ec3a 100644
--- a/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
+++ b/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
@@ -212,8 +212,8 @@ constexpr unsigned getNumWorkGroupSIMDs(bool FullSIMDMode) {
/// \returns Minimum number of waves per execution unit.
constexpr unsigned getMinWavesPerEU() { return 1; }
-/// \returns Number of bits in the num_records field is a buffer resource,
-/// or nullopt if the target is too generic to have a fixed value for that.
+/// \returns Number of bits in the num_records field in a buffer resource,
+/// or nullopt if it is not known concretely.
LLVM_ABI std::optional<unsigned> getBufferResourceNumRecordsWidth(GPUKind AK);
LLVM_ABI std::optional<unsigned>
getBufferResourceNumRecordsWidth(Triple::SubArchType SubArch);
diff --git a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
index 2b50d8be327e8..48e8eb3bad41d 100644
--- a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
+++ b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
@@ -488,7 +488,7 @@ unsigned AMDGPU::getLDSBankCount(Triple::SubArchType SubArch) {
std::optional<unsigned> AMDGPU::getBufferResourceNumRecordsWidth(GPUKind AK) {
const GPUInfo *Info = getAMDGPUInfo(AK);
- if (!Info)
+ if (!Info || Info->BufferResourceNumRecordsWidth == 0)
return std::nullopt;
return Info->BufferResourceNumRecordsWidth;
}
diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp
index cbf3d86c48b13..0037bc63e7b0e 100644
--- a/llvm/unittests/TargetParser/TargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -3220,6 +3220,44 @@ TEST(TargetParserTest, testAMDGPUgetMaxHWAddressableLocalMemorySize) {
327680u);
}
+TEST(TargetParserTest, testAMDGPUgetBufferResourceNumRecordsWidth) {
+ EXPECT_EQ(AMDGPU::getBufferResourceNumRecordsWidth(AMDGPU::GK_GFX900), 32u);
+ EXPECT_EQ(AMDGPU::getBufferResourceNumRecordsWidth(AMDGPU::GK_GFX1201), 32u);
+ EXPECT_EQ(AMDGPU::getBufferResourceNumRecordsWidth(AMDGPU::GK_GFX1250), 45u);
+
+ // Generic families that agree on resource width behave.
+ EXPECT_EQ(AMDGPU::getBufferResourceNumRecordsWidth(AMDGPU::GK_GFX9_GENERIC),
+ 32u);
+
+ EXPECT_EQ(AMDGPU::getBufferResourceNumRecordsWidth(AMDGPU::GK_GENERIC),
+ std::nullopt);
+ EXPECT_EQ(AMDGPU::getBufferResourceNumRecordsWidth(AMDGPU::GK_GENERIC_HSA),
+ std::nullopt);
+
+ EXPECT_EQ(AMDGPU::getBufferResourceNumRecordsWidth(AMDGPU::GK_NONE),
+ std::nullopt);
+ EXPECT_EQ(AMDGPU::getBufferResourceNumRecordsWidth(AMDGPU::GK_R600),
+ std::nullopt);
+
+ EXPECT_EQ(AMDGPU::getBufferResourceNumRecordsWidth(Triple::NoSubArch),
+ std::nullopt);
+
+ SmallVector<StringRef, 0> AllGPUs;
+ AMDGPU::fillValidArchListAMDGCN(AllGPUs, Triple::NoSubArch);
+ ASSERT_FALSE(AllGPUs.empty());
+ for (StringRef Name : AllGPUs) {
+ AMDGPU::GPUKind Kind = AMDGPU::parseArchAMDGCN(Name);
+ std::optional<unsigned> Width =
+ AMDGPU::getBufferResourceNumRecordsWidth(Kind);
+ EXPECT_TRUE(Width.has_value())
+ << "no num_records width for '" << Name << "'";
+ // The two overloads must agree wherever the GPU has a subarch to look up.
+ Triple::SubArchType SubArch = AMDGPU::getSubArch(Kind);
+ EXPECT_EQ(AMDGPU::getBufferResourceNumRecordsWidth(SubArch), Width)
+ << "overloads disagree for '" << Name << "'";
+ }
+}
+
TEST(TargetParserTest, testAMDGPUgetNumWorkGroupSIMDs) {
EXPECT_EQ(AMDGPU::getNumWorkGroupSIMDs(true), 4u);
EXPECT_EQ(AMDGPU::getNumWorkGroupSIMDs(false), 2u);
diff --git a/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp b/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
index 21d7aa51de321..69da1d25896fb 100644
--- a/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
@@ -611,7 +611,7 @@ emitAMDGPUTable(raw_ostream &OS, const RecordKeeper &RK,
<< getFeatureValue(R, "MaxWavesPerEU", 10) << ", "
<< getFeatureValue(R, "AddressableLocalMemorySize", 32768) << ", "
<< getFeatureValue(R, "LDSBankCount", 32) << ", "
- << getFeatureValue(R, "BufferResourceNumRecordsWidth", 32) << "},\n";
+ << getFeatureValue(R, "BufferResourceNumRecordsWidth", 0) << "},\n";
}
OS << "};\n"
"#endif // GET_AMDGPU_GPU_TABLE\n\n";
>From f63dcd8d5433cd38e68102a220945312fc2b67b4 Mon Sep 17 00:00:00 2001
From: Krzysztof Drewniak <Krzysztof.Drewniak at amd.com>
Date: Wed, 2 Sep 2026 20:44:03 +0000
Subject: [PATCH 3/3] [AMDGPU][NFC] Account for the LDS bank count column in
the GPU table test
AMDGPUTargetDefSubArchSpelling.td spells out every column of the emitted
GPUInfo rows, so it has to be updated whenever one is added. The
num_records width and getLDSBankCount landed independently, and each
CHECK line only grew by one, leaving them a column short.
Co-Authored-By: Claude Opus 5 (1M context) <noreply at anthropic.com>
---
llvm/test/TableGen/AMDGPUTargetDefSubArchSpelling.td | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/test/TableGen/AMDGPUTargetDefSubArchSpelling.td b/llvm/test/TableGen/AMDGPUTargetDefSubArchSpelling.td
index c095ef1c8c2d3..69cf05499845f 100644
--- a/llvm/test/TableGen/AMDGPUTargetDefSubArchSpelling.td
+++ b/llvm/test/TableGen/AMDGPUTargetDefSubArchSpelling.td
@@ -44,9 +44,9 @@ def GFX88F : ProcessorModel<"gfx88f", NoSchedModel, []>,
// The GPU table: both the base GPU and the variant share the gfx8 family; the
// variant uses its own AMDGPUSubArch888A from the spelling.
-// CHECK: {[[#]], Triple::AMDGPUSubArch888, {{.*}}, {8, 8, 8}, [[FAM:[0-9]+]], [[#]], [[#]], [[#]]},
-// CHECK: {[[#]], Triple::AMDGPUSubArch888A, {{.*}}, {8, 8, 8}, [[FAM]], [[#]], [[#]], [[#]]},
-// CHECK: {[[#]], Triple::AMDGPUSubArch88F, {{.*}}, {8, 8, 15}, [[#]], [[#]], [[#]], [[#]]},
+// CHECK: {[[#]], Triple::AMDGPUSubArch888, {{.*}}, {8, 8, 8}, [[FAM:[0-9]+]], [[#]], [[#]], [[#]], [[#]]},
+// CHECK: {[[#]], Triple::AMDGPUSubArch888A, {{.*}}, {8, 8, 8}, [[FAM]], [[#]], [[#]], [[#]], [[#]]},
+// CHECK: {[[#]], Triple::AMDGPUSubArch88F, {{.*}}, {8, 8, 15}, [[#]], [[#]], [[#]], [[#]], [[#]]},
// The subarch-name table maps the variant's own subarch to its triple name.
// CHECK: {Triple::AMDGPUSubArch888A, [[#]], [[#]]},
More information about the llvm-commits
mailing list