[llvm-branch-commits] [RISC-V][MC][RVY] Add support for RVY loads/stores (PR #213417)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Jul 31 23:53:33 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 adds supports for all new RVY loads/stores (capability-wide
versions: ly/sy instructions). Additionally, existing I/Zc* loads and
stores are updated to be mode-dependent, using either a YLEN register or
a XLEN register as the base.
In the former case loads/stores are authorized by that register,
and in the latter (compatibility mode), the loads/stores keep using an
address but are authorized by the DDC CSR. The assembler mnemonics are
the same in both cases. Prior to the standardization process CHERI
assembly used c-prefixed register names for capabilities, so we had the
following syntax:

```
lw x4, 0(c3) # capability mode: use new `CLW` instruction
lw x4, 0(x3) # integer mode: use existing `LW` instruction
```

During the standardization this was changed to keep the same register
name in both modes, so now we use `lw x4, 0(x3)` in both modes.

This allows using the RegClassByHwMode feature to reuse the same MC
instruction but with a different operand type depending on the HwMode.
The downstream fork had duplicated definitions which meant a lot of
switch statements now needed to handle both MCInsts. This approach
using HwMode should be much more maintainable and only introduces a
minor diff compared to what we had downstream.
This will also make it much easier adding support for RVY versions of
other extensions such as vector, since we just need to change out the
`GPRMem` operand with `PtrMem`.

This commit also adds assembler-level support for the RVI-compatible
mode of RVY where all base pointers are interpreted as XLEN values
instead of YLEN values using an internal xllvmrvyipm extension (until
the final toolchain convention has been ratified).


---

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


30 Files Affected:

- (modified) clang/test/Driver/print-supported-extensions-riscv.c (+1) 
- (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+61-4) 
- (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+40-5) 
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp (+4-1) 
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+2) 
- (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+19-3) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.cpp (+2) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+34-7) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoC.td (+9-7) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoD.td (+3) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoF.td (+3) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoQ.td (+3) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+8-8) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoY.td (+93-1) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZc.td (+5-5) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td (+5) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZilsd.td (+3) 
- (modified) llvm/lib/Target/RISCV/RISCVMakeCompressible.cpp (+2-1) 
- (modified) llvm/lib/Target/RISCV/RISCVRegisterInfo.td (+81-41) 
- (modified) llvm/lib/Target/RISCV/RISCVSchedule.td (+2) 
- (modified) llvm/lib/TargetParser/RISCVISAInfo.cpp (+13-9) 
- (modified) llvm/test/CodeGen/RISCV/features-info.ll (+1) 
- (added) llvm/test/MC/RISCV/rvy/rvy-invalid-load-store.s (+93) 
- (added) llvm/test/MC/RISCV/rvy/rvy-valid-load-store-64.s (+49) 
- (added) llvm/test/MC/RISCV/rvy/rvy-valid-load-store.s (+199) 
- (added) llvm/test/MC/RISCV/rvy/rvyc-invalid-load-store.s (+158) 
- (added) llvm/test/MC/RISCV/rvy/rvyc-valid-load-store-64.s (+89) 
- (added) llvm/test/MC/RISCV/rvy/rvyc-valid-load-store.s (+465) 
- (modified) llvm/unittests/Target/RISCV/RISCVBaseInfoTest.cpp (+3) 
- (modified) llvm/unittests/TargetParser/RISCVISAInfoTest.cpp (+33) 


``````````diff
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index c1abb1876d64a..5941e3f5098aa 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -179,6 +179,7 @@
 // CHECK-NEXT:     xcvmac               1.0       'XCVmac' (CORE-V Multiply-Accumulate)
 // CHECK-NEXT:     xcvmem               1.0       'XCVmem' (CORE-V Post-incrementing Load & Store)
 // CHECK-NEXT:     xcvsimd              1.0       'XCVsimd' (CORE-V SIMD ALU)
+// CHECK-NEXT:     xllvmrvyipm          1.0       'XLLVMRVYIPM' (Using RVY Base ISA with Integral Pointer (Compatibility) Mode)
 // CHECK-NEXT:     xmipscbop            1.0       'XMIPSCBOP' (MIPS Software Prefetch)
 // CHECK-NEXT:     xmipscmov            1.0       'XMIPSCMov' (MIPS conditional move instruction (mips.ccmov))
 // CHECK-NEXT:     xmipsexectl          1.0       'XMIPSEXECTL' (MIPS execution control)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 5a9f34af2b38d..9647d51526c9b 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -519,6 +519,12 @@ struct RISCVOperand final : public MCParsedAsmOperand {
            getRISCVMCRegisterClass(RISCV::YGPRRegClassID).contains(Reg.Reg);
   }
 
