llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-tablegen Author: Alexander Richardson (arichardson) <details> <summary>Changes</summary> This helper can be useful in validateTargetOperandClass to get the MCRegisterClass for the MCK_* enum. Migrate the RVY logic to use this new generated function. Checking all register classes instead of just the RVY ones will marginally slow down validateTargetOperandClass, but since this is already a slow path it should not matter. --- Full diff: https://github.com/llvm/llvm-project/pull/200453.diff 3 Files Affected: - (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (-21) - (added) llvm/test/TableGen/getRegClassFromMatchKind.td (+104) - (modified) llvm/utils/TableGen/AsmMatcherEmitter.cpp (+35) ``````````diff diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 19b724e481f69..98f7f4b6ec1a7 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -1394,27 +1394,6 @@ static MatchClassKind remapRegClassByHwMode(MatchClassKind Kind, bool Purecap) { } } -static const MCRegisterClass *getRegClassFromMatchKind(MatchClassKind K) { - // TODO: it would be nice to have tablegen generate this. - switch (K) { - case MCK_GPR: - return &RISCVMCRegisterClasses[RISCV::GPRRegClassID]; - case MCK_GPRC: - return &RISCVMCRegisterClasses[RISCV::GPRCRegClassID]; - case MCK_GPRSP: - return &RISCVMCRegisterClasses[RISCV::GPRSPRegClassID]; - case MCK_YGPR: - return &RISCVMCRegisterClasses[RISCV::YGPRRegClassID]; - case MCK_YGPRC: - return &RISCVMCRegisterClasses[RISCV::YGPRCRegClassID]; - case MCK_YGPRNoX0: - return &RISCVMCRegisterClasses[RISCV::YGPRNoX0RegClassID]; - case MCK_YGPRSP: - return &RISCVMCRegisterClasses[RISCV::YGPRSPRegClassID]; - default: - return nullptr; - } -} unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, unsigned _Kind) { diff --git a/llvm/test/TableGen/getRegClassFromMatchKind.td b/llvm/test/TableGen/getRegClassFromMatchKind.td new file mode 100644 index 0000000000000..6c629f6e11ac4 --- /dev/null +++ b/llvm/test/TableGen/getRegClassFromMatchKind.td @@ -0,0 +1,104 @@ +// RUN: llvm-tblgen -gen-asm-matcher -I %p/../../include %s | FileCheck %s --check-prefix=ASMMATCHER +// RUN: llvm-tblgen -gen-register-info -I %p/../../include %s -o %t.inc +// RUN: FileCheck %s --check-prefix=REGINFO-ENUM --input-file=%tEnums.inc +// RUN: FileCheck %s --check-prefix=REGINFO-DESC --input-file=%tMCDesc.inc + +/// This test verifies that TableGen's AsmMatcherEmitter correctly generates +/// the target-independent `getRegClassFromMatchKind` mapping function. +/// +/// It specifically verifies that: +/// - Explicit named target RegisterClasses (like `RegClass`) are mapped. +/// - Singleton registers (like `Reg` used literally in `bar` instruction) +/// which generate implicit `MCK_Reg` match classes are NOT mapped. +/// - Non-register class operands (like the custom immediate `MyImmOp` +/// in `baz` instruction) are NOT mapped. +/// - All register classes are covered by the generated function (checking enums) + + +include "llvm/Target/Target.td" + +def ArchInstrInfo : InstrInfo { } + +def ArchAsmParserVariant : AsmParserVariant { + let Variant = 0; + let Name = "Arch"; +} + +def Arch : Target { + let InstructionSet = ArchInstrInfo; + let AssemblyParserVariants = [ArchAsmParserVariant]; +} + +let Namespace = "Arch" in { + def Reg : Register<"reg">; + def Reg2 : Register<"reg2">; +} + +/// Use "Arch" as namespace to match the Target name. +def RegClass : RegisterClass<"Arch", [i32], 0, (add Reg, Reg2)>; + +def MyImmAsmOperand : AsmOperandClass { + let Name = "MyImm"; +} + +def MyImmOp : Operand<i32> { + let ParserMatchClass = MyImmAsmOperand; +} + +def foo : Instruction { + let Size = 2; + let OutOperandList = (outs); + let InOperandList = (ins RegClass:$src); + let AsmString = "foo $src"; + let Namespace = "Arch"; +} + +def bar : Instruction { + let Size = 2; + let OutOperandList = (outs); + let InOperandList = (ins); + let AsmString = "bar reg"; // uses Reg literally, making it a singleton register + let Namespace = "Arch"; +} + +def baz : Instruction { + let Size = 2; + let OutOperandList = (outs); + let InOperandList = (ins MyImmOp:$imm); + let AsmString = "baz $imm"; // uses MyImmAsmOperand + let Namespace = "Arch"; +} + +// ASMMATCHER: enum MatchClassKind { +// ASMMATCHER-NEXT: InvalidMatchClass = 0, +// ASMMATCHER-NEXT: OptionalMatchClass = 1, +// ASMMATCHER-NEXT: MCK_LAST_TOKEN = OptionalMatchClass, +// ASMMATCHER-NEXT: MCK_Reg, // register class 'Reg' +// ASMMATCHER-NEXT: MCK_RegClass, // register class 'RegClass' +// ASMMATCHER-NEXT: MCK_LAST_REGISTER = MCK_RegClass, +// ASMMATCHER-NEXT: MCK_Imm, // user defined class 'ImmAsmOperand' +// ASMMATCHER-NEXT: MCK_MyImm, // user defined class 'MyImmAsmOperand' +// ASMMATCHER-NEXT: NumMatchClassKinds +// ASMMATCHER-NEXT: }; + +// ASMMATCHER: {{\[\[}}maybe_unused]] static const MCRegisterClass *getRegClassFromMatchKind(MatchClassKind Kind) { +// ASMMATCHER-NEXT: switch (Kind) { +// ASMMATCHER-NEXT: case MCK_RegClass: +// ASMMATCHER-NEXT: return &ArchMCRegisterClasses[Arch::RegClassRegClassID]; +// ASMMATCHER-NEXT: default: +// ASMMATCHER-NEXT: return nullptr; +// ASMMATCHER-NEXT: } +// ASMMATCHER-NEXT: } + +// REGINFO-ENUM: // Register classes +// REGINFO-ENUM-EMPTY: +// REGINFO-ENUM-NEXT: namespace Arch { +// REGINFO-ENUM-EMPTY: +// REGINFO-ENUM-NEXT: enum { +// REGINFO-ENUM-NEXT: RegClassRegClassID = 0, +// REGINFO-ENUM-EMPTY: +// REGINFO-ENUM-NEXT: }; + +// REGINFO-DESC: extern const MCRegisterClass ArchMCRegisterClasses[] = { +// REGINFO-DESC-NEXT: { RegClass, RegClassBits, 0, 2, sizeof(RegClassBits), Arch::RegClassRegClassID, 32, 1, true, false }, +// REGINFO-DESC-NEXT: }; diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp index 4c61d64ec215a..9eee31d0f0018 100644 --- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -2520,6 +2520,37 @@ static void emitRegisterMatchErrorFunc(AsmMatcherInfo &Info, raw_ostream &OS) { OS << "}\n\n"; } +// Returns true if ClassName corresponds to a RegisterClass defined in the +// target description (and thus has a generated RegClassID), rather than a +// singleton register or an anonymous derived register class. +static bool isDefinedRegisterClass(const AsmMatcherInfo &Info, + StringRef ClassName) { + for (const auto &RC : Info.Target.getRegBank().getRegClasses()) { + if (RC.getName() == ClassName) + return true; + } + return false; +} + +static void emitGetRegClassFromMatchKindFunc(AsmMatcherInfo &Info, + raw_ostream &OS) { + OS << "[[maybe_unused]] static const MCRegisterClass " + "*getRegClassFromMatchKind(MatchClassKind Kind) {\n"; + OS << " switch (Kind) {\n"; + for (const auto &CI : Info.Classes) { + if (CI.isRegisterClass() && !CI.ValueName.empty() && + isDefinedRegisterClass(Info, CI.ClassName)) { + OS << " case " << CI.Name << ":\n"; + OS << " return &" << Info.Target.getName() << "MCRegisterClasses[" + << Info.Target.getName() << "::" << CI.ClassName << "RegClassID];\n"; + } + } + OS << " default:\n"; + OS << " return nullptr;\n"; + OS << " }\n"; + OS << "}\n\n"; +} + /// emitValidateOperandClass - Emit the function to validate an operand class. static void emitValidateOperandClass(const CodeGenTarget &Target, AsmMatcherInfo &Info, raw_ostream &OS) { @@ -3507,6 +3538,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "\n#ifdef GET_MATCHER_IMPLEMENTATION\n"; OS << "#undef GET_MATCHER_IMPLEMENTATION\n\n"; + OS << "#include \"llvm/MC/MCRegisterInfo.h\"\n\n"; // Generate the function that remaps for mnemonic aliases. bool HasMnemonicAliases = emitMnemonicAliases(OS, Info, Target); @@ -3528,6 +3560,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Emit a function to map register classes to operand match failure codes. emitRegisterMatchErrorFunc(Info, OS); + // Emit a function to map MatchClassKind to MCRegisterClass. + emitGetRegClassFromMatchKindFunc(Info, OS); + // Emit the routine to match token strings to their match class. emitMatchTokenString(Target, Info.Classes, OS); `````````` </details> https://github.com/llvm/llvm-project/pull/200453 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
