[llvm-branch-commits] [llvm] AMDGPU: TableGen subarch to major subarch table (PR #212605)
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Jul 29 11:59:34 PDT 2026
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/212605
>From 6c2f22c2d358f7237a47c031f1f420ab2c30633c Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 27 Jul 2026 07:54:09 +0200
Subject: [PATCH] AMDGPU: TableGen subarch to major subarch table
Replace the hand-written AMDGPUMajorFamilies array with a
generated lookup table. Adds a special case for the major
arches missing a concrete generic target definition (we probably
should just define those to avoid this).
Co-authored-by: Claude (Claude-Opus-4.8)
---
llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td | 8 ++
llvm/lib/Target/AMDGPU/GCNProcessors.td | 6 +
llvm/lib/TargetParser/AMDGPUTargetParser.cpp | 74 ++++--------
.../TableGen/Basic/AMDGPUTargetDefEmitter.cpp | 106 ++++++++++++++----
4 files changed, 119 insertions(+), 75 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td b/llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td
index e53f65cd5f60d..e6ea319017436 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td
@@ -59,3 +59,11 @@ class R600ProcessorModel<string n, ProcessorItineraries pi,
class AMDGPUProcessorModel<string n, SchedMachineModel m,
list<SubtargetFeature> f, list<int> isa>
: ProcessorModel<n, m, f>, AMDGPUGPUInfo<isa>;
+
+// A major-subarch family that has no "gfxN-generic" target of its own
+// (gfx6, gfx7, gfx8). \p major is the bare subarch suffix (e.g. "6");
+// \p members are the GPUs mapped to Triple::AMDGPUSubArch<major>
+class AMDGPUFamily<string major, list<Processor> members> {
+ string MajorSubArch = major;
+ list<Processor> Members = members;
+}
diff --git a/llvm/lib/Target/AMDGPU/GCNProcessors.td b/llvm/lib/Target/AMDGPU/GCNProcessors.td
index d6d8a8a4e070e..47dc1f182c7b4 100644
--- a/llvm/lib/Target/AMDGPU/GCNProcessors.td
+++ b/llvm/lib/Target/AMDGPU/GCNProcessors.td
@@ -398,3 +398,9 @@ def GFX13_GENERIC : AMDGPUProcessorModel<"gfx13-generic", GFX12SpeedModel,
let ArchFeatures = ArchFeaturesW32Wgp;
let CoveredGPUs = [GFX1310];
}
+
+// The gfx6/gfx7/gfx8 families have no "gfxN-generic" target, so their major
+// subarch (AMDGPUSubArch6/7/8) is declared here for getMajorSubArch.
+def : AMDGPUFamily<"6", [GFX600, GFX601, GFX602]>;
+def : AMDGPUFamily<"7", [GFX700, GFX701, GFX702, GFX703, GFX704, GFX705]>;
+def : AMDGPUFamily<"8", [GFX801, GFX802, GFX803, GFX805]>;
diff --git a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
index fa95e4005bb22..a555c94ee6c91 100644
--- a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
+++ b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
@@ -24,6 +24,9 @@ using namespace llvm;
using namespace AMDGPU;
namespace {
+constexpr unsigned NumAMDGPUSubArches =
+ Triple::LastAMDGPUSubArch - Triple::FirstAMDGPUSubArch + 1;
+
// Per-GPU data for the AMDGCN GPUKinds, from the generated table below.
struct GPUInfo {
StringRef Name;
@@ -34,6 +37,7 @@ struct GPUInfo {
};
#define GET_AMDGPU_GPU_TABLE
+#define GET_AMDGPU_MAJOR_SUBARCH
#include "llvm/TargetParser/AMDGPUTargetParserDef.inc"
// Look up the GPUInfo row for an AMDGCN GPUKind, or nullptr for GK_NONE / a
@@ -49,8 +53,6 @@ const GPUInfo *getAMDGPUInfo(GPUKind AK) {
// Reverse map: SubArch -> GPUKind, indexed by (SubArch - FirstAMDGPUSubArch).
// Subarches with no GPU (incl. the NoSubArch pseudo targets) map to GK_NONE.
-constexpr unsigned NumAMDGPUSubArches =
- Triple::LastAMDGPUSubArch - Triple::FirstAMDGPUSubArch + 1;
constexpr std::array<GPUKind, NumAMDGPUSubArches> AMDGPUSubArchToGPUKind = [] {
std::array<GPUKind, NumAMDGPUSubArches> Map{};
@@ -63,6 +65,21 @@ constexpr std::array<GPUKind, NumAMDGPUSubArches> AMDGPUSubArchToGPUKind = [] {
}
return Map;
}();
+
+/// SubArch -> major-family, indexed by (SubArch - FirstAMDGPUSubArch).
+constexpr std::array<Triple::SubArchType, NumAMDGPUSubArches>
+ AMDGPUMajorFamilies = [] {
+ std::array<Triple::SubArchType, NumAMDGPUSubArches> Map{};
+
+ for (unsigned I = 0; I < NumAMDGPUSubArches; ++I) {
+ Map[I] =
+ static_cast<Triple::SubArchType>(Triple::FirstAMDGPUSubArch + I);
+ }
+
+ for (const AMDGPUMajorSubArchEntry &Entry : AMDGPUMajorSubArch)
+ Map[Entry.SubArch - Triple::FirstAMDGPUSubArch] = Entry.Major;
+ return Map;
+ }();
} // namespace
StringRef llvm::AMDGPU::getArchFamilyNameAMDGCN(GPUKind AK) {
@@ -83,59 +100,6 @@ llvm::AMDGPU::getGPUKindFromSubArch(Triple::SubArchType SubArch) {
return AMDGPUSubArchToGPUKind[SubArch - Triple::FirstAMDGPUSubArch];
}
-static const Triple::SubArchType
- AMDGPUMajorFamilies[Triple::LastAMDGPUSubArch - Triple::FirstAMDGPUSubArch +
- 1] = {
- Triple::AMDGPUSubArch6, Triple::AMDGPUSubArch6,
- Triple::AMDGPUSubArch6, Triple::AMDGPUSubArch6,
-
- Triple::AMDGPUSubArch7, Triple::AMDGPUSubArch7,
- Triple::AMDGPUSubArch7, Triple::AMDGPUSubArch7,
- Triple::AMDGPUSubArch7, Triple::AMDGPUSubArch7,
- Triple::AMDGPUSubArch7,
-
- Triple::AMDGPUSubArch8, Triple::AMDGPUSubArch8,
- Triple::AMDGPUSubArch8, Triple::AMDGPUSubArch8,
- Triple::AMDGPUSubArch8,
-
- Triple::AMDGPUSubArch810,
-
- Triple::AMDGPUSubArch9, Triple::AMDGPUSubArch9,
- Triple::AMDGPUSubArch9, Triple::AMDGPUSubArch9,
- Triple::AMDGPUSubArch9, Triple::AMDGPUSubArch9,
- Triple::AMDGPUSubArch9,
-
- Triple::AMDGPUSubArch908, Triple::AMDGPUSubArch90A,
-
- Triple::AMDGPUSubArch9_4, Triple::AMDGPUSubArch9_4,
- Triple::AMDGPUSubArch9_4,
-
- Triple::AMDGPUSubArch10_1, Triple::AMDGPUSubArch10_1,
- Triple::AMDGPUSubArch10_1, Triple::AMDGPUSubArch10_1,
- Triple::AMDGPUSubArch10_1,
-
- Triple::AMDGPUSubArch10_3, Triple::AMDGPUSubArch10_3,
- Triple::AMDGPUSubArch10_3, Triple::AMDGPUSubArch10_3,
- Triple::AMDGPUSubArch10_3, Triple::AMDGPUSubArch10_3,
- Triple::AMDGPUSubArch10_3, Triple::AMDGPUSubArch10_3,
-
- Triple::AMDGPUSubArch11, Triple::AMDGPUSubArch11,
- Triple::AMDGPUSubArch11, Triple::AMDGPUSubArch11,
- Triple::AMDGPUSubArch11, Triple::AMDGPUSubArch11,
- Triple::AMDGPUSubArch11, Triple::AMDGPUSubArch11,
- Triple::AMDGPUSubArch11, Triple::AMDGPUSubArch11,
-
- Triple::AMDGPUSubArch11_7, Triple::AMDGPUSubArch11_7,
- Triple::AMDGPUSubArch11_7, Triple::AMDGPUSubArch11_7,
-
- Triple::AMDGPUSubArch12, Triple::AMDGPUSubArch12,
- Triple::AMDGPUSubArch12,
-
- Triple::AMDGPUSubArch12_5, Triple::AMDGPUSubArch12_5,
- Triple::AMDGPUSubArch12_5,
-
- Triple::AMDGPUSubArch13, Triple::AMDGPUSubArch13};
-
Triple::SubArchType AMDGPU::getMajorSubArch(Triple::SubArchType X) {
if (X < Triple::FirstAMDGPUSubArch || X > Triple::LastAMDGPUSubArch)
return Triple::NoSubArch;
diff --git a/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp b/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
index a4468de6d0968..ece842771f32c 100644
--- a/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
@@ -18,6 +18,8 @@
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
+#include <string>
+#include <utility>
#include <vector>
using namespace llvm;
@@ -29,14 +31,11 @@ static void emitGPUKindEnum(raw_ostream &OS, StringRef Name) {
OS << ((C == '-') ? '_' : toUpper(C));
}
-/// Derive the Triple::SubArchType for a canonical GPU record.
-static void emitSubArch(raw_ostream &OS, const Record *Rec) {
- if (Rec->getValueAsBit("IsPseudoTarget")) {
- OS << "Triple::NoSubArch";
- return;
- }
-
- StringRef Suffix = Rec->getValueAsString("Name");
+// Derive the Triple::SubArchType from a "gfx..." GPU name, e.g. "gfx90a" ->
+// Triple::AMDGPUSubArch90A, "gfx9-generic" -> Triple::AMDGPUSubArch9 (the
+// family major). The name must be a real hardware GPU (not a pseudo target).
+static void emitSubArchForName(raw_ostream &OS, StringRef Name) {
+ StringRef Suffix = Name;
Suffix.consume_front("gfx");
Suffix.consume_back("-generic");
@@ -45,15 +44,33 @@ static void emitSubArch(raw_ostream &OS, const Record *Rec) {
OS << ((C == '-') ? '_' : toUpper(C));
}
-/// The gfx family for a canonical GPU record: the "-generic" family prefix
-/// (e.g. "gfx9-4-generic" -> "gfx9"), or the name with its last two chars
-/// dropped for a concrete GPU (e.g. "gfx90a" -> "gfx9", "gfx1030" ->
-/// "gfx10"). Empty for a pseudo target.
+// Derive the Triple::SubArchType for a canonical GPU record. A pseudo target
+// represents no hardware and maps to Triple::NoSubArch; otherwise the subarch
+// is derived from the name.
+static void emitSubArch(raw_ostream &OS, const Record *Rec) {
+ if (Rec->getValueAsBit("IsPseudoTarget")) {
+ OS << "Triple::NoSubArch";
+ return;
+ }
+ emitSubArchForName(OS, Rec->getValueAsString("Name"));
+}
+
+// A canonical GPU record is a "gfxN-generic" family target if it covers a set
+// of concrete GPUs (via CoveredGPUs) rather than being a single piece of
+// hardware.
+static bool isGenericTarget(const Record *Rec) {
+ return !Rec->getValueAsListOfDefs("CoveredGPUs").empty();
+}
+
+// The gfx family for a canonical GPU record: the "-generic" family prefix (e.g.
+// "gfx9-4-generic" -> "gfx9"), or the name with its last two chars dropped for
+// a concrete GPU (e.g. "gfx90a" -> "gfx9", "gfx1030" -> "gfx10"). Empty for a
+// pseudo target.
static StringRef getArchFamily(const Record *Rec) {
if (Rec->getValueAsBit("IsPseudoTarget"))
return "";
StringRef Name = Rec->getValueAsString("Name");
- if (Name.ends_with("-generic"))
+ if (isGenericTarget(Rec))
return Name.take_front(Name.find('-'));
return Name.drop_back(2);
}
@@ -74,13 +91,6 @@ static void emitIsaVersion(raw_ostream &OS, const Record *Rec, char Open,
OS << Open << V[0] << ", " << V[1] << ", " << V[2] << Close;
}
-// A canonical GPU record is a "gfxN-generic" family target if it covers a set
-// of concrete GPUs (via CoveredGPUs) rather than being a single piece of
-// hardware.
-static bool isGenericTarget(const Record *Rec) {
- return !Rec->getValueAsListOfDefs("CoveredGPUs").empty();
-}
-
// A canonical GPU or a ProcessorAlias.
namespace {
struct GPUEntry {
@@ -301,6 +311,61 @@ static void emitAMDGPUTable(raw_ostream &OS, const RecordKeeper &RK) {
"#endif // GET_AMDGPU_GPU_TABLE\n\n";
}
+// Emit the subarch -> major-family-subarch overrides; a subarch not listed here
+// is its own major subarch. Each entry maps a member GPU's own subarch to its
+// family's major subarch, from one of two sources: a "gfxN-generic" target,
+// whose subarch is the major for every GPU it lists in CoveredGPUs, or an
+// AMDGPUFamily's MajorSubArch for the gfx6/gfx7/gfx8 families that have no
+// generic target.
+static void emitAMDGPUMajorSubArch(raw_ostream &OS, const RecordKeeper &RK) {
+ ArrayRef<const Record *> GPUs =
+ RK.getAllDerivedDefinitionsIfDefined("AMDGPUGPUInfo");
+ ArrayRef<const Record *> Families =
+ RK.getAllDerivedDefinitionsIfDefined("AMDGPUFamily");
+
+ // The overrides come from generic targets' CoveredGPUs and AMDGPUFamily
+ // members. std::array makes the R600 case (zero entries) well-formed.
+ size_t NumEntries = 0;
+ for (const Record *G : GPUs)
+ NumEntries += G->getValueAsListOfDefs("CoveredGPUs").size();
+ for (const Record *F : Families)
+ NumEntries += F->getValueAsListOfDefs("Members").size();
+
+ OS << "#ifdef GET_AMDGPU_MAJOR_SUBARCH\n"
+ "#undef GET_AMDGPU_MAJOR_SUBARCH\n"
+ "struct AMDGPUMajorSubArchEntry {\n"
+ " Triple::SubArchType SubArch;\n"
+ " Triple::SubArchType Major;\n"
+ "};\n"
+ "static constexpr std::array<AMDGPUMajorSubArchEntry, "
+ << NumEntries << "> AMDGPUMajorSubArch = {{\n";
+
+ // A "gfxN-generic" target's subarch is the major for every GPU it covers.
+ for (const Record *G : GPUs) {
+ for (const Record *Member : G->getValueAsListOfDefs("CoveredGPUs")) {
+ OS << " {";
+ emitSubArchForName(OS, Member->getValueAsString("Name"));
+ OS << ", ";
+ emitSubArch(OS, G);
+ OS << "},\n";
+ }
+ }
+
+ // The gfx6/gfx7/gfx8 families have no generic target, so their major comes
+ // from AMDGPUFamily::MajorSubArch.
+ for (const Record *F : Families) {
+ StringRef Major = F->getValueAsString("MajorSubArch");
+ for (const Record *Member : F->getValueAsListOfDefs("Members")) {
+ OS << " {";
+ emitSubArchForName(OS, Member->getValueAsString("Name"));
+ OS << ", Triple::AMDGPUSubArch" << Major << "},\n";
+ }
+ }
+
+ OS << "}};\n"
+ "#endif // GET_AMDGPU_MAJOR_SUBARCH\n\n";
+}
+
static void emitAMDGPUTargetDef(const RecordKeeper &RK, raw_ostream &OS) {
OS << "// Autogenerated by AMDGPUTargetDefEmitter.cpp\n\n";
// R600 processors are Processor records; AMDGPU processors are
@@ -310,6 +375,7 @@ static void emitAMDGPUTargetDef(const RecordKeeper &RK, raw_ostream &OS) {
emitR600(OS, RK);
emitAMDGPU(OS, RK);
emitAMDGPUTable(OS, RK);
+ emitAMDGPUMajorSubArch(OS, RK);
}
static TableGen::Emitter::Opt X("gen-amdgpu-target-def", emitAMDGPUTargetDef,
More information about the llvm-branch-commits
mailing list