+  bool isStackPtr() const {
+    return isReg() &&
+           (getRISCVMCRegisterClass(RISCV::SP_XRegClassID).contains(Reg.Reg) ||
+            getRISCVMCRegisterClass(RISCV::SP_YRegClassID).contains(Reg.Reg));
+  }
+
   bool isGPRPair() const {
     return Kind == KindTy::Register &&
            getRISCVMCRegisterClass(RISCV::GPRPairRegClassID).contains(Reg.Reg);
@@ -921,6 +927,10 @@ struct RISCVOperand final : public MCParsedAsmOperand {
 
   bool isUImm9Lsb000() const { return isUImmShifted<6, 3>(); }
 
+  bool isUImm9Lsb0000() const { return isUImmShifted<5, 4>(); }
+
+  bool isUImm10Lsb0000() const { return isUImmShifted<6, 4>(); }
+
   bool isUImm14Lsb00() const { return isUImmShifted<12, 2>(); }
 
   bool isUImm10Lsb00NonZero() const {
@@ -1448,8 +1458,29 @@ static MCRegister convertFPR64ToFPR256(MCRegister Reg) {
   return Reg - RISCV::F0_D + RISCV::F0_Q2;
 }
 
+static bool regClassIsYGPR(const MCRegisterClass &RC) {
+  assert(RC.getNumRegs() > 0);
+  return getRISCVMCRegisterClass(RISCV::YGPRRegClassID).contains(*RC.begin());
+}
+
+static MatchClassKind remapRegClassByHwMode(MatchClassKind Kind, bool Purecap) {
+  // TODO: Generate this mapping automatically from TableGen.
+  switch (Kind) {
+  case MCK_RegByHwMode_BasePtrRegClass:
+    return Purecap ? MCK_YGPRNoX0 : MCK_GPR;
+  case MCK_RegByHwMode_BasePtrCRegClass:
+    return Purecap ? MCK_YGPRC : MCK_GPRC;
+  case MCK_RegByHwMode_SP:
+    return Purecap ? MCK_SP_Y : MCK_SP_X;
+  default:
+    llvm_unreachable("Unhandled RegClassByHwMode");
+  }
+}
+
 unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
-                                                    unsigned Kind) {
+                                                    unsigned MatchKind) {
+  // Convert to enum for improved debugger output.
+  MatchClassKind Kind = static_cast<MatchClassKind>(MatchKind);
   RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
   if (!Op.isReg())
     return Match_InvalidOperand;
@@ -1461,10 +1492,30 @@ unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
       getRISCVMCRegisterClass(RISCV::FPR64CRegClassID).contains(Reg);
   bool IsRegVR = getRISCVMCRegisterClass(RISCV::VRRegClassID).contains(Reg);
 
-  if (Op.isGPR() && Kind == MCK_YGPR) {
-    // GPR and capability GPR use the same register names, convert if required.
+  // In RVY mode, classes such as BasePtrRC register class should select
+  // capability registers for the base pointer operands, otherwise we use GPRs.
+  // This is not currently handled automatically by tablegen so we have to
+  // manually remap the MCK_ values and also manually handle the register
+  // restrictions (such as NoX0) for ByHwMode classes.
+  // TODO: Is there any way we could do this in tablegen automatically?
+  bool NeedManualRegClassCheck = false;
+  if (Kind > MCK_LAST_REGISTER && Kind <= MCK_LAST_REGCLASS_BY_HWMODE) {
+    bool Purecap = STI->hasFeature(RISCV::FeatureStdExtY) &&
+                   !STI->hasFeature(RISCV::FeatureVendorXLLVMRVYIPM);
+    Kind = remapRegClassByHwMode(Kind, Purecap);
+  }
+  const MCRegisterClass *CheckRC = getRegClassFromMatchKind(Kind);
+  // YGPR and GPR use the same names, remap and check them if necessary.
+  if (!Op.isYGPR() && CheckRC && regClassIsYGPR(*CheckRC)) {
+    assert(Op.isGPR() && "Can only convert GPR to YGPR");
     Op.Reg.Reg = convertGPRToYGPR(Reg);
-    return Match_Success;
+    NeedManualRegClassCheck = true;
+  }
+  if (NeedManualRegClassCheck) {
+    assert(CheckRC && "Must have a valid register class for validation");
+    if (CheckRC->contains(Op.getReg()))
+      return Match_Success;
+    return getDiagKindFromRegisterClass(Kind);
   }
   if (IsRegFPR64 && Kind == MCK_FPR256) {
     Op.Reg.Reg = convertFPR64ToFPR256(Reg);
@@ -1628,6 +1679,9 @@ std::string RISCVAsmParser::getCustomOperandDiag(unsigned MatchError) {
   case Match_InvalidUImm9Lsb000:
     return Range(0, (1 << 9) - 8,
                  "immediate must be a multiple of 8 bytes in the range");
+  case Match_InvalidUImm9Lsb0000:
+    return Range(0, (1 << 9) - 16,
+                 "immediate must be a multiple of 16 bytes in the range");
   case Match_InvalidSImm8PLI_B:
     return Range(-(1 << 7), (1 << 8) - 1);
   case Match_InvalidSImm10:
@@ -1639,6 +1693,9 @@ std::string RISCVAsmParser::getCustomOperandDiag(unsigned MatchError) {
   case Match_InvalidUImm10Lsb00NonZero:
     return Range(4, (1 << 10) - 4,
                  "immediate must be a multiple of 4 bytes in the range");
+  case Match_InvalidUImm10Lsb0000:
+    return Range(0, (1 << 10) - 16,
+                 "immediate must be a multiple of 16 bytes in the range");
   case Match_InvalidSImm10Lsb0000NonZero:
     return Range(
         -(1 << 9), (1 << 9) - 16,
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 3b3eb5195a9b4..3d384ac47e612 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -95,6 +95,8 @@ static DecodeStatus DecodeSimpleRegisterClass(MCInst &Inst, uint32_t RegNo,
 
 constexpr auto DecodeGPRRegisterClass =
     DecodeSimpleRegisterClass<RISCV::X0, 32, /*RVELimit=*/16>;
+constexpr auto DecodeYGPRRegisterClass =
+    DecodeSimpleRegisterClass<RISCV::X0_Y, 32, /*RVELimit=*/16>;
 
 static DecodeStatus DecodeGPRX1X5RegisterClass(MCInst &Inst, uint32_t RegNo,
                                                uint64_t Address,
@@ -113,20 +115,33 @@ static DecodeStatus DecodeGPRX1RegisterClass(MCInst &Inst,
   return MCDisassembler::Success;
 }
 
-static DecodeStatus DecodeSPRegisterClass(MCInst &Inst,
-                                          const MCDisassembler *Decoder) {
+static DecodeStatus DecodeSP_XRegisterClass(MCInst &Inst,
+                                            const MCDisassembler *Decoder) {
   Inst.addOperand(MCOperand::createReg(RISCV::X2));
   return MCDisassembler::Success;
 }
 
-static DecodeStatus DecodeSPRegisterClass(MCInst &Inst, uint64_t RegNo,
-                                          uint32_t Address,
-                                          const MCDisassembler *Decoder) {
+static DecodeStatus DecodeSP_XRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                            uint32_t Address,
+                                            const MCDisassembler *Decoder) {
   assert(RegNo == 2);
   Inst.addOperand(MCOperand::createReg(RISCV::X2));
   return MCDisassembler::Success;
 }
 
+static DecodeStatus DecodeSP_YRegisterClass(MCInst &Inst,
+                                            const MCDisassembler *Decoder) {
+  Inst.addOperand(MCOperand::createReg(RISCV::X2_Y));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeSP_YRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                            uint32_t Address,
+                                            const MCDisassembler *Decoder) {
+  assert(RegNo == 2);
+  return DecodeSP_YRegisterClass(Inst, Decoder);
+}
+
 static DecodeStatus DecodeGPRX5RegisterClass(MCInst &Inst,
                                              const MCDisassembler *Decoder) {
   Inst.addOperand(MCOperand::createReg(RISCV::X5));
@@ -148,6 +163,8 @@ constexpr bool PredNoX31(uint32_t RegNo) { return RegNo != 31; }
 
 constexpr auto DecodeGPRNoX0RegisterClass =
     DecodeFilteredRegisterClass<DecodeGPRRegisterClass, PredNoX0>;
+constexpr auto DecodeYGPRNoX0RegisterClass =
+    DecodeFilteredRegisterClass<DecodeYGPRRegisterClass, PredNoX0>;
 constexpr auto DecodeGPRNoX2RegisterClass =
     DecodeFilteredRegisterClass<DecodeGPRRegisterClass, PredNoX2>;
 constexpr auto DecodeGPRNoX31RegisterClass =
@@ -463,9 +480,20 @@ static DecodeStatus decodeXqccmpRlistS0(MCInst &Inst, uint32_t Imm,
   return decodeZcmpRlist(Inst, Imm, Address, Decoder);
 }
 
+// The four-argument version is auto-generated by tablegen but we have to
+// forward-declare the two-argument version and implemented it after the .inc
+namespace {
+DecodeStatus DecodeSPRegClassByHwMode(MCInst &Inst,
+                                      const MCDisassembler *Decoder);
+} // namespace
+
 #include "RISCVGenDisassemblerTables.inc"
 
 namespace {
+DecodeStatus DecodeSPRegClassByHwMode(MCInst &Inst,
+                                      const MCDisassembler *Decoder) {
+  return DecodeSPRegClassByHwMode(Inst, 2, 0, Decoder);
+}
 
 struct DecoderListEntry {
   const uint8_t *Table;
@@ -607,6 +635,13 @@ static constexpr DecoderListEntry DecoderList16[]{
     // Standard Extensions
     // DecoderTableZicfiss16 must be checked before DecoderTable16.
     {DecoderTableZicfiss16, {}, "Zicfiss (Shadow Stack 16-bit)"},
+    // RVY instructions remap Zcf (RVY32) or Zcd (RVY64) encodings.
+    {DecoderTableRVY32Only16,
+     {RISCV::FeatureStdExtY, RISCV::Feature32Bit},
+     "RVY32-only 16-bit instructions"},
+    {DecoderTableRVY64Only16,
+     {RISCV::FeatureStdExtY, RISCV::Feature64Bit},
+     "RVY64-only 16-bit instructions"},
     {DecoderTable16, {}, "standard 16-bit instructions"},
     {DecoderTableRV32Only16, {}, "RV32-only 16-bit instructions"},
     // Zc* instructions incompatible with Zcf or Zcd
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
index 418c854a6ef7f..e121193f660da 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
@@ -86,7 +86,10 @@ Expected<ABI> computeTargetABI(const MCSubtargetInfo &STI, StringRef ABIName) {
         "support the D instruction set extension");
   }
   if ((ABIName.starts_with("il32pc64") || ABIName.starts_with("l64pc128")) &&
-      !FeatureBits[RISCV::FeatureStdExtY]) {
+      (!FeatureBits[RISCV::FeatureStdExtY] ||
+       FeatureBits[RISCV::FeatureVendorXLLVMRVYIPM])) {
+    // RVY ABIs are rejected without RVY base ISA or when targetting the
+    // integral pointer (RVI compatibility) mode of RVY.
     return createStringError(Twine('\'') + ABIName +
                              "' ABI is only supported for RVY targets");
   }
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index a34db0fda3c9b..a008f0c73d4b1 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -56,10 +56,12 @@ enum OperandType : unsigned {
   OPERAND_UIMM8,
   OPERAND_UIMM8_LSB000,
   OPERAND_UIMM8_GE32,
+  OPERAND_UIMM9_LSB0000,
   OPERAND_UIMM9,
   OPERAND_UIMM9_LSB000,
   OPERAND_UIMM9_YBNDSWI,
   OPERAND_UIMM10,
+  OPERAND_UIMM10_LSB0000,
   OPERAND_UIMM10_LSB00_NONZERO,
   OPERAND_UIMM11,
   OPERAND_UIMM12,
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 3f48aeb01c641..ebfd2b0b3303e 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1926,15 +1926,31 @@ def Feature32Bit
     : SubtargetFeature<"32bit", "IsRV32", "true", "Implements RV32">;
 def Feature64Bit
     : SubtargetFeature<"64bit", "IsRV64", "true", "Implements RV64">;
+// By default enabling RVY uses capability pointers, to use RVI/RVE compatible
+// integral addresses the internal +xllvmrvyipm extension can be used.
+// NOTE: the final user-visible extension is still TBD, this extension only
+// exists for testing of the internals.
+def FeatureVendorXLLVMRVYIPM
+    : RISCVExtension<1, 0, "Using RVY Base ISA with Integral Pointer "
+                     "(Compatibility) Mode", [FeatureStdExtY], "IsRVYIntMode">;
 def IsRV64 : Predicate<"Subtarget->is64Bit()">,
              AssemblerPredicate<(all_of Feature64Bit),
                                 "RV64I Base Instruction Set">;
 def IsRV32 : Predicate<"!Subtarget->is64Bit()">,
              AssemblerPredicate<(all_of (not Feature64Bit)),
                                 "RV32I Base Instruction Set">;
-
-defvar RV32 = DefaultMode;
-def RV64 : HwMode<[IsRV64]>;
+def IsStdExtYCapMode
+    : Predicate<"Subtarget->hasStdExtY() && !Subtarget->isRVYIntMode()">,
+      AssemblerPredicate<(all_of FeatureStdExtY, (not FeatureVendorXLLVMRVYIPM)),
+                         "Using RVY Capability pointer mode">;
+def NotStdExtYCapMode
+    : Predicate<"!Subtarget->hasStdExtY() || Subtarget->isRVYIntMode()">,
+      AssemblerPredicate<(any_of (not FeatureStdExtY), FeatureVendorXLLVMRVYIPM),
+                         "Not using RVY Capability Pointer Mode">;
+defvar RV32I = DefaultMode;
+def RV64I : HwMode<[IsRV64, NotStdExtYCapMode]>;
+def RV32Y : HwMode<[IsRV32, IsStdExtYCapMode]>;
+def RV64Y : HwMode<[IsRV64, IsStdExtYCapMode]>;
 
 def FeatureRelax
     : SubtargetFeature<"relax", "EnableLinkerRelax", "true",
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index bb1a97fe87140..913ad7698b50e 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -3039,6 +3039,8 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
         CASE_OPERAND_UIMM_LSB_ZEROS(8, 00)
         CASE_OPERAND_UIMM_LSB_ZEROS(8, 000)
         CASE_OPERAND_UIMM_LSB_ZEROS(9, 000)
+        CASE_OPERAND_UIMM_LSB_ZEROS(9, 0000)
+        CASE_OPERAND_UIMM_LSB_ZEROS(10, 0000)
         // clang-format on
         case RISCVOp::OPERAND_UIMM5_NONZERO:
           Ok = isUInt<5>(Imm) && (Imm != 0);
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index c7de1d58271e8..47109fb80db3c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -226,7 +226,7 @@ def ZeroOffsetMemOpOperand : AsmOperandClass {
   let ParserMethod = "parseZeroOffsetMemOp";
 }
 
-class MemOperand<RegisterClass regClass> : RegisterOperand<regClass>{
+class MemOperand<RegisterClassLike regClass> : RegisterOperand<regClass> {
   let OperandType = "OPERAND_MEMORY";
 }
 
@@ -235,11 +235,11 @@ def GPRMemZeroOffset : MemOperand<GPR> {
   let PrintMethod = "printZeroOffsetMemOp";
 }
 
-def BasePtr : MemOperand<GPR>;
+def BasePtr : MemOperand<BasePtrRegClass>;
 
 def SPMem : MemOperand<SP>;
 
-def BasePtrC : MemOperand<GPRC>;
+def BasePtrC : MemOperand<BasePtrCRegClass>;
 
 class SImmAsmOperand<int width, string suffix = "">
     : ImmAsmOperand<"S", width, suffix> {
@@ -676,8 +676,9 @@ class BranchCC_rri<bits<3> funct3, string opcodestr>
 }
 
 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
-class Load_ri<bits<3> funct3, string opcodestr, DAGOperand rty = GPR>
-    : RVInstI<funct3, OPC_LOAD, (outs rty:$rd),
+class Load_ri<bits<3> funct3, string opcodestr, DAGOperand rty = GPR,
+              RISCVOpcode opcode = OPC_LOAD>
+    : RVInstI<funct3, opcode, (outs rty:$rd),
               (ins BasePtr:$rs1, simm12_lo_optional:$imm12),
               opcodestr, "$rd, ${imm12}(${rs1})">;
 
@@ -692,8 +693,9 @@ class HLoad_r<bits<7> funct7, bits<5> funct5, string opcodestr>
 // reflecting the order these fields are specified in the instruction
 // encoding.
 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
-class Store_rri<bits<3> funct3, string opcodestr, DAGOperand rty = GPR>
-    : RVInstS<funct3, OPC_STORE, (outs),
+class Store_rri<bits<3> funct3, string opcodestr, DAGOperand rty = GPR,
+                RISCVOpcode opcode = OPC_STORE>
+    : RVInstS<funct3, opcode, (outs),
               (ins rty:$rs2, BasePtr:$rs1, simm12_lo_optional:$imm12),
               opcodestr, "$rs2, ${imm12}(${rs1})">;
 
@@ -1199,6 +1201,24 @@ def : InstAlias<"ntl.s1",     (ADD   X0, X0, X4)>;
 def : InstAlias<"ntl.all",    (ADD   X0, X0, X5)>;
 
 let EmitPriority = 0 in {
+def : InstAlias<"lb $rd, (${rs1})",
+                (LB  GPR:$rd, BasePtr:$rs1, 0)>;
+def : InstAlias<"lh $rd, (${rs1})",
+                (LH  GPR:$rd, BasePtr:$rs1, 0)>;
+def : InstAlias<"lw $rd, (${rs1})",
+                (LW  GPR:$rd, BasePtr:$rs1, 0)>;
+def : InstAlias<"lbu $rd, (${rs1})",
+                (LBU  GPR:$rd, BasePtr:$rs1, 0)>;
+def : InstAlias<"lhu $rd, (${rs1})",
+                (LHU  GPR:$rd, BasePtr:$rs1, 0)>;
+
+def : InstAlias<"sb $rs2, (${rs1})",
+                (SB  GPR:$rs2, BasePtr:$rs1, 0)>;
+def : InstAlias<"sh $rs2, (${rs1})",
+                (SH  GPR:$rs2, BasePtr:$rs1, 0)>;
+def : InstAlias<"sw $rs2, (${rs1})",
+                (SW  GPR:$rs2, BasePtr:$rs1, 0)>;
+
 def : InstAlias<"add $rd, $rs1, $imm12",
                 (ADDI  GPR:$rd, GPR:$rs1, simm12_lo:$imm12)>;
 def : InstAlias<"and $rd, $rs1, $imm12",
@@ -1214,6 +1234,13 @@ def : InstAlias<"srl $rd, $rs1, $shamt",
 def : InstAlias<"sra $rd, $rs1, $shamt",
                 (SRAI  GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
 let Predicates = [IsRV64] in {
+def : InstAlias<"lwu $rd, (${rs1})",
+                (LWU  GPR:$rd, BasePtr:$rs1, 0)>;
+def : InstAlias<"ld $rd, (${rs1})",
+                (LD  GPR:$rd, BasePtr:$rs1, 0)>;
+def : InstAlias<"sd $rs2, (${rs1})",
+                (SD  GPR:$rs2, BasePtr:$rs1, 0)>;
+
 def : InstAlias<"addw $rd, $rs1, $imm12",
                 (ADDIW  GPR:$rd, GPR:$rs1, simm12_lo:$imm12)>;
 def : InstAlias<"sllw $rd, $rs1, $shamt",
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
index 297595413f699..ee8ff3b2484c1 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
@@ -282,9 +282,10 @@ class CA_ALU<bits<6> funct6, bits<2> funct2, string OpcodeStr>
 
 let Predicates = [HasStdExtZca] in {
 
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0,
+    append Predicates = [NotStdExtYCapMode] in
 def C_ADDI4SPN : RVInst16CIW<0b000, OPC_C0, (outs GPRC:$rd),
-                             (ins SP:$rs1, uimm10_lsb00nonzero:$imm),
+                             (ins SP_X:$rs1, uimm10_lsb00nonzero:$imm),
                              "c.addi4spn", "$rd, $rs1, $imm">,
                              Sched<[WriteIALU, ReadIALU]> {
   bits<0> rs1;
@@ -386,9 +387,10 @@ def C_LI : RVInst16CI<0b010, OPC_C1, (outs GPR:$rd), (ins simm6:$imm),
                       "c.li", "$rd, $imm">,
            Sched<[WriteIALU]>;
 
-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),
+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),
                             "c.addi16sp", "$rd, $imm">,
                  Sched<[WriteIALU, ReadIALU]> {
   let Constraints = "$rd = $rd_wb";
@@ -739,8 +741,8 @@ def : InstAlias<".insn_cj $opcode, $funct3, $imm11",
 
 // Quadrant 0
 let Predicates = [HasStdExtZca] in {
-def : CompressPat<(ADDI GPRC:$rd, SP:$rs1, uimm10_lsb00nonzero:$imm),
-                  (C_ADDI4SPN GPRC:$rd, SP:$rs1...
[truncated]

``````````

</details>


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


More information about the llvm-branch-commits mailing list