[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