[llvm] AMDGPU: Add SubArchSpelling override to the TargetParser TableGen (PR #218500)

via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 24 12:52:01 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-amdgpu

Author: Matt Arsenault (arsenm)

<details>
<summary>Changes</summary>

Add an optional SubArchSpelling field for targets where the subarch name isn't
trivially derivable from it's gfxNMK name.

Co-Authored-By: Claude <noreply@<!-- -->anthropic.com>

---
Full diff: https://github.com/llvm/llvm-project/pull/218500.diff


5 Files Affected:

- (modified) llvm/include/llvm/TargetParser/AMDGPUTargetParser.h (+4) 
- (modified) llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td (+4) 
- (modified) llvm/lib/TargetParser/AMDGPUTargetParser.cpp (+6) 
- (added) llvm/test/TableGen/AMDGPUTargetDefSubArchSpelling.td (+44) 
- (modified) llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp (+64-23) 


``````````diff
diff --git a/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h b/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
index f8e283db55fec..5b4093b2536a5 100644
--- a/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
+++ b/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
@@ -108,6 +108,10 @@ enum FeatureError : uint32_t {
 };
 
 LLVM_ABI StringRef getArchFamilyNameAMDGCN(GPUKind AK);
+
+/// The canonical GPU name for a variant name.
+LLVM_ABI StringRef getBaseArchNameAMDGCN(GPUKind AK);
+
 LLVM_ABI Triple::SubArchType getSubArch(GPUKind AK);
 LLVM_ABI Triple::SubArchType getMajorSubArch(Triple::SubArchType SubArch);
 
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td b/llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td
index e6ea319017436..7e4b7ee75bdaf 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td
@@ -47,6 +47,10 @@ class AMDGPUGPUInfo<list<int> isa = []> {
   // A pseudo target ("generic"/"generic-hsa") that represents no
   // hardware.
   bit IsPseudoTarget = false;
+
+  // An explicit triple subarch spelling (e.g. "12.50"). If unset,
+  // this will be guessed from the device name.
+  string SubArchSpelling;
 }
 
 // An R600 processor that is also a canonical TargetParser GPU.
diff --git a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
index 98affe3e0d7bd..b3cd0a9c26942 100644
--- a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
+++ b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
@@ -41,6 +41,7 @@ struct GPUInfo {
   AMDGPUFeatureBitset Features;
   IsaVersion Version;
   StringTable::Offset FamilyName;
+  StringTable::Offset BaseName; // The canonical device name for a variant.
 };
 
 // Per-GPU data for the R600 GPUKinds.
@@ -168,6 +169,11 @@ Triple::SubArchType llvm::AMDGPU::getSubArch(GPUKind AK) {
   return Info ? Info->SubArch : Triple::SubArchType::NoSubArch;
 }
 
+StringRef llvm::AMDGPU::getBaseArchNameAMDGCN(GPUKind AK) {
+  const GPUInfo *Info = getAMDGPUInfo(AK);
+  return Info ? AMDGPUNameStrTab[Info->BaseName] : "";
+}
+
 AMDGPU::GPUKind
 llvm::AMDGPU::getGPUKindFromSubArch(Triple::SubArchType SubArch) {
   if (SubArch < Triple::FirstAMDGPUSubArch ||
diff --git a/llvm/test/TableGen/AMDGPUTargetDefSubArchSpelling.td b/llvm/test/TableGen/AMDGPUTargetDefSubArchSpelling.td
new file mode 100644
index 0000000000000..e0c4b82ba0469
--- /dev/null
+++ b/llvm/test/TableGen/AMDGPUTargetDefSubArchSpelling.td
@@ -0,0 +1,44 @@
+// RUN: llvm-tblgen -gen-amdgpu-target-def -I %p/../../include %s 2>&1 | FileCheck %s
+
+// Verify the -gen-amdgpu-target-def backend's handling of SubArchSpelling.
+
+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;
+  string SubArchSpelling;
+}
+
+def GFX888 : ProcessorModel<"gfx888", NoSchedModel, []>, AMDGPUGPUInfo<[8, 8, 8]>;
+
+// A variant CPU: its subarch, triple name, family, and base name come from the
+// spelling / ISA version, not its own name.
+def GFX888_AMAZING : ProcessorModel<"gfx888-amazing", NoSchedModel, []>,
+    AMDGPUGPUInfo<[8, 8, 8]> {
+  let SubArchSpelling = "8.88a";
+}
+
+// The variant contributes a distinct GPUKind.
+// CHECK: GK_GFX888
+// CHECK: GK_GFX888_AMAZING
+
+// The variant is its own major subarch, so it produces no override entry.
+// CHECK: AMDGPUMajorSubArchEntry, 0>{{ }}AMDGPUMajorSubArch
+
+// The name pool holds the variant's name, its gfx8 family, and its base name.
+// CHECK: "gfx888\0"
+// CHECK: "gfx8\0"
+// CHECK: "gfx888-amazing\0"
+// CHECK: "amdgpu8.88a\0"
+
+// The GPU table: the base GPU has no base name (offset 0); the variant uses
+// AMDGPUSubArch8_88A and records "gfx888" as its base name.
+// CHECK: {[[#]], Triple::AMDGPUSubArch888, {{.*}}, {8, 8, 8}, [[FAM:[0-9]+]], 0},
+// CHECK: {[[#]], Triple::AMDGPUSubArch8_88A, {{.*}}, {8, 8, 8}, [[FAM]], [[#]]},
+
+// The subarch-name table maps the variant's own subarch to its triple name.
+// CHECK: {Triple::AMDGPUSubArch8_88A, [[#]], [[#]]},
diff --git a/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp b/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
index d077178f98526..65d6add20a01a 100644
--- a/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
@@ -64,14 +64,34 @@ static void emitSubArchForName(raw_ostream &OS, StringRef Name) {
   emitSubArchSuffix(OS, Name);
 }
 
+// The explicit subarch spelling for a GPU whose subarch is not derivable from
+// its name, or empty. Optional so test stubs may omit it.
+static std::optional<StringRef> getSubArchSpelling(const Record *Rec) {
+  return Rec->getValueAsOptionalString("SubArchSpelling");
+}
+
+// Emit a subarch enumerator suffix for a spelling, converting '.' to '_' and
+// upcasing, e.g. "4.67q" -> "4_67Q".
+static void emitSpellingSuffix(raw_ostream &OS, StringRef Spelling) {
+  for (char C : Spelling)
+    OS << static_cast<char>((C == '.') ? '_' : toUpper(C));
+}
+
 // 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.
+// maps to Triple::NoSubArch; an explicit SubArchSpelling maps to that (e.g.
+// "4.67q" -> AMDGPUSubArch4_67Q); otherwise it is derived from the name.
 static void emitSubArch(raw_ostream &OS, const Record *Rec) {
   if (Rec->getValueAsBit("IsPseudoTarget")) {
     OS << "Triple::NoSubArch";
     return;
   }
+
+  if (std::optional<StringRef> Spelling = getSubArchSpelling(Rec)) {
+    OS << "Triple::AMDGPUSubArch";
+    emitSpellingSuffix(OS, *Spelling);
+    return;
+  }
+
   emitSubArchForName(OS, Rec->getValueAsString("Name"));
 }
 
@@ -82,17 +102,21 @@ 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) {
+// Emit the gfx family for a canonical GPU record: "gfx" + the ISA major version
+// (e.g. "gfx90a"/[9,0,10] -> "gfx9", "gfx1250"/[12,5,0] -> "gfx12").
+// Nothing for a pseudo target.
+static void emitArchFamily(raw_ostream &OS, const Record *Rec) {
   if (Rec->getValueAsBit("IsPseudoTarget"))
-    return "";
-  StringRef Name = Rec->getValueAsString("Name");
-  if (isGenericTarget(Rec))
-    return Name.take_front(Name.find('-'));
-  return Name.drop_back(2);
+    return;
+  OS << "gfx" << Rec->getValueAsListOfInts("IsaVersion")[0];
+}
+
+// Emit the canonical GPU name for a variant (empty for a non-variant GPU).
+static void emitBaseName(raw_ostream &OS, const Record *Rec) {
+  if (!getSubArchSpelling(Rec))
+    return;
+  std::vector<int64_t> V = Rec->getValueAsListOfInts("IsaVersion");
+  OS << "gfx" << V[0] << V[1] << hexdigit(V[2], /*LowerCase=*/true);
 }
 
 // Emit the ISA version tuple as "major, minor, stepping" wrapped in \p Open and
@@ -534,7 +558,14 @@ emitAMDGPUTable(raw_ostream &OS, const RecordKeeper &RK,
     emitFeatureBitset(OS, R, FeatureIdx);
     OS << ", ";
     emitIsaVersion(OS, R, '{', '}');
-    OS << ", " << Names.GetOrAddStringOffset(getArchFamily(R)) << "},\n";
+    SmallString<16> Family;
+    raw_svector_ostream FamilyOS(Family);
+    emitArchFamily(FamilyOS, R);
+    OS << ", " << Names.GetOrAddStringOffset(Family) << ", ";
+    SmallString<16> BaseName;
+    raw_svector_ostream BaseNameOS(BaseName);
+    emitBaseName(BaseNameOS, R);
+    OS << Names.GetOrAddStringOffset(BaseName) << "},\n";
   }
   OS << "};\n"
         "#endif // GET_AMDGPU_GPU_TABLE\n\n";
@@ -612,19 +643,29 @@ static void emitAMDGPUSubArchNames(raw_ostream &OS, const RecordKeeper &RK,
       continue;
     SubArchEntry Entry;
     Entry.GPUName = E.Rec->getValueAsString("Name");
-    {
-      raw_svector_ostream SubArchOS(Entry.Suffix);
-      emitSubArchSuffix(SubArchOS, Entry.GPUName);
-    }
 
-    // A "gfxN-generic" target maps to the major-family subarch, so it takes the
-    // family triple name; a concrete GPU derives it from the ISA version.
     SmallString<16> TripleName;
     raw_svector_ostream TripleOS(TripleName);
-    if (isGenericTarget(E.Rec))
-      emitFamilySubArchTripleName(TripleOS, Entry.Suffix);
-    else
-      emitConcreteSubArchTripleName(TripleOS, E.Rec);
+
+    // An explicit subarch spelling supplies the enumerator suffix and triple
+    // name, rather than the name/ISA version.
+    if (std::optional<StringRef> Spelling = getSubArchSpelling(E.Rec)) {
+      raw_svector_ostream SubArchOS(Entry.Suffix);
+      emitSpellingSuffix(SubArchOS, *Spelling);
+      TripleOS << "amdgpu" << *Spelling;
+    } else {
+      {
+        raw_svector_ostream SubArchOS(Entry.Suffix);
+        emitSubArchSuffix(SubArchOS, Entry.GPUName);
+      }
+
+      // A "gfxN-generic" target maps to the major-family subarch, so it takes
+      // the family triple name; a concrete GPU derives it from the ISA version.
+      if (isGenericTarget(E.Rec))
+        emitFamilySubArchTripleName(TripleOS, Entry.Suffix);
+      else
+        emitConcreteSubArchTripleName(TripleOS, E.Rec);
+    }
     Entry.TripleNameOffset = Names.GetOrAddStringOffset(TripleName);
 
     Entries.push_back(std::move(Entry));

``````````

</details>


https://github.com/llvm/llvm-project/pull/218500


More information about the llvm-commits mailing list