[llvm-branch-commits] [llvm] [TableGen] Expose remapRegClassByHwMode() helper in AsmMatcher (PR #223302)
Alexander Richardson via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Sep 13 21:46:16 PDT 2026
https://github.com/arichardson updated https://github.com/llvm/llvm-project/pull/223302
>From 75cb490c08be8643e6018e739ec477d7d2edf7d2 Mon Sep 17 00:00:00 2001
From: Alex Richardson <alexrichardson at google.com>
Date: Sun, 13 Sep 2026 21:41:45 -0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
=?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.8-beta.1
---
llvm/test/TableGen/RegClassByHwMode.td | 64 +++++++-----
llvm/utils/TableGen/AsmMatcherEmitter.cpp | 122 ++++++++++++----------
2 files changed, 103 insertions(+), 83 deletions(-)
diff --git a/llvm/test/TableGen/RegClassByHwMode.td b/llvm/test/TableGen/RegClassByHwMode.td
index a9acc154ad933..d03c1e4246d33 100644
--- a/llvm/test/TableGen/RegClassByHwMode.td
+++ b/llvm/test/TableGen/RegClassByHwMode.td
@@ -97,39 +97,47 @@ include "Common/RegClassByHwModeCommon.td"
// ASMMATCHER-NEXT: MCK_LAST_REGCLASS_BY_HWMODE = MCK_RegByHwMode_YRegs_EvenIfRequired,
// ASMMATCHER-NEXT: MCK_Imm, // user defined class 'ImmAsmOperand'
+// ASMMATCHER: static constexpr MatchClassKind RegClassByHwModeMatchTable[4][3] = {
+// ASMMATCHER-NEXT: { // DefaultMode
+// ASMMATCHER-NEXT: MCK_PtrRegs32, // MyPtrRC
+// ASMMATCHER-NEXT: MCK_XRegs, // XRegs_EvenIfRequired
+// ASMMATCHER-NEXT: MCK_YRegs, // YRegs_EvenIfRequired
+// ASMMATCHER-NEXT: },
+// ASMMATCHER-NEXT: { // EvenMode
+// ASMMATCHER-NEXT: InvalidMatchClass, // Missing mode entry for MyPtrRC
+// ASMMATCHER-NEXT: MCK_XRegs_Even, // XRegs_EvenIfRequired
+// ASMMATCHER-NEXT: MCK_YRegs_Even, // YRegs_EvenIfRequired
+// ASMMATCHER-NEXT: },
+// ASMMATCHER-NEXT: { // OddMode
+// ASMMATCHER-NEXT: InvalidMatchClass, // Missing mode entry for MyPtrRC
+// ASMMATCHER-NEXT: MCK_XRegs_Odd, // XRegs_EvenIfRequired
+// ASMMATCHER-NEXT: InvalidMatchClass, // Missing mode entry for YRegs_EvenIfRequired
+// ASMMATCHER-NEXT: },
+// ASMMATCHER-NEXT: { // Ptr64
+// ASMMATCHER-NEXT: MCK_PtrRegs64, // MyPtrRC
+// ASMMATCHER-NEXT: InvalidMatchClass, // Missing mode entry for XRegs_EvenIfRequired
+// ASMMATCHER-NEXT: InvalidMatchClass, // Missing mode entry for YRegs_EvenIfRequired
+// ASMMATCHER-NEXT: },
+// ASMMATCHER-NEXT: };
+// ASMMATCHER-EMPTY:
+// ASMMATCHER-NEXT: static_assert(MCK_LAST_REGCLASS_BY_HWMODE - MCK_LAST_REGISTER == 3);
+// ASMMATCHER-EMPTY:
+// ASMMATCHER-NEXT: {{\[\[}}maybe_unused{{\]\]}} static inline MatchClassKind
+// ASMMATCHER-NEXT: remapRegClassByHwMode(unsigned Kind, const MCSubtargetInfo &STI) {
+// ASMMATCHER-NEXT: if (Kind > MCK_LAST_REGISTER && Kind <= MCK_LAST_REGCLASS_BY_HWMODE) {
+// ASMMATCHER-NEXT: unsigned HwMode = STI.getHwMode(MCSubtargetInfo::HwMode_RegInfo);
+// ASMMATCHER-NEXT: assert(HwMode < 4 && "Invalid HwMode");
+// ASMMATCHER-NEXT: return RegClassByHwModeMatchTable[HwMode][Kind - (MCK_LAST_REGISTER + 1)];
+// ASMMATCHER-NEXT: }
+// ASMMATCHER-NEXT: return static_cast<MatchClassKind>(Kind);
+// ASMMATCHER-NEXT: }
+
// ASMMATCHER: static unsigned validateOperandClass(MCParsedAsmOperand &GOp, MatchClassKind Kind, const MCSubtargetInfo &STI) {
// ASMMATCHER: if (Kind <= MCK_LAST_TOKEN) {
// ASMMATCHER: switch (Kind) {
-// ASMMATCHER: if (Kind > MCK_LAST_REGISTER && Kind <= MCK_LAST_REGCLASS_BY_HWMODE) {
-// ASMMATCHER-NEXT: static constexpr MatchClassKind RegClassByHwModeMatchTable[4][3] = {
-// ASMMATCHER-NEXT: { // DefaultMode
-// ASMMATCHER-NEXT: MCK_PtrRegs32, // MyPtrRC
-// ASMMATCHER-NEXT: MCK_XRegs, // XRegs_EvenIfRequired
-// ASMMATCHER-NEXT: MCK_YRegs, // YRegs_EvenIfRequired
-// ASMMATCHER-NEXT: },
-// ASMMATCHER-NEXT: { // EvenMode
-// ASMMATCHER-NEXT: InvalidMatchClass, // Missing mode entry for MyPtrRC
-// ASMMATCHER-NEXT: MCK_XRegs_Even, // XRegs_EvenIfRequired
-// ASMMATCHER-NEXT: MCK_YRegs_Even, // YRegs_EvenIfRequired
-// ASMMATCHER-NEXT: },
-// ASMMATCHER-NEXT: { // OddMode
-// ASMMATCHER-NEXT: InvalidMatchClass, // Missing mode entry for MyPtrRC
-// ASMMATCHER-NEXT: MCK_XRegs_Odd, // XRegs_EvenIfRequired
-// ASMMATCHER-NEXT: InvalidMatchClass, // Missing mode entry for YRegs_EvenIfRequired
-// ASMMATCHER-NEXT: },
-// ASMMATCHER-NEXT: { // Ptr64
-// ASMMATCHER-NEXT: MCK_PtrRegs64, // MyPtrRC
-// ASMMATCHER-NEXT: InvalidMatchClass, // Missing mode entry for XRegs_EvenIfRequired
-// ASMMATCHER-NEXT: InvalidMatchClass, // Missing mode entry for YRegs_EvenIfRequired
-// ASMMATCHER-NEXT: },
-// ASMMATCHER-NEXT: };
-// ASMMATCHER-EMPTY:
-// ASMMATCHER-NEXT: static_assert(MCK_LAST_REGCLASS_BY_HWMODE - MCK_LAST_REGISTER == 3);
-// ASMMATCHER-NEXT: const unsigned HwMode = STI.getHwMode(MCSubtargetInfo::HwMode_RegInfo);
-// ASMMATCHER-NEXT: Kind = RegClassByHwModeMatchTable[HwMode][Kind - (MCK_LAST_REGISTER + 1)];
-// ASMMATCHER-NEXT: }
+// ASMMATCHER: Kind = remapRegClassByHwMode(Kind, STI);
// ASMMATCHER: if (Operand.isReg()) {
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index 5e2127d139081..34ebb34edb055 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -2624,6 +2624,67 @@ static void emitGetRegClassFromMatchKindFunc(AsmMatcherInfo &Info,
OS << "}\n\n";
}
+/// emitRegClassByHwModeMatchTable - Emit the RegClassByHwMode match table and
+/// helper functions for remapping match classes by hardware mode.
+static void emitRegClassByHwModeMatchTable(const CodeGenTarget &Target,
+ AsmMatcherInfo &Info,
+ raw_ostream &OS) {
+ ArrayRef<const Record *> RegClassesByHwMode = Target.getAllRegClassByHwMode();
+ if (RegClassesByHwMode.empty())
+ return;
+
+ const CodeGenHwModes &CGH = Target.getHwModes();
+ const CodeGenRegBank &RegBank = Target.getRegBank();
+ unsigned NumModes = CGH.getNumModeIds();
+ unsigned NumClassesByHwMode = RegClassesByHwMode.size();
+
+ OS << "static constexpr MatchClassKind RegClassByHwModeMatchTable["
+ << NumModes << "][" << NumClassesByHwMode << "] = {\n";
+
+ // TODO: If the instruction predicates can statically resolve which hwmode,
+ // directly match the register class
+ for (unsigned M = 0; M < NumModes; ++M) {
+ OS << " { // " << CGH.getModeName(M, /*IncludeDefault=*/true) << '\n';
+ for (unsigned I = 0; I != NumClassesByHwMode; ++I) {
+ const Record *Class = RegClassesByHwMode[I];
+ const HwModeSelect &ModeSelect = CGH.getHwModeSelect(Class);
+
+ auto FoundMode =
+ find_if(ModeSelect.Items, [=](const HwModeSelect::PairType P) {
+ return P.first == M;
+ });
+
+ if (FoundMode == ModeSelect.Items.end()) {
+ OS << " InvalidMatchClass, // Missing mode entry for "
+ << Class->getName() << "\n";
+ } else {
+ const CodeGenRegisterClass *RegClass =
+ RegBank.getRegClass(FoundMode->second);
+ const ClassInfo *CI =
+ Info.RegisterClassClasses.at(RegClass->getDef());
+ OS << " " << CI->Name << ", // " << Class->getName() << "\n";
+ }
+ }
+
+ OS << " },\n";
+ }
+
+ OS << "};\n\n";
+
+ OS << "static_assert(MCK_LAST_REGCLASS_BY_HWMODE - MCK_LAST_REGISTER == "
+ << NumClassesByHwMode << ");\n\n";
+
+ OS << "[[maybe_unused]] static inline MatchClassKind\n"
+ << "remapRegClassByHwMode(unsigned Kind, const MCSubtargetInfo &STI) {\n"
+ << " if (Kind > MCK_LAST_REGISTER && Kind <= MCK_LAST_REGCLASS_BY_HWMODE) {\n"
+ << " unsigned HwMode = STI.getHwMode(MCSubtargetInfo::HwMode_RegInfo);\n"
+ << " assert(HwMode < " << NumModes << " && \"Invalid HwMode\");\n"
+ << " return RegClassByHwModeMatchTable[HwMode][Kind - (MCK_LAST_REGISTER + 1)];\n"
+ << " }\n"
+ << " return static_cast<MatchClassKind>(Kind);\n"
+ << "}\n\n";
+}
+
/// emitValidateOperandClass - Emit the function to validate an operand class.
static void emitValidateOperandClass(const CodeGenTarget &Target,
AsmMatcherInfo &Info, raw_ostream &OS) {
@@ -2672,69 +2733,17 @@ static void emitValidateOperandClass(const CodeGenTarget &Target,
}
OS << " } // end switch (Kind)\n\n";
- const CodeGenRegBank &RegBank = Target.getRegBank();
ArrayRef<const Record *> RegClassesByHwMode = Target.getAllRegClassByHwMode();
- unsigned NumClassesByHwMode = RegClassesByHwMode.size();
-
if (!RegClassesByHwMode.empty()) {
// Resolve RegClassByHwMode kinds to their concrete class regardless of
// whether Operand is actually a register, so that the diagnostic
// fallback paths below (for both register and non-register operands)
// see a concrete class rather than an unresolved by-hwmode one.
- OS << " if (Kind > MCK_LAST_REGISTER &&"
- " Kind <= MCK_LAST_REGCLASS_BY_HWMODE) {\n";
-
- const CodeGenHwModes &CGH = Target.getHwModes();
- unsigned NumModes = CGH.getNumModeIds();
-
- OS << indent(4)
- << "static constexpr MatchClassKind RegClassByHwModeMatchTable["
- << NumModes << "][" << RegClassesByHwMode.size() << "] = {\n";
-
- // TODO: If the instruction predicates can statically resolve which hwmode,
- // directly match the register class
- for (unsigned M = 0; M < NumModes; ++M) {
- OS << indent(6) << "{ // " << CGH.getModeName(M, /*IncludeDefault=*/true)
- << '\n';
- for (unsigned I = 0; I != NumClassesByHwMode; ++I) {
- const Record *Class = RegClassesByHwMode[I];
- const HwModeSelect &ModeSelect = CGH.getHwModeSelect(Class);
-
- auto FoundMode =
- find_if(ModeSelect.Items, [=](const HwModeSelect::PairType P) {
- return P.first == M;
- });
-
- if (FoundMode == ModeSelect.Items.end()) {
- OS << indent(8) << "InvalidMatchClass, // Missing mode entry for "
- << Class->getName() << "\n";
- } else {
- const CodeGenRegisterClass *RegClass =
- RegBank.getRegClass(FoundMode->second);
- const ClassInfo *CI =
- Info.RegisterClassClasses.at(RegClass->getDef());
- OS << indent(8) << CI->Name << ", // " << Class->getName() << "\n";
- }
- }
-
- OS << indent(6) << "},\n";
- }
-
- OS << indent(4) << "};\n\n";
-
- OS << indent(4)
- << "static_assert(MCK_LAST_REGCLASS_BY_HWMODE - MCK_LAST_REGISTER == "
- << NumClassesByHwMode << ");\n";
-
- OS << indent(4)
- << "const unsigned HwMode = "
- "STI.getHwMode(MCSubtargetInfo::HwMode_RegInfo);\n"
- << indent(4)
- << "Kind = RegClassByHwModeMatchTable[HwMode][Kind - (MCK_LAST_REGISTER "
- "+ 1)];\n"
- " }\n\n";
+ OS << " Kind = remapRegClassByHwMode(Kind, STI);\n\n";
}
+ const CodeGenRegBank &RegBank = Target.getRegBank();
+
// Check for register operands, including sub-classes.
const auto &Regs = RegBank.getRegisters();
StringRef Namespace = Regs.front().TheDef->getValueAsString("Namespace");
@@ -3649,6 +3658,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (AsmParser->getValueAsBit("EmitTokenDiagnosticTypes"))
emitTokenDiagFunction(Info, OS);
+ // Emit the RegClassByHwMode match table and remap helper functions.
+ emitRegClassByHwModeMatchTable(Target, Info, OS);
+
// Emit the routine to validate an operand against a match class.
emitValidateOperandClass(Target, Info, OS);
More information about the llvm-branch-commits
mailing list