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 <[email protected]> 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); _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
