[clang] [llvm] AMDGPU: Eliminate old macro driven processor name parsing (PR #212608)
Matt Arsenault via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 29 23:51:56 PDT 2026
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/212608
>From 88554dceb0e1df633f2af1e7395c93211faef821 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 27 Jul 2026 22:35:25 +0200
Subject: [PATCH] AMDGPU: Eliminate old macro driven processor name parsing
Previously the generated inc file had a series of macros for use
with StringSwitch; now just directly scan the generated name table.
Co-authored-by: Claude (Claude-Opus-4.8)
---
.../Misc/target-invalid-cpu-note/amdgcn.c | 36 +--
.../test/Misc/target-invalid-cpu-note/r600.c | 20 +-
.../llvm/TargetParser/AMDGPUTargetParser.h | 4 +-
llvm/lib/TargetParser/AMDGPUTargetParser.cpp | 115 +++++---
.../TableGen/Basic/AMDGPUTargetDefEmitter.cpp | 256 +++++++++++-------
5 files changed, 254 insertions(+), 177 deletions(-)
diff --git a/clang/test/Misc/target-invalid-cpu-note/amdgcn.c b/clang/test/Misc/target-invalid-cpu-note/amdgcn.c
index c898accc6db5f..3e641a3944397 100644
--- a/clang/test/Misc/target-invalid-cpu-note/amdgcn.c
+++ b/clang/test/Misc/target-invalid-cpu-note/amdgcn.c
@@ -6,37 +6,19 @@
// CHECK: error: unknown target CPU 'not-a-cpu'
// CHECK-NEXT: note: valid target CPU values are:
// CHECK-SAME: {{^}} gfx600
-// CHECK-SAME: {{^}}, tahiti
// CHECK-SAME: {{^}}, gfx601
-// CHECK-SAME: {{^}}, pitcairn
-// CHECK-SAME: {{^}}, verde
// CHECK-SAME: {{^}}, gfx602
-// CHECK-SAME: {{^}}, hainan
-// CHECK-SAME: {{^}}, oland
// CHECK-SAME: {{^}}, gfx700
-// CHECK-SAME: {{^}}, kaveri
// CHECK-SAME: {{^}}, gfx701
-// CHECK-SAME: {{^}}, hawaii
// CHECK-SAME: {{^}}, gfx702
// CHECK-SAME: {{^}}, gfx703
-// CHECK-SAME: {{^}}, kabini
-// CHECK-SAME: {{^}}, mullins
// CHECK-SAME: {{^}}, gfx704
-// CHECK-SAME: {{^}}, bonaire
// CHECK-SAME: {{^}}, gfx705
// CHECK-SAME: {{^}}, gfx801
-// CHECK-SAME: {{^}}, carrizo
// CHECK-SAME: {{^}}, gfx802
-// CHECK-SAME: {{^}}, iceland
-// CHECK-SAME: {{^}}, tonga
// CHECK-SAME: {{^}}, gfx803
-// CHECK-SAME: {{^}}, fiji
-// CHECK-SAME: {{^}}, polaris10
-// CHECK-SAME: {{^}}, polaris11
// CHECK-SAME: {{^}}, gfx805
-// CHECK-SAME: {{^}}, tongapro
// CHECK-SAME: {{^}}, gfx810
-// CHECK-SAME: {{^}}, stoney
// CHECK-SAME: {{^}}, gfx900
// CHECK-SAME: {{^}}, gfx902
// CHECK-SAME: {{^}}, gfx904
@@ -84,6 +66,24 @@
// CHECK-SAME: {{^}}, gfx12-generic
// CHECK-SAME: {{^}}, gfx12-5-generic
// CHECK-SAME: {{^}}, gfx13-generic
+// CHECK-SAME: {{^}}, tahiti
+// CHECK-SAME: {{^}}, pitcairn
+// CHECK-SAME: {{^}}, verde
+// CHECK-SAME: {{^}}, hainan
+// CHECK-SAME: {{^}}, oland
+// CHECK-SAME: {{^}}, kaveri
+// CHECK-SAME: {{^}}, hawaii
+// CHECK-SAME: {{^}}, kabini
+// CHECK-SAME: {{^}}, mullins
+// CHECK-SAME: {{^}}, bonaire
+// CHECK-SAME: {{^}}, carrizo
+// CHECK-SAME: {{^}}, iceland
+// CHECK-SAME: {{^}}, tonga
+// CHECK-SAME: {{^}}, fiji
+// CHECK-SAME: {{^}}, polaris10
+// CHECK-SAME: {{^}}, polaris11
+// CHECK-SAME: {{^}}, tongapro
+// CHECK-SAME: {{^}}, stoney
// CHECK-SAME: {{$}}
// The pseudo targets "generic"/"generic-hsa" may not be used.
diff --git a/clang/test/Misc/target-invalid-cpu-note/r600.c b/clang/test/Misc/target-invalid-cpu-note/r600.c
index 1481d41745ea9..bc0d27e832442 100644
--- a/clang/test/Misc/target-invalid-cpu-note/r600.c
+++ b/clang/test/Misc/target-invalid-cpu-note/r600.c
@@ -6,29 +6,29 @@
// CHECK: error: unknown target CPU 'not-a-cpu'
// CHECK-NEXT: note: valid target CPU values are:
// CHECK-SAME: {{^}} r600
-// CHECK-SAME: {{^}}, rv630
-// CHECK-SAME: {{^}}, rv635
// CHECK-SAME: {{^}}, r630
-// CHECK-SAME: {{^}}, rs780
// CHECK-SAME: {{^}}, rs880
-// CHECK-SAME: {{^}}, rv610
-// CHECK-SAME: {{^}}, rv620
// CHECK-SAME: {{^}}, rv670
// CHECK-SAME: {{^}}, rv710
// CHECK-SAME: {{^}}, rv730
-// CHECK-SAME: {{^}}, rv740
// CHECK-SAME: {{^}}, rv770
// CHECK-SAME: {{^}}, cedar
-// CHECK-SAME: {{^}}, palm
// CHECK-SAME: {{^}}, cypress
-// CHECK-SAME: {{^}}, hemlock
// CHECK-SAME: {{^}}, juniper
// CHECK-SAME: {{^}}, redwood
// CHECK-SAME: {{^}}, sumo
-// CHECK-SAME: {{^}}, sumo2
// CHECK-SAME: {{^}}, barts
// CHECK-SAME: {{^}}, caicos
-// CHECK-SAME: {{^}}, aruba
// CHECK-SAME: {{^}}, cayman
// CHECK-SAME: {{^}}, turks
+// CHECK-SAME: {{^}}, rv630
+// CHECK-SAME: {{^}}, rv635
+// CHECK-SAME: {{^}}, rs780
+// CHECK-SAME: {{^}}, rv610
+// CHECK-SAME: {{^}}, rv620
+// CHECK-SAME: {{^}}, rv740
+// CHECK-SAME: {{^}}, palm
+// CHECK-SAME: {{^}}, hemlock
+// CHECK-SAME: {{^}}, sumo2
+// CHECK-SAME: {{^}}, aruba
// CHECK-SAME: {{$}}
diff --git a/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h b/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
index c83528b76c7f9..8f8decdb373ce 100644
--- a/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
+++ b/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
@@ -35,10 +35,10 @@ enum GPUKind : uint32_t {
// Not specified processor.
GK_NONE = 0,
-#define R600_GPU(NAME, ENUM, FEATURES) ENUM,
+#define GET_R600_GPU_ENUM
#include "llvm/TargetParser/R600TargetParserDef.inc"
-#define AMDGPU_GPU(NAME, ENUM) ENUM,
+#define GET_AMDGPU_GPU_ENUM
#include "llvm/TargetParser/AMDGPUTargetParserDef.inc"
};
diff --git a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
index 72b474cff7cc1..f866a092d6697 100644
--- a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
+++ b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
@@ -13,10 +13,8 @@
#include "llvm/TargetParser/AMDGPUTargetParser.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/StringTable.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
#include <array>
@@ -28,6 +26,12 @@ namespace {
constexpr unsigned NumAMDGPUSubArches =
Triple::LastAMDGPUSubArch - Triple::FirstAMDGPUSubArch + 1;
+// A legacy GPU name (e.g. "tahiti") mapped to the GPUKind it aliases.
+struct GPUNameAlias {
+ StringTable::Offset AltName;
+ GPUKind Kind;
+};
+
// Per-GPU data for the AMDGCN GPUKinds, from the generated table below.
struct GPUInfo {
StringTable::Offset Name;
@@ -37,15 +41,28 @@ struct GPUInfo {
StringTable::Offset FamilyName;
};
+// Per-GPU data for the R600 GPUKinds.
+struct R600Info {
+ StringTable::Offset Name;
+ R600FeatureKind ArchFeatures;
+};
+
#define GET_AMDGPU_NAME_TABLE
#define GET_AMDGPU_GPU_TABLE
+#define GET_AMDGPU_GPU_ALIAS_TABLE
#define GET_AMDGPU_MAJOR_SUBARCH
#define GET_AMDGPU_SUBARCH_NAME
#include "llvm/TargetParser/AMDGPUTargetParserDef.inc"
-// The string table shared by every generated table that stores GPU-name-derived
-// strings as offsets.
+#define GET_R600_NAME_TABLE
+#define GET_R600_GPU_TABLE
+#define GET_R600_GPU_ALIAS_TABLE
+#include "llvm/TargetParser/R600TargetParserDef.inc"
+
+// The string tables holding GPU-name-derived strings as offsets. R600 and
+// AMDGPU come from separate generated headers, each with its own pool.
constexpr StringTable AMDGPUNameStrTab = AMDGPUNameTable;
+constexpr StringTable R600NameStrTab = R600NameTable;
// Look up the GPUInfo row for an AMDGCN GPUKind, or nullptr for GK_NONE / a
// non-AMDGCN (R600) kind.
@@ -58,6 +75,34 @@ const GPUInfo *getAMDGPUInfo(GPUKind AK) {
return &AMDGPUGPUTable[Idx];
}
+// Look up the R600Info row for an R600 GPUKind, or nullptr for a non-R600 kind.
+const R600Info *getR600Info(GPUKind AK) {
+ if (AK < R600FirstGPUKind)
+ return nullptr;
+ unsigned Idx = AK - R600FirstGPUKind;
+ if (Idx >= std::size(R600GPUTable))
+ return nullptr;
+ return &R600GPUTable[Idx];
+}
+
+// Scan a name -> GPUKind table (canonical names, then aliases) for \p CPU.
+template <typename InfoT, size_t N, size_t M>
+GPUKind parseArchImpl(StringRef CPU, const InfoT (&Table)[N], GPUKind FirstKind,
+ const StringTable &StrTab,
+ const GPUNameAlias (&Aliases)[M]) {
+ for (unsigned I = 0; I != N; ++I) {
+ if (CPU == StrTab[Table[I].Name])
+ return static_cast<GPUKind>(FirstKind + I);
+ }
+
+ for (const GPUNameAlias &A : Aliases) {
+ if (CPU == StrTab[A.AltName])
+ return A.Kind;
+ }
+
+ return GK_NONE;
+}
+
// Reverse map: SubArch -> GPUKind, indexed by (SubArch - FirstAMDGPUSubArch).
// Subarches with no GPU (incl. the NoSubArch pseudo targets) map to GK_NONE.
constexpr std::array<GPUKind, NumAMDGPUSubArches> AMDGPUSubArchToGPUKind = [] {
@@ -220,30 +265,18 @@ StringRef llvm::AMDGPU::getArchNameFromSubArch(Triple::SubArchType SubArch) {
}
StringRef llvm::AMDGPU::getArchNameR600(GPUKind AK) {
- switch (AK) {
-#define R600_GPU(NAME, ENUM, FEATURES) \
- case ENUM: \
- return NAME;
-#include "llvm/TargetParser/R600TargetParserDef.inc"
- default:
- return "";
- }
+ const R600Info *Info = getR600Info(AK);
+ return Info ? R600NameStrTab[Info->Name] : "";
}
AMDGPU::GPUKind llvm::AMDGPU::parseArchAMDGCN(StringRef CPU) {
- return StringSwitch<AMDGPU::GPUKind>(CPU)
-#define AMDGPU_GPU(NAME, ENUM) .Case(NAME, ENUM)
-#define AMDGPU_GPU_ALIAS(NAME, ENUM) .Case(NAME, ENUM)
-#include "llvm/TargetParser/AMDGPUTargetParserDef.inc"
- .Default(AMDGPU::GPUKind::GK_NONE);
+ return parseArchImpl(CPU, AMDGPUGPUTable, AMDGPUFirstGPUKind,
+ AMDGPUNameStrTab, AMDGPUGPUAliases);
}
AMDGPU::GPUKind llvm::AMDGPU::parseArchR600(StringRef CPU) {
- return StringSwitch<AMDGPU::GPUKind>(CPU)
-#define R600_GPU(NAME, ENUM, FEATURES) .Case(NAME, ENUM)
-#define R600_GPU_ALIAS(NAME, ENUM) .Case(NAME, ENUM)
-#include "llvm/TargetParser/R600TargetParserDef.inc"
- .Default(AMDGPU::GPUKind::GK_NONE);
+ return parseArchImpl(CPU, R600GPUTable, R600FirstGPUKind, R600NameStrTab,
+ R600GPUAliases);
}
unsigned AMDGPU::getArchAttrAMDGCN(GPUKind AK) {
@@ -256,36 +289,32 @@ unsigned AMDGPU::getArchAttrAMDGCN(Triple::SubArchType SubArch) {
}
R600FeatureKind AMDGPU::getArchAttrR600(GPUKind AK) {
- switch (AK) {
-#define R600_GPU(NAME, ENUM, FEATURES) \
- case ENUM: \
- return FEATURES;
-#include "llvm/TargetParser/R600TargetParserDef.inc"
- default:
- return R600_FEATURE_NONE;
- }
+ const R600Info *Info = getR600Info(AK);
+ return Info ? Info->ArchFeatures : R600_FEATURE_NONE;
}
void AMDGPU::fillValidArchListAMDGCN(SmallVectorImpl<StringRef> &Values,
Triple::SubArchType SubArch) {
// XXX: Should this only report unique canonical names?
// An alias shares its GPU's GPUKind, so it is filtered alongside it.
-#define AMDGPU_GPU(NAME, ENUM) \
- if (getSubArch(ENUM) != Triple::NoSubArch && \
- isCPUValidForSubArch(SubArch, ENUM)) \
- Values.push_back(NAME);
-#define AMDGPU_GPU_ALIAS(NAME, ENUM) \
- if (isCPUValidForSubArch(SubArch, ENUM)) \
- Values.push_back(NAME);
-#include "llvm/TargetParser/AMDGPUTargetParserDef.inc"
+ for (unsigned I = 0; I != std::size(AMDGPUGPUTable); ++I) {
+ GPUKind Kind = static_cast<GPUKind>(AMDGPUFirstGPUKind + I);
+ if (AMDGPUGPUTable[I].SubArch != Triple::NoSubArch &&
+ isCPUValidForSubArch(SubArch, Kind))
+ Values.push_back(AMDGPUNameStrTab[AMDGPUGPUTable[I].Name]);
+ }
+
+ for (const GPUNameAlias &A : AMDGPUGPUAliases) {
+ if (isCPUValidForSubArch(SubArch, A.Kind))
+ Values.push_back(AMDGPUNameStrTab[A.AltName]);
+ }
}
void AMDGPU::fillValidArchListR600(SmallVectorImpl<StringRef> &Values) {
- Values.append({
-#define R600_GPU(NAME, ENUM, FEATURES) NAME,
-#define R600_GPU_ALIAS(NAME, ENUM) NAME,
-#include "llvm/TargetParser/R600TargetParserDef.inc"
- });
+ for (const R600Info &Info : R600GPUTable)
+ Values.push_back(R600NameStrTab[Info.Name]);
+ for (const GPUNameAlias &A : R600GPUAliases)
+ Values.push_back(R600NameStrTab[A.AltName]);
}
AMDGPU::IsaVersion AMDGPU::getIsaVersion(StringRef GPU) {
diff --git a/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp b/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
index 4a675bd8f8339..5588a74719428 100644
--- a/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp
@@ -179,121 +179,155 @@ static void validate(ArrayRef<GPUEntry> Entries) {
}
}
-static void emitR600(raw_ostream &OS, const RecordKeeper &RK) {
+// The canonical R600 GPU records, in GPUKind-enum / TableGen definition order.
+static std::vector<const Record *>
+collectR600Canonicals(const RecordKeeper &RK) {
+ std::vector<GPUEntry> Entries = collectGPUs(RK, /*WantR600=*/true);
+ std::vector<const Record *> Canon;
+ Canon.reserve(Entries.size());
+
+ for (const GPUEntry &E : Entries) {
+ if (!E.IsAlias)
+ Canon.push_back(E.Rec);
+ }
+
+ return Canon;
+}
+
+// Emit the R600 GPUKind enumerators (canonical GPUs only; aliases share a
+// canonical's kind). Guarded by GET_R600_GPU_ENUM.
+static void emitR600Enum(raw_ostream &OS, const RecordKeeper &RK) {
+ std::vector<const Record *> Canon = collectR600Canonicals(RK);
+ if (Canon.empty())
+ return;
+ OS << "#ifdef GET_R600_GPU_ENUM\n"
+ "#undef GET_R600_GPU_ENUM\n";
+ for (const Record *R : Canon) {
+ OS << " ";
+ emitGPUKindEnum(OS, R->getValueAsString("Name"));
+ OS << ",\n";
+ }
+ OS << "#endif // GET_R600_GPU_ENUM\n\n";
+}
+
+// Emit the R600Info table indexed by (GPUKind - R600FirstGPUKind). Names are
+// offsets into the shared \p Names table. Guarded by GET_R600_GPU_TABLE.
+static void emitR600Table(raw_ostream &OS, const RecordKeeper &RK,
+ StringToOffsetTable &Names) {
+ std::vector<const Record *> Canon = collectR600Canonicals(RK);
+ if (Canon.empty())
+ return;
+
+ OS << "#ifdef GET_R600_GPU_TABLE\n"
+ "#undef GET_R600_GPU_TABLE\n";
+ OS << "static constexpr GPUKind R600FirstGPUKind = ";
+ emitGPUKindEnum(OS, Canon.front()->getValueAsString("Name"));
+ OS << ";\n"
+ "static constexpr R600Info R600GPUTable[] = {\n";
+ for (const Record *R : Canon) {
+ OS << " {" << Names.GetOrAddStringOffset(R->getValueAsString("Name"))
+ << ", ";
+ emitFeatureExpr(OS, R, "R600_FEATURE_NONE");
+ OS << "},\n";
+ }
+ OS << "};\n"
+ "#endif // GET_R600_GPU_TABLE\n\n";
+}
+
+// Emit the R600 name -> GPUKind alias table. Guarded by
+// GET_R600_GPU_ALIAS_TABLE; names are offsets into \p Names.
+static void emitR600Aliases(raw_ostream &OS, const RecordKeeper &RK,
+ StringToOffsetTable &Names) {
std::vector<GPUEntry> Entries = collectGPUs(RK, /*WantR600=*/true);
validate(Entries);
if (Entries.empty())
return;
- OS << "#ifndef R600_GPU\n"
- "#define R600_GPU(NAME, ENUM, FEATURES)\n"
- "#endif\n\n"
- "#ifndef R600_GPU_ALIAS\n"
- "#define R600_GPU_ALIAS(NAME, ENUM)\n"
- "#endif\n\n";
-
+ OS << "#ifdef GET_R600_GPU_ALIAS_TABLE\n"
+ "#undef GET_R600_GPU_ALIAS_TABLE\n"
+ "static constexpr GPUNameAlias R600GPUAliases[] = {\n";
for (const GPUEntry &E : Entries) {
- StringRef Name = E.Rec->getValueAsString("Name");
- if (E.IsAlias) {
- OS << "R600_GPU_ALIAS(\"" << Name << "\", ";
- emitGPUKindEnum(OS, E.Rec->getValueAsString("Alias"));
- OS << ")\n";
+ if (!E.IsAlias)
continue;
- }
- OS << "R600_GPU(\"" << Name << "\", ";
- emitGPUKindEnum(OS, Name);
- OS << ", ";
- emitFeatureExpr(OS, E.Rec, "R600_FEATURE_NONE");
- OS << ")\n";
+ OS << " {" << Names.GetOrAddStringOffset(E.Rec->getValueAsString("Name"))
+ << ", ";
+ emitGPUKindEnum(OS, E.Rec->getValueAsString("Alias"));
+ OS << "},\n";
}
-
- OS << "\n#undef R600_GPU\n"
- "#undef R600_GPU_ALIAS\n";
+ OS << "};\n"
+ "#endif // GET_R600_GPU_ALIAS_TABLE\n\n";
}
-// Return \p Entries with the generic-family entries moved after the non-generic
-// ones, each group keeping definition order. The GPUKind enum and GPUInfo table
-// are positional and rely on the generics forming a contiguous block at the
-// end, so both are emitted in this order.
-static std::vector<GPUEntry>
-orderGenericsLast(ArrayRef<GPUEntry> Entries,
- const StringMap<const Record *> &Canonicals) {
- std::vector<GPUEntry> Ordered;
- Ordered.reserve(Entries.size());
+// Canonical AMDGPU GPUs in GPUKind-enum order: non-generic targets first, then
+// the "gfxN-generic" targets. The enum and the GPUInfo table share this order.
+static std::vector<const Record *>
+collectAMDGPUCanonicals(const RecordKeeper &RK) {
+ std::vector<GPUEntry> Entries = collectGPUs(RK, /*WantR600=*/false);
+ std::vector<const Record *> Canon;
+ Canon.reserve(Entries.size());
for (const GPUEntry &E : Entries) {
- if (!E.isGeneric(Canonicals))
- Ordered.push_back(E);
+ if (!E.IsAlias && !isGenericTarget(E.Rec))
+ Canon.push_back(E.Rec);
}
for (const GPUEntry &E : Entries) {
- if (E.isGeneric(Canonicals))
- Ordered.push_back(E);
+ if (!E.IsAlias && isGenericTarget(E.Rec))
+ Canon.push_back(E.Rec);
}
- return Ordered;
+ return Canon;
}
-static void emitAMDGPUEntry(raw_ostream &OS, const GPUEntry &E) {
- StringRef Name = E.Rec->getValueAsString("Name");
- if (E.IsAlias) {
- OS << "AMDGPU_GPU_ALIAS(\"" << Name << "\", ";
- emitGPUKindEnum(OS, E.Rec->getValueAsString("Alias"));
- OS << ")\n";
- } else {
- OS << "AMDGPU_GPU(\"" << Name << "\", ";
- emitGPUKindEnum(OS, Name);
- OS << ")\n";
+// Emit the AMDGPU GPUKind enumerators (canonical GPUs only; aliases share a
+// canonical's kind). Guarded by GET_AMDGPU_GPU_ENUM.
+static void emitAMDGPUEnum(raw_ostream &OS, const RecordKeeper &RK) {
+ std::vector<const Record *> Canon = collectAMDGPUCanonicals(RK);
+ if (Canon.empty())
+ return;
+ OS << "#ifdef GET_AMDGPU_GPU_ENUM\n"
+ "#undef GET_AMDGPU_GPU_ENUM\n";
+ for (const Record *R : Canon) {
+ OS << " ";
+ emitGPUKindEnum(OS, R->getValueAsString("Name"));
+ OS << ",\n";
}
+ OS << "#endif // GET_AMDGPU_GPU_ENUM\n\n";
}
-static void emitAMDGPU(raw_ostream &OS, const RecordKeeper &RK) {
+// Emit the name -> GPUKind alias table (legacy names such as "tahiti" ->
+// gfx600). Guarded by GET_AMDGPU_GPU_ALIAS_TABLE; names are offsets into \p
+// Names.
+static void emitAMDGPUAliases(raw_ostream &OS, const RecordKeeper &RK,
+ StringToOffsetTable &Names) {
std::vector<GPUEntry> Entries = collectGPUs(RK, /*WantR600=*/false);
validate(Entries);
if (Entries.empty())
return;
- StringMap<const Record *> Canonicals;
+ OS << "#ifdef GET_AMDGPU_GPU_ALIAS_TABLE\n"
+ "#undef GET_AMDGPU_GPU_ALIAS_TABLE\n"
+ "static constexpr GPUNameAlias AMDGPUGPUAliases[] = {\n";
for (const GPUEntry &E : Entries) {
if (!E.IsAlias)
- Canonicals[E.Rec->getValueAsString("Name")] = E.Rec;
+ continue;
+ OS << " {" << Names.GetOrAddStringOffset(E.Rec->getValueAsString("Name"))
+ << ", ";
+ emitGPUKindEnum(OS, E.Rec->getValueAsString("Alias"));
+ OS << "},\n";
}
-
- OS << "#ifndef AMDGPU_GPU\n"
- "#define AMDGPU_GPU(NAME, ENUM)\n"
- "#endif\n\n"
- "#ifndef AMDGPU_GPU_ALIAS\n"
- "#define AMDGPU_GPU_ALIAS(NAME, ENUM)\n"
- "#endif\n\n";
-
- for (const GPUEntry &E : orderGenericsLast(Entries, Canonicals))
- emitAMDGPUEntry(OS, E);
-
- OS << "\n#undef AMDGPU_GPU\n"
- "#undef AMDGPU_GPU_ALIAS\n";
+ OS << "};\n"
+ "#endif // GET_AMDGPU_GPU_ALIAS_TABLE\n\n";
}
/// Emit a GPUInfo table indexed by (GPUKind - AMDGPUFirstGPUKind). Name and
/// family strings are stored as offsets into the shared \p Names table.
static void emitAMDGPUTable(raw_ostream &OS, const RecordKeeper &RK,
StringToOffsetTable &Names) {
- std::vector<GPUEntry> Entries = collectGPUs(RK, /*WantR600=*/false);
- if (Entries.empty())
+ std::vector<const Record *> Canon = collectAMDGPUCanonicals(RK);
+ if (Canon.empty())
return;
- StringMap<const Record *> Canonicals;
- for (const GPUEntry &E : Entries) {
- if (!E.IsAlias)
- Canonicals[E.Rec->getValueAsString("Name")] = E.Rec;
- }
-
- // Canonicals only; aliases share a canonical's GPUKind row.
- std::vector<const Record *> Canon;
- for (const GPUEntry &E : orderGenericsLast(Entries, Canonicals)) {
- if (!E.IsAlias)
- Canon.push_back(E.Rec);
- }
-
OS << "#ifdef GET_AMDGPU_GPU_TABLE\n"
"#undef GET_AMDGPU_GPU_TABLE\n";
OS << "static constexpr GPUKind AMDGPUFirstGPUKind = ";
@@ -314,11 +348,10 @@ 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
+// Emit the subarch -> major-family-subarch overrides for getMajorSubArch (a
+// subarch not listed here is its own major). Each member GPU maps to its
+// family's major, sourced from a "gfxN-generic" target's CoveredGPUs, or from
+// 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 =
@@ -408,30 +441,45 @@ static void emitAMDGPUSubArchNames(raw_ostream &OS, const RecordKeeper &RK,
static void emitAMDGPUTargetDef(const RecordKeeper &RK, raw_ostream &OS) {
OS << "// Autogenerated by AMDGPUTargetDefEmitter.cpp\n\n";
- // R600 processors are Processor records; AMDGPU processors are
- // ProcessorModel records. R600.td and AMDGPU.td are separate top-level files
- // (neither includes the other), so exactly one family is present in a given
- // run; the other section emits nothing.
- emitR600(OS, RK);
- emitAMDGPU(OS, RK);
+ // R600.td and AMDGPU.td are separate top-level files, so a run sees exactly
+ // one family; the other family's sections emit nothing.
+ emitR600Enum(OS, RK);
+ emitAMDGPUEnum(OS, RK);
emitAMDGPUMajorSubArch(OS, RK);
- // The GPUInfo and SubArchName tables both reference GPU-name strings; pool
- // them into a single string table. Buffer the two tables first so every
- // referenced string is interned, then emit the shared table def (guarded so
- // consumers pull it in once) ahead of the buffered tables.
- StringToOffsetTable Names;
- std::string GPUTable, SubArchNames;
- raw_string_ostream GPUTableOS(GPUTable), SubArchNamesOS(SubArchNames);
- emitAMDGPUTable(GPUTableOS, RK, Names);
- emitAMDGPUSubArchNames(SubArchNamesOS, RK, Names);
-
- OS << "#ifdef GET_AMDGPU_NAME_TABLE\n"
- "#undef GET_AMDGPU_NAME_TABLE\n";
- Names.EmitStringTableDef(OS, "AMDGPUNameTable");
- OS << "#endif // GET_AMDGPU_NAME_TABLE\n\n";
-
- OS << GPUTable << SubArchNames;
+ // Each family gets its own string pool with a distinct guard/symbol so the
+ // two generated headers stay independent when a consumer includes both.
+ // Buffer the tables first to intern their strings, then emit the pool ahead.
+ {
+ StringToOffsetTable Names;
+ std::string Tables;
+ raw_string_ostream TablesOS(Tables);
+ emitR600Table(TablesOS, RK, Names);
+ emitR600Aliases(TablesOS, RK, Names);
+ if (!Tables.empty()) {
+ OS << "#ifdef GET_R600_NAME_TABLE\n"
+ "#undef GET_R600_NAME_TABLE\n";
+ Names.EmitStringTableDef(OS, "R600NameTable");
+ OS << "#endif // GET_R600_NAME_TABLE\n\n";
+ OS << Tables;
+ }
+ }
+
+ {
+ StringToOffsetTable Names;
+ std::string Tables;
+ raw_string_ostream TablesOS(Tables);
+ emitAMDGPUTable(TablesOS, RK, Names);
+ emitAMDGPUAliases(TablesOS, RK, Names);
+ emitAMDGPUSubArchNames(TablesOS, RK, Names);
+ if (!Tables.empty()) {
+ OS << "#ifdef GET_AMDGPU_NAME_TABLE\n"
+ "#undef GET_AMDGPU_NAME_TABLE\n";
+ Names.EmitStringTableDef(OS, "AMDGPUNameTable");
+ OS << "#endif // GET_AMDGPU_NAME_TABLE\n\n";
+ OS << Tables;
+ }
+ }
}
static TableGen::Emitter::Opt X("gen-amdgpu-target-def", emitAMDGPUTargetDef,
More information about the cfe-commits
mailing list