[llvm] [TableGen] Handle RegClassByHwMode in AsmWriter (PR #171264)

via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 8 21:59:31 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-mc

Author: Alexander Richardson (arichardson)

<details>
<summary>Changes</summary>

Previously, we were emitting a broken AliasPatternCond array, outputting
`MyTarget::RegClassByHwModeRegClassID` which does not exist.
Instead, we now add a new predicate and pass the RegClassByHwMode index
as the value argument.


---
Full diff: https://github.com/llvm/llvm-project/pull/171264.diff


4 Files Affected:

- (modified) llvm/include/llvm/MC/MCInstPrinter.h (+12-11) 
- (modified) llvm/lib/MC/MCInstPrinter.cpp (+8-1) 
- (added) llvm/test/TableGen/RegClassByHwModeAlias.td (+48) 
- (modified) llvm/utils/TableGen/AsmWriterEmitter.cpp (+13-9) 


``````````diff
diff --git a/llvm/include/llvm/MC/MCInstPrinter.h b/llvm/include/llvm/MC/MCInstPrinter.h
index 434c2e7623563..c615d01493989 100644
--- a/llvm/include/llvm/MC/MCInstPrinter.h
+++ b/llvm/include/llvm/MC/MCInstPrinter.h
@@ -201,17 +201,18 @@ struct AliasPattern {
 
 struct AliasPatternCond {
   enum CondKind : uint8_t {
-    K_Feature,       // Match only if a feature is enabled.
-    K_NegFeature,    // Match only if a feature is disabled.
-    K_OrFeature,     // Match only if one of a set of features is enabled.
-    K_OrNegFeature,  // Match only if one of a set of features is disabled.
-    K_EndOrFeatures, // Note end of list of K_Or(Neg)?Features.
-    K_Ignore,        // Match any operand.
-    K_Reg,           // Match a specific register.
-    K_TiedReg,       // Match another already matched register.
-    K_Imm,           // Match a specific immediate.
-    K_RegClass,      // Match registers in a class.
-    K_Custom,        // Call custom matcher by index.
+    K_Feature,          // Match only if a feature is enabled.
+    K_NegFeature,       // Match only if a feature is disabled.
+    K_OrFeature,        // Match only if one of a set of features is enabled.
+    K_OrNegFeature,     // Match only if one of a set of features is disabled.
+    K_EndOrFeatures,    // Note end of list of K_Or(Neg)?Features.
+    K_Ignore,           // Match any operand.
+    K_Reg,              // Match a specific register.
+    K_TiedReg,          // Match another already matched register.
+    K_Imm,              // Match a specific immediate.
+    K_RegClass,         // Match registers in a class.
+    K_RegClassByHwMode, // Match registers in a class (by HwMode)
+    K_Custom,           // Call custom matcher by index.
   };
 
   CondKind Kind;
diff --git a/llvm/lib/MC/MCInstPrinter.cpp b/llvm/lib/MC/MCInstPrinter.cpp
index 069716a3ecf9b..ac8f84270ee74 100644
--- a/llvm/lib/MC/MCInstPrinter.cpp
+++ b/llvm/lib/MC/MCInstPrinter.cpp
@@ -61,6 +61,7 @@ void MCInstPrinter::printAnnotation(raw_ostream &OS, StringRef Annot) {
 }
 
 static bool matchAliasCondition(const MCInst &MI, const MCSubtargetInfo *STI,
+                                const MCInstrInfo &MII,
                                 const MCRegisterInfo &MRI, unsigned &OpIdx,
                                 const AliasMatchingData &M,
                                 const AliasPatternCond &C,
@@ -102,6 +103,12 @@ static bool matchAliasCondition(const MCInst &MI, const MCSubtargetInfo *STI,
   case AliasPatternCond::K_TiedReg:
     // Operand must match the register of another operand.
     return Opnd.isReg() && Opnd.getReg() == MI.getOperand(C.Value).getReg();
+  case AliasPatternCond::K_RegClassByHwMode: {
+    // Operand must be RegisterByHwMode. Value is RegClassByHwMode index.
+    unsigned HwModeId = STI->getHwMode(MCSubtargetInfo::HwMode_RegInfo);
+    int16_t RCID = MII.getRegClassByHwModeTable(HwModeId)[C.Value];
+    return Opnd.isReg() && MRI.getRegClass(RCID).contains(Opnd.getReg());
+  }
   case AliasPatternCond::K_RegClass:
     // Operand must be a register in this class. Value is a register class id.
     return Opnd.isReg() && MRI.getRegClass(C.Value).contains(Opnd.getReg());
@@ -148,7 +155,7 @@ const char *MCInstPrinter::matchAliasPatterns(const MCInst *MI,
     unsigned OpIdx = 0;
     bool OrPredicateResult = false;
     if (llvm::all_of(Conds, [&](const AliasPatternCond &C) {
-          return matchAliasCondition(*MI, STI, MRI, OpIdx, M, C,
+          return matchAliasCondition(*MI, STI, MII, MRI, OpIdx, M, C,
                                      OrPredicateResult);
         })) {
       // If all conditions matched, use this asm string.
diff --git a/llvm/test/TableGen/RegClassByHwModeAlias.td b/llvm/test/TableGen/RegClassByHwModeAlias.td
new file mode 100644
index 0000000000000..726bd3a0a5a49
--- /dev/null
+++ b/llvm/test/TableGen/RegClassByHwModeAlias.td
@@ -0,0 +1,48 @@
+// RUN: llvm-tblgen -gen-asm-writer  -I %S -I %p/../../include %s -o - | FileCheck %s
+
+include "Common/RegClassByHwModeCommon.td"
+
+def IsPtrY : Predicate<"Subtarget->isPtrY()">;
+defvar PtrX = DefaultMode;
+def PtrY : HwMode<[IsPtrY]>;
+
+// Define more restrictive subset classes to check that those are handled.
+def EvenXRegs : RegisterClass<"MyTarget", [i64], 64, (add X0, X2, X4, X6)>;
+def EvenYRegs : RegisterClass<"MyTarget", [i64], 64, (add Y0, Y2, Y4, Y6)>;
+def PtrRC : RegClassByHwMode<[PtrX, PtrY], [XRegs, YRegs]>;
+def EvenPtrRC : RegClassByHwMode<[PtrX, PtrY], [EvenXRegs, EvenYRegs]>;
+
+def TEST_XREG : TestInstruction {
+  let OutOperandList = (outs XRegs:$dst);
+  let InOperandList = (ins XRegs:$src);
+  let AsmString = "t_x $dst, $src";
+  let opcode = 0;
+}
+def TEST_PTR : TestInstruction {
+  let OutOperandList = (outs PtrRC:$dst);
+  let InOperandList = (ins PtrRC:$src);
+  let AsmString = "t_ptr $dst, $src";
+  let opcode = 0;
+}
+
+def MY_T_X : InstAlias<"t_x $src", (TEST_XREG X0, XRegs:$src)>;
+def MY_T_X_EVEN : InstAlias<"t_x.even $src", (TEST_XREG EvenXRegs:$dst, EvenXRegs:$src)>;
+
+// TODO: Can't use a fixed register for this instruction, would need RegisterByHwMode.
+// def MY_T_PTR : InstAlias<"t_ptr $src", (TEST_PTR X0, XRegs:$src)>;
+def MY_T_PTR_EVEN : InstAlias<"t_ptr.even $src", (TEST_PTR EvenPtrRC:$dst, EvenPtrRC:$src)>;
+
+// CHECK-LABEL: static const AliasPatternCond Conds[] = {
+// CHECK-NEXT:    // (TEST_PTR EvenPtrRC:$dst, EvenPtrRC:$src) - 0
+// CHECK-NEXT:    {AliasPatternCond::K_RegClassByHwMode, MyTarget::EvenPtrRC},
+// CHECK-NEXT:    {AliasPatternCond::K_RegClassByHwMode, MyTarget::EvenPtrRC},
+// CHECK-NEXT:    // (TEST_XREG X0, XRegs:$src) - 2
+// CHECK-NEXT:    {AliasPatternCond::K_Reg, MyTarget::X0},
+// CHECK-NEXT:    {AliasPatternCond::K_RegClass, MyTarget::XRegsRegClassID},
+// CHECK-NEXT:    // (TEST_XREG EvenXRegs:$dst, EvenXRegs:$src) - 4
+// CHECK-NEXT:    {AliasPatternCond::K_RegClass, MyTarget::EvenXRegsRegClassID},
+// CHECK-NEXT:    {AliasPatternCond::K_RegClass, MyTarget::EvenXRegsRegClassID},
+// CHECK-NEXT:  };
+
+def MyTargetISA : InstrInfo;
+def MyTarget : Target { let InstructionSet = MyTargetISA; }
diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
index 8901ecb7210a7..edca87504a2f7 100644
--- a/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -943,17 +943,21 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
             }
           }
 
-          if (Rec->isSubClassOf("RegisterOperand"))
-            Rec = Rec->getValueAsDef("RegClass");
-          if (Rec->isSubClassOf("RegisterClassLike")) {
+          if (Target.getAsRegClassLike(Rec)) {
             if (!IAP.isOpMapped(ROName)) {
               IAP.addOperand(ROName, MIOpNum, PrintMethodIdx);
-              const Record *R = CGA.ResultOperands[i].getRecord();
-              if (R->isSubClassOf("RegisterOperand"))
-                R = R->getValueAsDef("RegClass");
-              IAP.addCond(std::string(
-                  formatv("AliasPatternCond::K_RegClass, {}::{}RegClassID",
-                          Namespace, R->getName())));
+              const Record *R =
+                  Target.getAsRegClassLike(CGA.ResultOperands[i].getRecord());
+              assert(R && "Not a valid register class?");
+              if (R->isSubClassOf("RegClassByHwMode")) {
+                IAP.addCond(std::string(
+                    formatv("AliasPatternCond::K_RegClassByHwMode, {}::{}",
+                            Namespace, R->getName())));
+              } else {
+                IAP.addCond(std::string(
+                    formatv("AliasPatternCond::K_RegClass, {}::{}RegClassID",
+                            Namespace, R->getName())));
+              }
             } else {
               IAP.addCond(std::string(formatv("AliasPatternCond::K_TiedReg, {}",
                                               IAP.getOpIndex(ROName))));

``````````

</details>


https://github.com/llvm/llvm-project/pull/171264


More information about the llvm-commits mailing list