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

Reply via email to