[llvm-branch-commits] [TableGen] Support HwMode registers in CompressInstEmitter (PR #203599)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Jun 12 11:04:04 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-risc-v

Author: Alexander Richardson (arichardson)

<details>
<summary>Changes</summary>

This patch introduces a small helper (HwModePredicates) in CodeGenHwModes
to resolve HwModeSelect records (like RegisterByHwMode/RegClassByHwMode)
using subtarget features.

If all the predicates ensure that a specific register class is selected
(or lack of all of them results in DefaultMode), we can correctly validate
compress patterns involving HwMode-dependent registers and types.
This allows using a single instruction for RVY C_ADDI4SPN/C_ADDI16SP
instead of having to duplicate it for both modes (which was the previous
approach).

Let me know if you think this complexity is worth adding or if I should
just use the duplicated instructions approach.

As you can probably tell, the `struct HwModePredicates` is fully AI
generated, but if this approach sounds good I'll clean it up and see if it
can be simplified futher.

Assisted-by: Gemini


---

Patch is 53.16 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/203599.diff


13 Files Affected:

- (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (-6) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoC.td (+8-14) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+6-4) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoY.td (+2-29) 
- (modified) llvm/test/MC/RISCV/rvy/rvyc-valid-addi.s (+4-6) 
- (modified) llvm/test/TableGen/RegClassByHwModeCompressPat.td (+106-1) 
- (added) llvm/test/TableGen/RegClassByHwModeCompressPat4Modes.td (+116) 
- (added) llvm/test/TableGen/RegClassByHwModeCompressPatError.td (+92) 
- (modified) llvm/utils/TableGen/Common/CodeGenHwModes.cpp (+209) 
- (modified) llvm/utils/TableGen/Common/CodeGenHwModes.h (+10) 
- (modified) llvm/utils/TableGen/Common/SubtargetFeatureInfo.cpp (+43) 
- (modified) llvm/utils/TableGen/Common/SubtargetFeatureInfo.h (+20) 
- (modified) llvm/utils/TableGen/CompressInstEmitter.cpp (+51-63) 


``````````diff
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index c7dbdcd5fab78..6afd894ada7ce 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -115,12 +115,6 @@ static DecodeStatus DecodeGPRX1RegisterClass(MCInst &Inst,
   return MCDisassembler::Success;
 }
 
-static DecodeStatus DecodeSP_XRegisterClass(MCInst &Inst,
-                                            const MCDisassembler *Decoder) {
-  Inst.addOperand(MCOperand::createReg(RISCV::X2));
-  return MCDisassembler::Success;
-}
-
 static DecodeStatus DecodeSP_XRegisterClass(MCInst &Inst, uint64_t RegNo,
                                             uint32_t Address,
                                             const MCDisassembler *Decoder) {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
index b3b28cfc17813..8b0eb3a2e2d19 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
@@ -266,13 +266,9 @@ class CA_ALU<bits<6> funct6, bits<2> funct2, string OpcodeStr>
 
 let Predicates = [HasStdExtZca] in {
 
-// Ideally we would reuse C_ADDI16SP for StdExtY, but since the CompressPat
-// uses instructions with different register classes (ADDI vs YADDI) we can't
-// do this yet. Instead, add a variant of the instruction in RISCVInstrInfoY.td.
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0,
-    append Predicates = [NotStdExtYCapMode] in
-def C_ADDI4SPN : RVInst16CIW<0b000, OPC_C0, (outs GPRC:$rd),
-                             (ins SP_X:$rs1, uimm10_lsb00nonzero:$imm),
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+def C_ADDI4SPN : RVInst16CIW<0b000, OPC_C0, (outs BasePtrCRegClass:$rd),
+                             (ins SP:$rs1, uimm10_lsb00nonzero:$imm),
                              "c.addi4spn", "$rd, $rs1, $imm">,
                              Sched<[WriteIALU, ReadIALU]> {
   bits<0> rs1;
@@ -374,13 +370,9 @@ def C_LI : RVInst16CI<0b010, OPC_C1, (outs GPR:$rd), (ins simm6:$imm),
                       "c.li", "$rd, $imm">,
            Sched<[WriteIALU]>;
 
-// Ideally we would reuse C_ADDI16SP for StdExtY, but since the CompressPat
-// uses instructions with different register classes (ADDI vs YADDI) we can't
-// do this yet. Instead, add a variant of the instruction in RISCVInstrInfoY.td.
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0,
-    append Predicates = [NotStdExtYCapMode] in
-def C_ADDI16SP : RVInst16CI<0b011, OPC_C1, (outs SP_X:$rd_wb),
-                            (ins SP_X:$rd, simm10_lsb0000nonzero:$imm),
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+def C_ADDI16SP : RVInst16CI<0b011, OPC_C1, (outs SP:$rd_wb),
+                            (ins SP:$rd, simm10_lsb0000nonzero:$imm),
                             "c.addi16sp", "$rd, $imm">,
                  Sched<[WriteIALU, ReadIALU]> {
   let Constraints = "$rd = $rd_wb";
@@ -753,6 +745,7 @@ def : InstAlias<".insn_cj $opcode, $funct3, $imm11",
 
 // Quadrant 0
 let Predicates = [HasStdExtZca] in {
+let append Predicates = [NotStdExtYCapMode] in
 def : CompressPat<(ADDI GPRC:$rd, SP_X:$rs1, uimm10_lsb00nonzero:$imm),
                   (C_ADDI4SPN GPRC:$rd, SP_X:$rs1, uimm10_lsb00nonzero:$imm)>;
 
@@ -799,6 +792,7 @@ def : CompressPat<(ADDIW GPRNoX0:$rs1, GPRNoX0:$rs1, simm6:$imm),
 
 def : CompressPat<(ADDI GPRNoX0:$rd, X0, simm6:$imm),
                   (C_LI GPRNoX0:$rd, simm6:$imm)>;
+let append Predicates = [NotStdExtYCapMode] in
 def : CompressPat<(ADDI X2, X2, simm10_lsb0000nonzero:$imm),
                   (C_ADDI16SP X2, simm10_lsb0000nonzero:$imm)>;
 def : CompressPat<(LUI GPRNoX0X2:$rd, c_lui_imm:$imm),
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index c00acbcb6f40c..8866a1f6aa4d9 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -623,7 +623,7 @@ class QCIMVCCI<bits<3> funct3, string opcodestr, DAGOperand immType>
                opcodestr, "$rd, $rs1, $imm, $rs3">,
       Sched<[WriteIALU, ReadIALU, ReadIALU, ReadIALU]> {
   bits<5> imm;
-  
+
   let Constraints = "$rd = $rd_wb";
   let rs2 = imm;
 }
@@ -1992,10 +1992,12 @@ def : CompressPat<(QC_E_ANDI GPRC:$rs1, GPRC:$rs1, simm6:$imm),
                   (C_ANDI GPRC:$rs1, simm6:$imm)>;
 def : CompressPat<(QC_E_ADDI GPRNoX0:$rs1, GPRNoX0:$rs2, 0),
                   (C_MV GPRNoX0:$rs1, GPRNoX0:$rs2)>;
+let append Predicates = [NotStdExtYCapMode] in {
 def : CompressPat<(QC_E_ADDAI X2, simm10_lsb0000nonzero:$imm),
                   (C_ADDI16SP X2, simm10_lsb0000nonzero:$imm)>;
 def : CompressPat<(QC_E_ADDI X2, X2, simm10_lsb0000nonzero:$imm),
                   (C_ADDI16SP X2, simm10_lsb0000nonzero:$imm)>;
+}
 
 def : CompressPat<(QC_E_ADDI GPRNoX0:$rs1, GPRNoX0:$rs2, simm12_lo:$imm),
                   (ADDI GPRNoX0:$rs1, GPRNoX0:$rs2, simm12_lo:$imm)>;
@@ -2066,7 +2068,7 @@ def : CompressPat<(QC_E_BLTUI GPRNoX0:$rs1, uimm5nonzero:$imm5, bare_simm13_lsb0
 // How the bug happens is:
 // - QC.E.LI is parsed with a bare symbol, which is valid + expected, and can
 //   be handled by fixups/relocations.
-// - Compression turns this into a `C.LI` because the `simm6` 
+// - Compression turns this into a `C.LI` because the `simm6`
 //   MCOperandPredicate accepts bare symbols.
 // - Binary Code emission didn't know how to create a fixup for a CI-type
 //   instruction containing a bare symbol.
@@ -2077,7 +2079,7 @@ def : CompressPat<(QC_E_BLTUI GPRNoX0:$rs1, uimm5nonzero:$imm5, bare_simm13_lsb0
 //
 // This is good enough for emitting objects, but doesn't work for emitting
 // assembly. Emitting assembly is why we need the following Hacks.
-// 
+//
 // Emitting an instruction to assembly proceeds as:
 // - Compression (in emitInstruction)
 // - Decompression (in RISCVInstPrinter::printInst)
@@ -2086,7 +2088,7 @@ def : CompressPat<(QC_E_BLTUI GPRNoX0:$rs1, uimm5nonzero:$imm5, bare_simm13_lsb0
 // So in the case of `QC.E.LI` with a bare symbol, first it is compressed to
 // `C.LI` with a bare symbol, and then it is decompressed to `ADDI` with a bare
 // symbol for printing, which is printed via an alias as `li <reg>, <symbol>`.
-// Both the decompression and the alias use the MCOperandPredicate from 
+// Both the decompression and the alias use the MCOperandPredicate from
 // `simm12`, which accepts bare symbols.
 //
 // The problem here is that `li <reg>, <symbol>` fails to parse, because the
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoY.td b/llvm/lib/Target/RISCV/RISCVInstrInfoY.td
index 4f588a4a7c695..95554cebe8731 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoY.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoY.td
@@ -220,37 +220,10 @@ def : CompressPat<(SY YGPR:$rs2, SPMem:$rs1, uimm9_lsb000:$imm),
 } // Predicates = [HasStdExtZca, IsStdExtYCapMode, IsRV32]
 
 let Predicates = [HasStdExtZca, IsStdExtYCapMode] in {
-// Ideally, we would reuse C_ADDI4SPN/C_ADDI16SP with SP:$rs1, but since the
-// CompressPat uses instructions with different register classes (ADDI vs YADDI)
-// we can't do this until tablegen resolves predicates in CompressPat.
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0, DecoderNamespace = "RVY" in {
-def C_YADDI4SPN : RVInst16CIW<0b000, OPC_C0, (outs YGPRC:$rd),
-                              (ins SP_Y:$rs1, uimm10_lsb00nonzero:$imm),
-                              "c.addi4spn", "$rd, $rs1, $imm">,
-                              Sched<[WriteIALU, ReadIALU]> {
-  bits<0> rs1;
-  let Inst{12-11} = imm{5-4};
-  let Inst{10-7} = imm{9-6};
-  let Inst{6} = imm{2};
-  let Inst{5} = imm{3};
-}
-def C_YADDI16SP : RVInst16CI<0b011, OPC_C1, (outs SP_Y:$rd_wb),
-                             (ins SP_Y:$rd, simm10_lsb0000nonzero:$imm),
-                             "c.addi16sp", "$rd, $imm">,
-                  Sched<[WriteIALU, ReadIALU]> {
-  let Constraints = "$rd = $rd_wb";
-  let rd = 2;
-  let Inst{12} = imm{9};
-  let Inst{6} = imm{4};
-  let Inst{5} = imm{6};
-  let Inst{4-3} = imm{8-7};
-  let Inst{2} = imm{5};
-}
-} // hasSideEffects = 0, mayLoad = 0, mayStore = 0, DecoderNamespace = "RVY"
 def : CompressPat<(YADDI YGPRC:$rd, SP_Y:$rs1, uimm10_lsb00nonzero:$imm),
-                  (C_YADDI4SPN YGPRC:$rd, SP_Y:$rs1, uimm10_lsb00nonzero:$imm)>;
+                  (C_ADDI4SPN YGPRC:$rd, SP_Y:$rs1, uimm10_lsb00nonzero:$imm)>;
 def : CompressPat<(YADDI X2_Y, X2_Y, simm10_lsb0000nonzero:$imm),
-                  (C_YADDI16SP X2_Y, simm10_lsb0000nonzero:$imm)>;
+                  (C_ADDI16SP X2_Y, simm10_lsb0000nonzero:$imm)>;
 } // Predicates = [HasStdExtZca, IsStdExtYCapMode]
 
 let Predicates = [HasStdExtZca, IsStdExtYCapMode, IsRV64] in {
diff --git a/llvm/test/MC/RISCV/rvy/rvyc-valid-addi.s b/llvm/test/MC/RISCV/rvy/rvyc-valid-addi.s
index 88cf60884c966..bcbd67169da94 100644
--- a/llvm/test/MC/RISCV/rvy/rvyc-valid-addi.s
+++ b/llvm/test/MC/RISCV/rvy/rvyc-valid-addi.s
@@ -20,8 +20,7 @@
 c.addi4spn a0, sp, 12
 // CHECK-ASM-AND-OBJ: c.addi4spn	a0, sp, 12
 // CHECK-ASM-SAME: # encoding: [0x68,0x00]
-// CHECK-INT-NEXT: # <MCInst #[[#]] C_ADDI4SPN{{$}}
-// CHECK-CAP-NEXT: # <MCInst #[[#]] C_YADDI4SPN{{$}}
+// CHECK-ASM-NEXT: # <MCInst #[[#]] C_ADDI4SPN{{$}}
 // CHECK-INT-NEXT: #  <MCOperand Reg:X10>
 // CHECK-CAP-NEXT: #  <MCOperand Reg:X10_Y>
 // CHECK-INT-NEXT: #  <MCOperand Reg:X2>
@@ -31,8 +30,7 @@ c.addi4spn a0, sp, 12
 c.addi16sp sp, 16
 // CHECK-ASM-AND-OBJ: c.addi16sp	sp, 16
 // CHECK-ASM-SAME: # encoding: [0x41,0x61]
-// CHECK-INT-NEXT: # <MCInst #[[#]] C_ADDI16SP{{$}}
-// CHECK-CAP-NEXT: # <MCInst #[[#]] C_YADDI16SP{{$}}
+// CHECK-ASM-NEXT: # <MCInst #[[#]] C_ADDI16SP{{$}}
 // CHECK-INT-NEXT: #  <MCOperand Reg:X2>
 // CHECK-CAP-NEXT: #  <MCOperand Reg:X2_Y>
 // CHECK-INT-NEXT: #  <MCOperand Reg:X2>
@@ -56,7 +54,7 @@ yaddi a0, sp, 12
 // CHECK-CAP-ASM-AND-OBJ: c.addi4spn	a0, sp, 12
 // CHECK-CAP-SAME: # encoding: [0x68,0x00]
 // CHECK-INT-NEXT: # <MCInst #[[#]] YADDI{{$}}
-// CHECK-CAP-NEXT: # <MCInst #[[#]] C_YADDI4SPN{{$}}
+// CHECK-CAP-NEXT: # <MCInst #[[#]] C_ADDI4SPN{{$}}
 // CHECK-ASM-NEXT: #  <MCOperand Reg:X10_Y>
 // CHECK-ASM-NEXT: #  <MCOperand Reg:X2_Y>
 // CHECK-ASM-NEXT: #  <MCOperand Imm:12>>
@@ -67,7 +65,7 @@ yaddi sp, sp, 16
 // CHECK-CAP-ASM-AND-OBJ: c.addi16sp	sp, 16
 // CHECK-CAP-SAME: # encoding: [0x41,0x61]
 // CHECK-INT-NEXT: # <MCInst #[[#]] YADDI{{$}}
-// CHECK-CAP-NEXT: # <MCInst #[[#]] C_YADDI16SP{{$}}
+// CHECK-CAP-NEXT: # <MCInst #[[#]] C_ADDI16SP{{$}}
 // CHECK-ASM-NEXT: #  <MCOperand Reg:X2_Y>
 // CHECK-ASM-NEXT: #  <MCOperand Reg:X2_Y>
 // CHECK-ASM-NEXT: #  <MCOperand Imm:16>>
diff --git a/llvm/test/TableGen/RegClassByHwModeCompressPat.td b/llvm/test/TableGen/RegClassByHwModeCompressPat.td
index cbe686848c4c4..4837851f2a8e7 100644
--- a/llvm/test/TableGen/RegClassByHwModeCompressPat.td
+++ b/llvm/test/TableGen/RegClassByHwModeCompressPat.td
@@ -2,7 +2,12 @@
 
 include "Common/RegClassByHwModeCommon.td"
 
-def IsPtr64 : Predicate<"Subtarget->isPtr64()">;
+def FeaturePtr64 : SubtargetFeature<"ptr64", "IsPtr64", "true", "Ptr64 mode">;
+
+def IsPtr64 : Predicate<"Subtarget->isPtr64()">,
+              AssemblerPredicate<(all_of FeaturePtr64)>;
+def NotPtr64 : Predicate<"!Subtarget->isPtr64()">,
+               AssemblerPredicate<(all_of (not FeaturePtr64))>;
 defvar Ptr32 = DefaultMode;
 def Ptr64 : HwMode<[IsPtr64]>;
 def PtrRC : RegClassByHwMode<[Ptr32, Ptr64], [XRegs, YRegs]>;
@@ -38,6 +43,13 @@ def X_MOV_TIED : TestInstruction {
   let Size = 1;
 }
 
+def Y_MOV : TestInstruction {
+  let OutOperandList = (outs YRegs:$dst);
+  let InOperandList = (ins YRegs:$src);
+  let AsmString = "y_mov $dst, $src";
+  let opcode = 5;
+}
+
 def PTR_MOV : TestInstruction {
   let OutOperandList = (outs PtrRC:$dst);
   let InOperandList = (ins PtrRC:$src);
@@ -81,6 +93,17 @@ def : CompressPat<(PTR_MOV PtrRC:$dst, PtrRC:$dst),
 def : CompressPat<(PTR_MOV PtrRC:$dst, PtrRC:$src),
                   (PTR_MOV_SMALL PtrRC:$dst, PtrRC:$src)>;
 
+// Test compression/uncompression when HwMode can be resolved by pattern predicates.
+// X_MOV (XRegs) -> PTR_MOV_SMALL (PtrRC) is valid in 32-bit mode (NotPtr64).
+let Predicates = [NotPtr64] in
+def : CompressPat<(X_MOV XRegs:$dst, XRegs:$src),
+                  (PTR_MOV_SMALL XRegs:$dst, XRegs:$src)>;
+
+// Y_MOV (YRegs) -> PTR_MOV_SMALL (PtrRC) is valid in 64-bit mode (IsPtr64).
+let Predicates = [IsPtr64] in
+def : CompressPat<(Y_MOV YRegs:$dst, YRegs:$src),
+                  (PTR_MOV_SMALL YRegs:$dst, YRegs:$src)>;
+
 // CHECK:     static bool compressInst(MCInst &OutInst,
 // CHECK-NEXT:                          const MCInst &MI,
 // CHECK-NEXT:                          const MCSubtargetInfo &STI) {
@@ -165,8 +188,39 @@ def : CompressPat<(PTR_MOV PtrRC:$dst, PtrRC:$src),
 // CHECK-NEXT:       OutInst.setLoc(MI.getLoc());
 // CHECK-NEXT:       return true;
 // CHECK-NEXT:     } // if
+// CHECK-NEXT:     if (!STI.getFeatureBits()[MyTarget::FeaturePtr64] &&
+// CHECK-NEXT:         MI.getOperand(0).isReg() &&
+// CHECK-NEXT:         MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(0).getReg()) &&
+// CHECK-NEXT:         MI.getOperand(1).isReg() &&
+// CHECK-NEXT:         MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(1).getReg())) {
+// CHECK-NEXT:       // ptr_mov.small $dst, $src
+// CHECK-NEXT:       OutInst.setOpcode(MyTarget::PTR_MOV_SMALL);
+// CHECK-NEXT:       // Operand: dst
+// CHECK-NEXT:       OutInst.addOperand(MI.getOperand(0));
+// CHECK-NEXT:       // Operand: src
+// CHECK-NEXT:       OutInst.addOperand(MI.getOperand(1));
+// CHECK-NEXT:       OutInst.setLoc(MI.getLoc());
+// CHECK-NEXT:       return true;
+// CHECK-NEXT:     } // if
 // CHECK-NEXT:     break;
 // CHECK-NEXT:   } // case X_MOV
+// CHECK-NEXT:   case MyTarget::Y_MOV: {
+// CHECK-NEXT:     if (STI.getFeatureBits()[MyTarget::FeaturePtr64] &&
+// CHECK-NEXT:         MI.getOperand(0).isReg() &&
+// CHECK-NEXT:         MyTargetMCRegisterClasses[MyTarget::YRegsRegClassID].contains(MI.getOperand(0).getReg()) &&
+// CHECK-NEXT:         MI.getOperand(1).isReg() &&
+// CHECK-NEXT:         MyTargetMCRegisterClasses[MyTarget::YRegsRegClassID].contains(MI.getOperand(1).getReg())) {
+// CHECK-NEXT:       // ptr_mov.small $dst, $src
+// CHECK-NEXT:       OutInst.setOpcode(MyTarget::PTR_MOV_SMALL);
+// CHECK-NEXT:       // Operand: dst
+// CHECK-NEXT:       OutInst.addOperand(MI.getOperand(0));
+// CHECK-NEXT:       // Operand: src
+// CHECK-NEXT:       OutInst.addOperand(MI.getOperand(1));
+// CHECK-NEXT:       OutInst.setLoc(MI.getLoc());
+// CHECK-NEXT:       return true;
+// CHECK-NEXT:     } // if
+// CHECK-NEXT:     break;
+// CHECK-NEXT:   } // case Y_MOV
 // CHECK-NEXT:   } // switch
 // CHECK-NEXT:   return false;
 // CHECK-NEXT: }
@@ -191,6 +245,34 @@ def : CompressPat<(PTR_MOV PtrRC:$dst, PtrRC:$src),
 // CHECK-NEXT:       OutInst.setLoc(MI.getLoc());
 // CHECK-NEXT:       return true;
 // CHECK-NEXT:     } // if
+// CHECK-NEXT:     if (!STI.getFeatureBits()[MyTarget::FeaturePtr64] &&
+// CHECK-NEXT:         MI.getOperand(0).isReg() &&
+// CHECK-NEXT:         MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(0).getReg()) &&
+// CHECK-NEXT:         MI.getOperand(1).isReg() &&
+// CHECK-NEXT:         MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(1).getReg())) {
+// CHECK-NEXT:       // x_mov $dst, $src
+// CHECK-NEXT:       OutInst.setOpcode(MyTarget::X_MOV);
+// CHECK-NEXT:       // Operand: dst
+// CHECK-NEXT:       OutInst.addOperand(MI.getOperand(0));
+// CHECK-NEXT:       // Operand: src
+// CHECK-NEXT:       OutInst.addOperand(MI.getOperand(1));
+// CHECK-NEXT:       OutInst.setLoc(MI.getLoc());
+// CHECK-NEXT:       return true;
+// CHECK-NEXT:     } // if
+// CHECK-NEXT:     if (STI.getFeatureBits()[MyTarget::FeaturePtr64] &&
+// CHECK-NEXT:         MI.getOperand(0).isReg() &&
+// CHECK-NEXT:         MyTargetMCRegisterClasses[MyTarget::YRegsRegClassID].contains(MI.getOperand(0).getReg()) &&
+// CHECK-NEXT:         MI.getOperand(1).isReg() &&
+// CHECK-NEXT:         MyTargetMCRegisterClasses[MyTarget::YRegsRegClassID].contains(MI.getOperand(1).getReg())) {
+// CHECK-NEXT:       // y_mov $dst, $src
+// CHECK-NEXT:       OutInst.setOpcode(MyTarget::Y_MOV);
+// CHECK-NEXT:       // Operand: dst
+// CHECK-NEXT:       OutInst.addOperand(MI.getOperand(0));
+// CHECK-NEXT:       // Operand: src
+// CHECK-NEXT:       OutInst.addOperand(MI.getOperand(1));
+// CHECK-NEXT:       OutInst.setLoc(MI.getLoc());
+// CHECK-NEXT:       return true;
+// CHECK-NEXT:     } // if
 // CHECK-NEXT:     break;
 // CHECK-NEXT:   } // case PTR_MOV_SMALL
 // CHECK-NEXT:   case MyTarget::PTR_MOV_TIED: {
@@ -308,6 +390,16 @@ def : CompressPat<(PTR_MOV PtrRC:$dst, PtrRC:$src),
 // CHECK-NEXT:     break;
 // CHECK-NEXT:   } // case PTR_MOV
 // CHECK-NEXT:   case MyTarget::X_MOV: {
+// CHECK-NEXT:     if (!STI.getFeatureBits()[MyTarget::FeaturePtr64] &&
+// CHECK-NEXT:         MI.getOperand(0).isReg() && MI.getOperand(0).getReg().isPhysical() &&
+// CHECK-NEXT:         MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(0).getReg()) &&
+// CHECK-NEXT:         MI.getOperand(1).isReg() && MI.getOperand(1).getReg().isPhysical() &&
+// CHECK-NEXT:         MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(1).getReg())) {
+// CHECK-NEXT:       // ptr_mov.small $dst, $src
+// CHECK-NEXT:       // Operand: dst
+// CHECK-NEXT:       // Operand: src
+// CHECK-NEXT:       return true;
+// CHECK-NEXT:     } // if
 // CHECK-NEXT:     if (MI.getOperand(0).isReg() && MI.getOperand(0).getReg().isPhysical() &&
 // CHECK-NEXT:         MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(0).getReg()) &&
 // CHECK-NEXT:         MI.getOperand(1).isReg() && MI.getOperand(1).getReg().isPhysical() &&
@@ -336,6 +428,19 @@ def : CompressPat<(PTR_MOV PtrRC:$dst, PtrRC:$src),
 // CHECK-NEXT:     } // if
 // CHECK-NEXT:     break;
 // CHECK-NEXT:   } // case X_MOV
+// CHECK-NEXT:   case MyTarget::Y_MOV: {
+// CHECK-NEXT:     if (STI.getFeatureBits()[MyTarget::FeaturePtr64] &&
+// CHECK-NEXT:         MI.getOperand(0).isReg() && MI.getOperand(0).getReg().isPhysical() &&
+// CHECK-NEXT:         MyTargetMCRegisterClasses[MyTarget::YRegsRegClassID].contains(MI.getOperand(0).getReg()) &&
+// CHECK-NEXT:         MI.getOperand(1).isReg() && MI.getOperand(1).getReg().isPhysical() &&
+// CHECK-NEXT:         MyTargetMCRegisterClasses[MyTarget::YRegsRegClassID].contains(MI.getOperand(1).getReg())) {
+// CHECK-NEXT:       // ptr_mov.small $dst, $src
+// CHECK-NEXT:       // Operand: dst
+// CHECK-NEXT:       // Operand: src
+// CHECK-NEXT:       return true;
+// CHECK-NEXT:     } // if
+// CHECK-NEXT:     break;
+// CHECK-NEXT:   } // case Y_MOV
 // CHECK-NEXT:   } // switch
 // CHECK-NEXT:   return false;
 // CHECK-NEXT: }
diff --git a/llvm/test/TableGen/RegClassByHwModeCompressPat4Modes.td b/llvm/test/TableGen/RegClassByHwModeCompressPat4Modes.td
new file mode 100644
index 0000000000000..d652973357cb8
--- /dev/null
+++ b/llvm/test/TableGen/RegClassByHwModeCompressPat4Modes.td
@@ -0,0 +1,116 @@
+// RUN: llvm-tblgen --gen-compress-inst-emitter -I %p/../../include -I %S %s -o - | FileCheck %s
+
+include "Common/RegClassByHwModeCommon.td"
+
+// Define features
+def Feature64Bit : SubtargetFeature<"64bit", "Is64Bit", "true", "64-bit mode">;
+def FeatureCap : SubtargetFeature<"cap", "IsCap", "true", "Capability mode">;
+
+// Define predicates
+def Is64Bit : Predicate<"Subtarget->is64Bit()">,
+              AssemblerPredicate<(all_of Feature64Bit)>;
+def Not64Bit : Predicate<"!Subtarget->is64Bit()">,
+               AssemblerPredicate<(all_of (not Feature64Bit))>;
+def IsCap : Predicate<"Subtarget->isCap()">,
+            AssemblerPredicate<(all_of FeatureCap)>;
+def NotCap : Predicate<"!Subtarget->isCap()">,
+             AssemblerPredicate<(all_of (not FeatureCap))>;
+
+// Define 4 modes (similar to RISC-V RV32I, RV64I, RV32Y, RV64Y)
+def Mode32I : HwMode<[Not64Bit, NotCap]>;
+def Mode64I : HwMode<[Is64Bit, NotCap]>;
+def Mode32C : HwMode<[Not64Bit, IsCap]>;
+def Mode64C : HwMode<[Is64Bit, IsCap]>;
+
+// Define mode-dependent register class (SP-like)
+// Resolves to XRegs in Integer modes, and YRegs in Capability modes
+def PtrRC : RegClassByHwMode<[Mode32I,...
[truncated]

``````````

</details>


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


More information about the llvm-branch-commits mailing list