[llvm] [AMDGPU] Introduce subtarget features `FeatureLDSAllocGranularity<size>` and expose them to the frontend (PR #220394)
Chinmay Deshpande via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 10 14:55:19 PDT 2026
https://github.com/chinmaydd updated https://github.com/llvm/llvm-project/pull/220394
>From 4240da505c860de27e70bdbccd0b861fd084229c Mon Sep 17 00:00:00 2001
From: Chinmay Deshpande <chdeshpa at amd.com>
Date: Thu, 10 Sep 2026 14:56:13 -0400
Subject: [PATCH] [AMDGPU] Model LDS allocation granularity with subtarget
features
Add numeric LDS allocation granularity features, expose them through the TargetParser feature bitset, and use them in the existing backend query.
Generic targets select the largest covered allocation granularity so their resource calculations remain conservative.
Change-Id: Icdd501d008c9d3cd566bdc8bde4a75d566ecb90a
---
llvm/lib/Target/AMDGPU/AMDGPU.td | 26 ++++++-
llvm/lib/Target/AMDGPU/AMDGPUFeatures.td | 17 +++++
llvm/lib/Target/AMDGPU/R600Processors.td | 6 +-
.../Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp | 12 ++--
llvm/lib/TargetParser/AMDGPUTargetParser.cpp | 7 +-
llvm/test/TableGen/AMDGPUTargetDefErrors.td | 70 +++++++++++++++++++
.../TargetParser/TargetParserTest.cpp | 46 ++++++++++++
.../TableGen/Basic/AMDGPUTargetDefEmitter.cpp | 57 +++++++++++++--
8 files changed, 223 insertions(+), 18 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td
index 6df3cb2761616..f4f0213f2ced7 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPU.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPU.td
@@ -1614,7 +1614,8 @@ class GCNSubtargetFeatureGeneration <string Value,
def FeatureSouthernIslands : GCNSubtargetFeatureGeneration<"SOUTHERN_ISLANDS",
"southern-islands",
- [FeatureFP64, FeatureAddressableLocalMemorySize32768, FeatureMIMG_R128,
+ [FeatureFP64, FeatureAddressableLocalMemorySize32768,
+ FeatureLDSAllocGranularity256, FeatureMIMG_R128,
FeatureWavefrontSize64, FeatureSupportsWave64, FeatureSMemTimeInst,
FeatureMadMacF32Insts,
FeatureDsSrc2Insts, FeatureLDSBankCount32, FeatureMovrel,
@@ -1632,7 +1633,8 @@ def FeatureSouthernIslands : GCNSubtargetFeatureGeneration<"SOUTHERN_ISLANDS",
def FeatureSeaIslands : GCNSubtargetFeatureGeneration<"SEA_ISLANDS",
"sea-islands",
- [FeatureFP64, FeatureAddressableLocalMemorySize65536, FeatureMIMG_R128,
+ [FeatureFP64, FeatureAddressableLocalMemorySize65536,
+ FeatureLDSAllocGranularity512, FeatureMIMG_R128,
FeatureWavefrontSize64, FeatureSupportsWave64, FeatureFlatAddressSpace,
FeatureCIInsts, FeatureMovrel, FeatureTrigReducedRange,
FeatureGFX7GFX8GFX9Insts, FeatureSMemTimeInst, FeatureMadMacF32Insts,
@@ -1652,7 +1654,8 @@ def FeatureSeaIslands : GCNSubtargetFeatureGeneration<"SEA_ISLANDS",
def FeatureVolcanicIslands : GCNSubtargetFeatureGeneration<"VOLCANIC_ISLANDS",
"volcanic-islands",
- [FeatureFP64, FeatureAddressableLocalMemorySize65536, FeatureMIMG_R128,
+ [FeatureFP64, FeatureAddressableLocalMemorySize65536,
+ FeatureLDSAllocGranularity512, FeatureMIMG_R128,
FeatureWavefrontSize64, FeatureSupportsWave64, FeatureFlatAddressSpace,
FeatureGCN3Encoding, FeatureCIInsts, Feature16BitInsts,
FeatureSMemRealTime, FeatureVGPRIndexMode, FeatureMovrel,
@@ -1702,6 +1705,7 @@ def FeatureGFX9 : GCNSubtargetFeatureGeneration<"GFX9",
def FeatureGFX10 : GCNSubtargetFeatureGeneration<"GFX10",
"gfx10",
[FeatureFP64, FeatureAddressableLocalMemorySize65536,
+ FeatureLDSAllocGranularity512,
FeatureHalfAddressablePhysicalLocalMemory, FeatureMIMG_R128,
FeatureSupportsWave32, FeatureSupportsWave64, FeatureSupportsWGP,
FeatureFlatAddressSpace,
@@ -1736,6 +1740,7 @@ def FeatureGFX10 : GCNSubtargetFeatureGeneration<"GFX10",
def FeatureGFX11 : GCNSubtargetFeatureGeneration<"GFX11",
"gfx11",
[FeatureFP64, FeatureAddressableLocalMemorySize65536,
+ FeatureLDSAllocGranularity512,
FeatureHalfAddressablePhysicalLocalMemory, FeatureMIMG_R128,
FeatureSupportsWave32, FeatureSupportsWave64, FeatureSupportsWGP,
FeatureFlatAddressSpace, Feature16BitInsts,
@@ -1906,6 +1911,7 @@ def FeatureISAVersion8_1_0 : FeatureSet<
def FeatureISAVersion9_0_Common : FeatureSet<
[FeatureGFX9,
FeatureAddressableLocalMemorySize65536,
+ FeatureLDSAllocGranularity512,
FeatureLDSBankCount32,
FeatureImageInsts,
FeatureMadMacF32Insts]>;
@@ -2055,6 +2061,7 @@ def FeatureISAVersion9_4_Common : FeatureSet<
def FeatureISAVersion9_5_Common : FeatureSet<
!listconcat(FeatureISAVersion9_4_Common.Features,
[FeatureAddressableLocalMemorySize163840,
+ FeatureLDSAllocGranularity1280,
FeatureLDSBankCount64,
FeatureFP8Insts,
FeatureFP8ConversionInsts,
@@ -2077,6 +2084,7 @@ def FeatureISAVersion9_4_2 : FeatureSet<
!listconcat(FeatureISAVersion9_4_Common.Features,
[
FeatureAddressableLocalMemorySize65536,
+ FeatureLDSAllocGranularity512,
FeatureLDSBankCount32,
FeatureFP8Insts,
FeatureFP8ConversionInsts,
@@ -2088,6 +2096,7 @@ def FeatureISAVersion9_4_2 : FeatureSet<
def FeatureISAVersion9_4_Generic : FeatureSet<
!listconcat(FeatureISAVersion9_4_Common.Features,
[FeatureAddressableLocalMemorySize65536,
+ FeatureLDSAllocGranularity1280,
FeatureLDSBankCount32,
FeatureRequiresCOV6])>;
@@ -2296,6 +2305,7 @@ def FeatureISAVersion12 : FeatureSet<
FeatureSupportsWave64, FeatureSupportsWGP,
FeatureBackOffBarrier,
FeatureAddressableLocalMemorySize65536,
+ FeatureLDSAllocGranularity512,
FeatureHalfAddressablePhysicalLocalMemory,
FeatureLDSBankCount32,
FeatureDLInsts,
@@ -2455,6 +2465,7 @@ def FeatureISAVersion12_50_STRICT : FeatureSet<
!listconcat(FeatureISAVersion12_50_Common.Features,
[FeatureGFX1250_STRICT,
FeatureAddressableLocalMemorySize327680,
+ FeatureLDSAllocGranularity2048,
FeatureLDSBankCount64,
FeatureWMMAN16Insts,
FeatureVOP3PX2IncrementsVaVdstTwice,
@@ -2484,6 +2495,7 @@ def FeatureISAVersion12_50_STRICT : FeatureSet<
def FeatureISAVersion12_50 : FeatureSet<
!listconcat(FeatureISAVersion12_50_Common.Features,
[FeatureAddressableLocalMemorySize327680,
+ FeatureLDSAllocGranularity2048,
FeatureLDSBankCount64,
FeatureWMMAN16Insts,
FeatureWMMAF4Insts,
@@ -2513,6 +2525,7 @@ def FeatureISAVersion12_50 : FeatureSet<
def FeatureISAVersion12_51 : FeatureSet<
!listconcat(FeatureISAVersion12_50_Common.Features,
[FeatureAddressableLocalMemorySize327680,
+ FeatureLDSAllocGranularity2048,
FeatureLDSBankCount64,
FeatureWMMAN16Insts,
FeatureWMMAF4Insts,
@@ -2550,6 +2563,7 @@ def FeatureISAVersion12_Generic: FeatureSet<
def FeatureISAVersion12_5_Generic: FeatureSet<
!listconcat(FeatureISAVersion12_50_Common.Features,
[FeatureAddressableLocalMemorySize327680,
+ FeatureLDSAllocGranularity2048,
FeatureLDSBankCount64,
FeatureSetregVGPRMSBFixup,
FeatureRequiresCOV6,
@@ -2565,6 +2579,7 @@ def FeatureISAVersion13 : FeatureSet<
[FeatureGFX13,
FeatureGFX1250Insts,
FeatureAddressableLocalMemorySize196608,
+ FeatureLDSAllocGranularity1024,
Feature64BitLiterals,
FeatureLDSBankCount32,
FeatureDLInsts,
@@ -3251,6 +3266,11 @@ def AMDGPUFrontendVisibleFeatures {
FeatureSGPRInitBug, FeatureApertureRegs, FeatureGetDoorbellID,
FeatureAGPRAlloc, Feature1536VGPRs, Feature1024AddressableVGPRs,
FeatureHalfAddressablePhysicalLocalMemory,
+ FeatureLDSAllocGranularity256,
+ FeatureLDSAllocGranularity512,
+ FeatureLDSAllocGranularity1024,
+ FeatureLDSAllocGranularity1280,
+ FeatureLDSAllocGranularity2048,
];
}
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUFeatures.td b/llvm/lib/Target/AMDGPU/AMDGPUFeatures.td
index 1d398830f07c6..fe598b07cb34f 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUFeatures.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPUFeatures.td
@@ -45,6 +45,23 @@ def FeatureAddressableLocalMemorySize163840 : SubtargetFeatureAddressableLocalMe
def FeatureAddressableLocalMemorySize196608 : SubtargetFeatureAddressableLocalMemorySize<196608>;
def FeatureAddressableLocalMemorySize327680 : SubtargetFeatureAddressableLocalMemorySize<327680>;
+class SubtargetFeatureLDSAllocGranularity <int Granularity> : SubtargetFeature <
+ "lds-alloc-granularity-"#Granularity,
+ "LDSAllocationGranularity",
+ !cast<string>(Granularity),
+ "LDS allocation granularity in bytes."
+> {
+ // SubtargetFeature.Value is string-typed; preserve the numeric value for
+ // TableGen backends.
+ int NumericValue = Granularity;
+}
+
+def FeatureLDSAllocGranularity256 : SubtargetFeatureLDSAllocGranularity<256>;
+def FeatureLDSAllocGranularity512 : SubtargetFeatureLDSAllocGranularity<512>;
+def FeatureLDSAllocGranularity1024 : SubtargetFeatureLDSAllocGranularity<1024>;
+def FeatureLDSAllocGranularity1280 : SubtargetFeatureLDSAllocGranularity<1280>;
+def FeatureLDSAllocGranularity2048 : SubtargetFeatureLDSAllocGranularity<2048>;
+
// Whether each wavefront size mode is available on the hardware,
// independent of the active mode.
def FeatureSupportsWave32 : SubtargetFeature<"supports-wave32",
diff --git a/llvm/lib/Target/AMDGPU/R600Processors.td b/llvm/lib/Target/AMDGPU/R600Processors.td
index 6637539d8c628..0daadf1423ad7 100644
--- a/llvm/lib/Target/AMDGPU/R600Processors.td
+++ b/llvm/lib/Target/AMDGPU/R600Processors.td
@@ -59,13 +59,15 @@ def FeatureR700 : R600SubtargetFeatureGeneration<"R700", "r700",
>;
def FeatureEvergreen : R600SubtargetFeatureGeneration<"EVERGREEN", "evergreen",
- [FeatureFetchLimit16, FeatureAddressableLocalMemorySize32768, FeatureMadMacF32Insts]
+ [FeatureFetchLimit16, FeatureAddressableLocalMemorySize32768,
+ FeatureLDSAllocGranularity256, FeatureMadMacF32Insts]
>;
def FeatureNorthernIslands : R600SubtargetFeatureGeneration<"NORTHERN_ISLANDS",
"northern-islands",
[FeatureFetchLimit16, FeatureWavefrontSize64,
- FeatureAddressableLocalMemorySize32768, FeatureMadMacF32Insts]
+ FeatureAddressableLocalMemorySize32768, FeatureLDSAllocGranularity256,
+ FeatureMadMacF32Insts]
>;
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
index 88e2d2f485262..3f83a873b3a0b 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
@@ -3661,17 +3661,17 @@ bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII,
}
unsigned getLdsDwGranularity(const MCSubtargetInfo &ST) {
- if (ST.getFeatureBits().test(FeatureAddressableLocalMemorySize32768))
+ if (ST.getFeatureBits().test(FeatureLDSAllocGranularity256))
return 64;
- if (ST.getFeatureBits().test(FeatureAddressableLocalMemorySize65536))
+ if (ST.getFeatureBits().test(FeatureLDSAllocGranularity512))
return 128;
- if (ST.getFeatureBits().test(FeatureAddressableLocalMemorySize196608))
+ if (ST.getFeatureBits().test(FeatureLDSAllocGranularity1024))
return 256;
- if (ST.getFeatureBits().test(FeatureAddressableLocalMemorySize163840))
+ if (ST.getFeatureBits().test(FeatureLDSAllocGranularity1280))
return 320;
- if (ST.getFeatureBits().test(FeatureAddressableLocalMemorySize327680))
+ if (ST.getFeatureBits().test(FeatureLDSAllocGranularity2048))
return 512;
- return 64; // In sync with getAddressableLocalMemorySize
+ return 64;
}
bool isPackedSingleSGPRFP32Inst(unsigned Opc) {
diff --git a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
index bf6acf0774215..e89d17918d3ff 100644
--- a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
+++ b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
@@ -521,7 +521,12 @@ static const AMDGPUFeatureBitset FrontendOnlyFeatures = {
FEAT_AGPR_ALLOC,
FEAT_1536_PHYSICAL_VGPRS,
FEAT_HALF_ADDRESSABLE_PHYSICAL_LOCAL_MEMORY,
- FEAT_1024_ADDRESSABLE_VGPRS};
+ FEAT_1024_ADDRESSABLE_VGPRS,
+ FEAT_LDS_ALLOC_GRANULARITY_256,
+ FEAT_LDS_ALLOC_GRANULARITY_512,
+ FEAT_LDS_ALLOC_GRANULARITY_1024,
+ FEAT_LDS_ALLOC_GRANULARITY_1280,
+ FEAT_LDS_ALLOC_GRANULARITY_2048};
// Add a GPU's features (minus the frontend-only ones) to \p Features. With \p
// Overwrite false, existing entries are kept so user -mattr overrides win.
diff --git a/llvm/test/TableGen/AMDGPUTargetDefErrors.td b/llvm/test/TableGen/AMDGPUTargetDefErrors.td
index fc6180fbf9e68..0c8580917104d 100644
--- a/llvm/test/TableGen/AMDGPUTargetDefErrors.td
+++ b/llvm/test/TableGen/AMDGPUTargetDefErrors.td
@@ -19,6 +19,10 @@
// RUN: | FileCheck %t/bad-stepping.td -DFILE=%t/bad-stepping.td --implicit-check-not="error:"
// RUN: not llvm-tblgen -gen-amdgpu-target-def -I %p/../../include %t/generic-feature-superset.td 2>&1 \
// RUN: | FileCheck %t/generic-feature-superset.td -DFILE=%t/generic-feature-superset.td --implicit-check-not="error:"
+// RUN: llvm-tblgen -gen-amdgpu-target-def -I %p/../../include %t/generic-lds-granularity-valid.td 2>&1 \
+// RUN: | FileCheck %t/generic-lds-granularity-valid.td --check-prefix=VALID
+// RUN: not llvm-tblgen -gen-amdgpu-target-def -I %p/../../include %t/generic-lds-granularity-invalid.td 2>&1 \
+// RUN: | FileCheck %t/generic-lds-granularity-invalid.td -DFILE=%t/generic-lds-granularity-invalid.td --implicit-check-not="error:"
// Verify the validation performed by the -gen-amdgpu-target-def backend.
@@ -165,3 +169,69 @@ def : ProcessorModel<"gfx9-generic", NoSchedModel, [FeatureFoo]>,
AMDGPUGPUInfo<[9, 0, 0]> {
let CoveredGPUs = [GFX900];
}
+
+//--- generic-lds-granularity-valid.td
+include "llvm/Target/Target.td"
+def MyTarget : Target;
+class AMDGPUArchFeature<string spelling> { string Spelling = spelling; }
+class AMDGPUGPUInfo<list<int> isa = []> {
+ list<AMDGPUArchFeature> ArchFeatures = [];
+ list<int> IsaVersion = isa;
+ list<Processor> CoveredGPUs = [];
+ bit IsPseudoTarget = false;
+}
+
+class SubtargetFeatureLDSAllocGranularity<int Granularity> : SubtargetFeature<
+ "granule-"#Granularity, "LDSAllocationGranularity",
+ !cast<string>(Granularity), "Granularity"> {
+ int NumericValue = Granularity;
+}
+def FeatureGranuleSmall : SubtargetFeatureLDSAllocGranularity<256>;
+def FeatureGranuleBig : SubtargetFeatureLDSAllocGranularity<512>;
+
+def AMDGPUFrontendVisibleFeatures {
+ list<SubtargetFeature> Features = [FeatureGranuleSmall, FeatureGranuleBig];
+}
+
+def GFX900 : ProcessorModel<"gfx900", NoSchedModel, [FeatureGranuleSmall]>,
+ AMDGPUGPUInfo<[9, 0, 0]>;
+
+// A generic carries the worst-case numeric field, so it keeps the larger
+// granularity while covering a GPU with a smaller one. That is not an error.
+// VALID: GK_GFX9_GENERIC
+def : ProcessorModel<"gfx9-generic", NoSchedModel, [FeatureGranuleBig]>,
+ AMDGPUGPUInfo<[9, 0, 0]> {
+ let CoveredGPUs = [GFX900];
+}
+
+//--- generic-lds-granularity-invalid.td
+include "llvm/Target/Target.td"
+def MyTarget : Target;
+class AMDGPUArchFeature<string spelling> { string Spelling = spelling; }
+class AMDGPUGPUInfo<list<int> isa = []> {
+ list<AMDGPUArchFeature> ArchFeatures = [];
+ list<int> IsaVersion = isa;
+ list<Processor> CoveredGPUs = [];
+ bit IsPseudoTarget = false;
+}
+
+class SubtargetFeatureLDSAllocGranularity<int Granularity> : SubtargetFeature<
+ "granule-"#Granularity, "LDSAllocationGranularity",
+ !cast<string>(Granularity), "Granularity"> {
+ int NumericValue = Granularity;
+}
+def FeatureGranuleSmall : SubtargetFeatureLDSAllocGranularity<256>;
+def FeatureGranuleBig : SubtargetFeatureLDSAllocGranularity<512>;
+
+def AMDGPUFrontendVisibleFeatures {
+ list<SubtargetFeature> Features = [FeatureGranuleSmall, FeatureGranuleBig];
+}
+
+def GFX900 : ProcessorModel<"gfx900", NoSchedModel, [FeatureGranuleBig]>,
+ AMDGPUGPUInfo<[9, 0, 0]>;
+
+// CHECK: [[FILE]]:[[#@LINE+1]]:1: error: generic target 'gfx9-generic' exposes feature 'granule-256' below the 'LDSAllocationGranularity' of covered GPU 'gfx900'
+def : ProcessorModel<"gfx9-generic", NoSchedModel, [FeatureGranuleSmall]>,
+ AMDGPUGPUInfo<[9, 0, 0]> {
+ let CoveredGPUs = [GFX900];
+}
diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp
index cbf3d86c48b13..4dfaaa12b49d7 100644
--- a/llvm/unittests/TargetParser/TargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -2826,6 +2826,14 @@ TEST(TargetParserTest, testAMDGPUfillAMDGPUFeatureMap) {
// A capability feature is queried through the bitset only.
EXPECT_FALSE(HasFeature("gfx1030", "half-addressable-physical-local-memory"));
+
+ // Numeric hardware properties stay out of the target-feature string. Merging
+ // multiple values there would silently select the largest one.
+ EXPECT_FALSE(HasFeature("gfx600", "lds-alloc-granularity-256"));
+ EXPECT_FALSE(HasFeature("gfx900", "lds-alloc-granularity-512"));
+ EXPECT_FALSE(HasFeature("gfx950", "lds-alloc-granularity-1280"));
+ EXPECT_FALSE(HasFeature("gfx1310", "lds-alloc-granularity-1024"));
+ EXPECT_FALSE(HasFeature("gfx1250", "lds-alloc-granularity-2048"));
}
TEST(TargetParserTest, testAMDGPUgetFeatureBitset) {
@@ -2876,6 +2884,44 @@ TEST(TargetParserTest, testAMDGPUHalfAddressableLDSFeature) {
EXPECT_FALSE(Has(AMDGPU::GK_GFX1310));
}
+TEST(TargetParserTest, testAMDGPULDSAllocGranularityFeatures) {
+ auto Has = [](AMDGPU::GPUKind AK, AMDGPU::AMDGPUFeature Feature) {
+ return AMDGPU::getFeatureBitset(AK).test(Feature);
+ };
+ auto Count = [&Has](AMDGPU::GPUKind AK) {
+ return Has(AK, AMDGPU::FEAT_LDS_ALLOC_GRANULARITY_256) +
+ Has(AK, AMDGPU::FEAT_LDS_ALLOC_GRANULARITY_512) +
+ Has(AK, AMDGPU::FEAT_LDS_ALLOC_GRANULARITY_1024) +
+ Has(AK, AMDGPU::FEAT_LDS_ALLOC_GRANULARITY_1280) +
+ Has(AK, AMDGPU::FEAT_LDS_ALLOC_GRANULARITY_2048);
+ };
+
+ // Exactly one allocation granularity is set per GPU.
+ EXPECT_EQ(Count(AMDGPU::GK_GFX600), 1);
+ EXPECT_EQ(Count(AMDGPU::GK_GFX900), 1);
+ EXPECT_EQ(Count(AMDGPU::GK_GFX950), 1);
+ EXPECT_EQ(Count(AMDGPU::GK_GFX1310), 1);
+ EXPECT_EQ(Count(AMDGPU::GK_GFX1250), 1);
+ EXPECT_EQ(Count(AMDGPU::GK_GFX9_4_GENERIC), 1);
+
+ // The legacy pseudo-targets do not represent hardware.
+ EXPECT_EQ(Count(AMDGPU::GK_GENERIC), 0);
+ EXPECT_EQ(Count(AMDGPU::GK_GENERIC_HSA), 0);
+
+ EXPECT_TRUE(Has(AMDGPU::GK_GFX600, AMDGPU::FEAT_LDS_ALLOC_GRANULARITY_256));
+ EXPECT_TRUE(Has(AMDGPU::GK_GFX900, AMDGPU::FEAT_LDS_ALLOC_GRANULARITY_512));
+ EXPECT_TRUE(Has(AMDGPU::GK_GFX950, AMDGPU::FEAT_LDS_ALLOC_GRANULARITY_1280));
+ EXPECT_TRUE(Has(AMDGPU::GK_GFX1310, AMDGPU::FEAT_LDS_ALLOC_GRANULARITY_1024));
+ EXPECT_TRUE(Has(AMDGPU::GK_GFX1250, AMDGPU::FEAT_LDS_ALLOC_GRANULARITY_2048));
+
+ // A generic target uses the largest allocation granularity of the GPUs it
+ // covers. gfx9-4-generic therefore uses gfx950's 1280-byte granule.
+ EXPECT_TRUE(
+ Has(AMDGPU::GK_GFX9_4_GENERIC, AMDGPU::FEAT_LDS_ALLOC_GRANULARITY_1280));
+ EXPECT_FALSE(
+ Has(AMDGPU::GK_GFX9_4_GENERIC, AMDGPU::FEAT_LDS_ALLOC_GRANULARITY_512));
+}
+
TEST(TargetParserTest, testAMDGPUfillValidArchListAMDGCN) {
SmallVector<StringRef, 0> All;
AMDGPU::fillValidArchListAMDGCN(All, Triple::NoSubArch);
diff --git a/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp b/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
index d4a5f3084af75..9e7923777a2f9 100644
--- a/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
@@ -476,14 +476,44 @@ collectVisibleFeatures(const Record *GPU,
return Visible;
}
+// Return the LDS allocation granularity in \p GPU's feature closure. Two
+// features setting different granularities is an error: SubtargetFeature
+// silently takes the larger.
+static int64_t getLDSAllocGranularity(const Record *GPU) {
+ SetVector<const Record *> Closure;
+ collectFeatureClosure(GPU, Closure);
+
+ const Record *Found = nullptr;
+ int64_t Value = 256;
+ for (const Record *F : Closure) {
+ if (F->getValueAsString("FieldName") != "LDSAllocationGranularity")
+ continue;
+
+ int64_t V = F->getValueAsInt("NumericValue");
+ if (Found && V != Value) {
+ PrintFatalError(GPU->getLoc(),
+ "GPU '" + GPU->getValueAsString("Name") +
+ "' gets conflicting 'LDSAllocationGranularity' "
+ "values from '" +
+ Found->getValueAsString("Name") + "' and '" +
+ F->getValueAsString("Name") + "'");
+ }
+ Found = F;
+ Value = V;
+ }
+ return Value;
+}
+
// Make sure a "gfxN-generic" processor doesn't expose a frontend-visible
// feature missing from any covered processor.
//
+// LDS allocation granularity is an exception to exact matching. A generic
+// target conservatively uses the largest granularity of the GPUs it covers.
+//
// FIXME: The check should cover all SubtargetFeatures, not just the
// frontend-visible ones. It is limited to those because a generic legitimately
-// carries some features a covered GPU lacks (bug/hazard workarounds and
-// worst-case-valued features); those cases need to be marked to opt out of the
-// check, plus min-value handling for numeric features.
+// carries some boolean features a covered GPU lacks (bug and hazard
+// workarounds); those cases need to be marked to opt out of the check.
static void
validateGenericFeatures(const Record *GPU,
const DenseMap<const Record *, unsigned> &FeatureIdx) {
@@ -498,14 +528,29 @@ validateGenericFeatures(const Record *GPU,
SetVector<const Record *> MemberFeatures =
collectVisibleFeatures(Member, FeatureIdx);
for (const Record *F : GenericFeatures) {
- if (!MemberFeatures.contains(F)) {
+ if (MemberFeatures.contains(F))
+ continue;
+
+ StringRef FieldName = F->getValueAsString("FieldName");
+ if (FieldName == "LDSAllocationGranularity") {
+ int64_t GenericValue = getLDSAllocGranularity(GPU);
+ int64_t MemberValue = getLDSAllocGranularity(Member);
+ if (GenericValue >= MemberValue)
+ continue;
+
PrintFatalError(GPU->getLoc(),
"generic target '" + GPU->getValueAsString("Name") +
"' exposes feature '" +
- F->getValueAsString("Name") +
- "' not supported by covered GPU '" +
+ F->getValueAsString("Name") + "' below the '" +
+ FieldName + "' of covered GPU '" +
Member->getValueAsString("Name") + "'");
}
+
+ PrintFatalError(GPU->getLoc(),
+ "generic target '" + GPU->getValueAsString("Name") +
+ "' exposes feature '" + F->getValueAsString("Name") +
+ "' not supported by covered GPU '" +
+ Member->getValueAsString("Name") + "'");
}
}
}
More information about the llvm-commits
mailing list