[llvm] [RISC-V] Use an optional offset operand instead of zero-offset InstAliases (PR #210901)

Alexander Richardson via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 5 14:45:58 PDT 2026


https://github.com/arichardson updated https://github.com/llvm/llvm-project/pull/210901

>From 22f77171e92c3a9f1a2ec026959f23c0459b15d6 Mon Sep 17 00:00:00 2001
From: Alexander Richardson <mail at alexrichardson.me>
Date: Tue, 21 Jul 2026 00:54:33 -0700
Subject: [PATCH 1/4] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
 =?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.8-beta.1-arichardson
---
 .../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 19 ++++
 llvm/lib/Target/RISCV/RISCVInstrInfo.td       | 89 +++++++++----------
 llvm/lib/Target/RISCV/RISCVInstrInfoD.td      |  3 -
 llvm/lib/Target/RISCV/RISCVInstrInfoF.td      |  7 +-
 llvm/lib/Target/RISCV/RISCVInstrInfoQ.td      |  3 -
 llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td   | 32 +++----
 llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td    |  5 --
 llvm/lib/Target/RISCV/RISCVInstrInfoZilsd.td  |  7 +-
 8 files changed, 80 insertions(+), 85 deletions(-)

diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 8563f678464a6..70d679c1ad068 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -307,6 +307,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
   std::unique_ptr<RISCVOperand> defaultFRMArgOp() const;
   std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp() const;
   std::unique_ptr<RISCVOperand> defaultSMTVType();
+  std::unique_ptr<RISCVOperand> defaultZeroOffset();
 
 public:
   enum RISCVMatchResultTy : unsigned {
@@ -956,6 +957,19 @@ struct RISCVOperand final : public MCParsedAsmOperand {
             VK == ELF::R_RISCV_TLSDESC_ADD_LO12);
   }
 
+  /// Returns NoMatch rather than the NearMatch of the underlying predicate
+  /// for anything that is not an immediate at all (such as the '(' token of an
+  /// offset-less memory operand). This lets the matcher skip this optional
+  /// operand and insert the default 0 offset. An immediate that fails Pred
+  /// (e.g. out of range) still reports the wrapped class diagnostic.
+  template <bool (RISCVOperand::*Pred)() const>
+  DiagnosticPredicate isOptionalMemOffset() const {
+    if (!isImm())
+      return DiagnosticPredicate::NoMatch;
+    return (this->*Pred)() ? DiagnosticPredicate::Match
+                           : DiagnosticPredicate::NearMatch;
+  }
+
   bool isSImm12Lsb00000() const {
     return isSImmPred([](int64_t Imm) { return isShiftedInt<7, 5>(Imm); });
   }
@@ -4101,6 +4115,11 @@ std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {
                                     llvm::SMLoc());
 }
 
+std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultZeroOffset() {
+  return RISCVOperand::createExpr(MCConstantExpr::create(0, getContext()),
+                                  llvm::SMLoc(), llvm::SMLoc(), isRV64());
+}
+
 static unsigned getNFforLXSEG(unsigned Opcode) {
   switch (Opcode) {
   default:
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index e10ee7389db0e..545098e32122c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -206,6 +206,7 @@ class ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass {
 
 class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass {
   let Name = prefix # "Imm" # width # suffix;
+  let PredicateMethod = "is" # prefix # "Imm" # width # suffix;
   let RenderMethod = "addImmOperands";
   let DiagnosticType = !strconcat("Invalid", Name);
 }
@@ -253,6 +254,18 @@ class BareSImmNLsb0AsmOperand<int width>
   let PredicateMethod = "isBareSimmNLsb0<" # width # ">";
 }
 
+// Use for memory operands where offset may be omitted entirely: "lb a0, (a1)"
+// parses as an offset of 0 without needing a separate zero-offset InstAlias
+// for every load/store instruction.
+class OptionalMemOffsetAsmOperand<AsmOperandClass base> : AsmOperandClass {
+  let Name = "Optional" # base.Name;
+  let PredicateMethod = "isOptionalMemOffset<&RISCVOperand::" # base.PredicateMethod # ">";
+  let RenderMethod = "addImmOperands";
+  let DiagnosticType = base.DiagnosticType;
+  let IsOptional = 1;
+  let DefaultMethod = "defaultZeroOffset";
+}
+
 class RISCVOp<ValueType vt = XLenVT> : Operand<vt> {
   let OperandNamespace = "RISCVOp";
 }
@@ -362,6 +375,14 @@ def simm12_lo : RISCVSImmLeafOp<12> {
   let OperandType = "OPERAND_SIMM12_LO";
 }
 
+// Variant of simm12_lo for memory-operand offsets that may be omitted
+// entirely, e.g. "lb a0, (a1)". See OptionalMemOffsetAsmOperand.
+def simm12_lo_optional : RISCVSImmLeafOp<12> {
+  let ParserMatchClass = OptionalMemOffsetAsmOperand<simm12_lo.ParserMatchClass>;
+  let MCOperandPredicate = simm12_lo.MCOperandPredicate;
+  let OperandType = simm12_lo.OperandType;
+}
+
 // A 12-bit signed immediate which cannot fit in 6-bit signed immediate,
 // but even negative value fit in 12-bit.
 def simm12_no6 : ImmLeaf<XLenVT, [{
@@ -655,7 +676,8 @@ 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), (ins BasePtr:$rs1, simm12_lo:$imm12),
+    : RVInstI<funct3, OPC_LOAD, (outs rty:$rd),
+              (ins BasePtr:$rs1, simm12_lo_optional:$imm12),
               opcodestr, "$rd, ${imm12}(${rs1})">;
 
 class HLoad_r<bits<7> funct7, bits<5> funct5, string opcodestr>
@@ -671,7 +693,7 @@ class HLoad_r<bits<7> funct7, bits<5> funct5, string opcodestr>
 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
 class Store_rri<bits<3> funct3, string opcodestr, DAGOperand rty = GPR>
     : RVInstS<funct3, OPC_STORE, (outs),
-              (ins rty:$rs2, BasePtr:$rs1, simm12_lo:$imm12),
+              (ins rty:$rs2, BasePtr:$rs1, simm12_lo_optional:$imm12),
               opcodestr, "$rs2, ${imm12}(${rs1})">;
 
 class HStore_rr<bits<7> funct7, string opcodestr>
@@ -767,7 +789,7 @@ def JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20),
                   "jal", "$rd, $imm20">, Sched<[WriteJal]>;
 
 def JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd),
-                   (ins GPR:$rs1, simm12_lo:$imm12),
+                   (ins GPR:$rs1, simm12_lo_optional:$imm12),
                    "jalr", "$rd, ${imm12}(${rs1})">,
            Sched<[WriteJalr, ReadJalr]>;
 } // hasSideEffects = 0, mayLoad = 0, mayStore = 0
@@ -1107,11 +1129,12 @@ def : InstAlias<"j $offset",   (JAL X0, simm21_lsb0_jal:$offset)>;
 def : InstAlias<"jal $offset", (JAL X1, simm21_lsb0_jal:$offset)>;
 
 // Non-zero offset aliases of "jalr" are the lowest weight, followed by the
-// two-register form, then the one-register forms and finally "ret".
+// two-register form, then the one-register forms and finally "ret". The
+// "(${rs})" offset-less forms are covered by simm12_lo_optional.
 def : InstAlias<"jr $rs",                (JALR      X0, GPR:$rs, 0), 3>;
-def : InstAlias<"jr ${offset}(${rs})",   (JALR      X0, GPR:$rs, simm12_lo:$offset)>;
+def : InstAlias<"jr ${offset}(${rs})",   (JALR      X0, GPR:$rs, simm12_lo_optional:$offset)>;
 def : InstAlias<"jalr $rs",              (JALR      X1, GPR:$rs, 0), 3>;
-def : InstAlias<"jalr ${offset}(${rs})", (JALR      X1, GPR:$rs, simm12_lo:$offset)>;
+def : InstAlias<"jalr ${offset}(${rs})", (JALR      X1, GPR:$rs, simm12_lo_optional:$offset)>;
 def : InstAlias<"jalr $rd, $rs",         (JALR GPR:$rd, GPR:$rs, 0), 2>;
 def : InstAlias<"ret",                   (JALR      X0,      X1, 0), 4>;
 
@@ -1119,9 +1142,6 @@ def : InstAlias<"ret",                   (JALR      X0,      X1, 0), 4>;
 def : InstAlias<"jr $rs, $offset",        (JALR      X0, GPR:$rs, simm12_lo:$offset), 0>;
 def : InstAlias<"jalr $rs, $offset",      (JALR      X1, GPR:$rs, simm12_lo:$offset), 0>;
 def : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12_lo:$offset), 0>;
-def : InstAlias<"jr (${rs})",             (JALR      X0, GPR:$rs, 0), 0>;
-def : InstAlias<"jalr (${rs})",           (JALR      X1, GPR:$rs, 0), 0>;
-def : InstAlias<"jalr $rd, (${rs})",      (JALR GPR:$rd, GPR:$rs, 0), 0>;
 
 def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw
 
@@ -1178,24 +1198,6 @@ 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, GPR:$rs1, 0)>;
-def : InstAlias<"lh $rd, (${rs1})",
-                (LH  GPR:$rd, GPR:$rs1, 0)>;
-def : InstAlias<"lw $rd, (${rs1})",
-                (LW  GPR:$rd, GPR:$rs1, 0)>;
-def : InstAlias<"lbu $rd, (${rs1})",
-                (LBU  GPR:$rd, GPR:$rs1, 0)>;
-def : InstAlias<"lhu $rd, (${rs1})",
-                (LHU  GPR:$rd, GPR:$rs1, 0)>;
-
-def : InstAlias<"sb $rs2, (${rs1})",
-                (SB  GPR:$rs2, GPR:$rs1, 0)>;
-def : InstAlias<"sh $rs2, (${rs1})",
-                (SH  GPR:$rs2, GPR:$rs1, 0)>;
-def : InstAlias<"sw $rs2, (${rs1})",
-                (SW  GPR:$rs2, GPR:$rs1, 0)>;
-
 def : InstAlias<"add $rd, $rs1, $imm12",
                 (ADDI  GPR:$rd, GPR:$rs1, simm12_lo:$imm12)>;
 def : InstAlias<"and $rd, $rs1, $imm12",
@@ -1211,13 +1213,6 @@ 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, GPR:$rs1, 0)>;
-def : InstAlias<"ld $rd, (${rs1})",
-                (LD  GPR:$rd, GPR:$rs1, 0)>;
-def : InstAlias<"sd $rs2, (${rs1})",
-                (SD  GPR:$rs2, GPR:$rs1, 0)>;
-
 def : InstAlias<"addw $rd, $rs1, $imm12",
                 (ADDIW  GPR:$rd, GPR:$rs1, simm12_lo:$imm12)>;
 def : InstAlias<"sllw $rd, $rs1, $shamt",
@@ -1308,7 +1303,7 @@ def InsnI : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$
 def InsnI_Mem : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode,
                                                        uimm3:$funct3,
                                                        AnyReg:$rs1,
-                                                       simm12_lo:$imm12),
+                                                       simm12_lo_optional:$imm12),
                                "$opcode, $funct3, $rd, ${imm12}(${rs1})">;
 def InsnB : DirectiveInsnB<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3,
                                         AnyReg:$rs1, AnyReg:$rs2,
@@ -1322,7 +1317,7 @@ def InsnJ : DirectiveInsnJ<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode,
                            "$opcode, $rd, $imm20">;
 def InsnS : DirectiveInsnS<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3,
                                         AnyReg:$rs2, AnyReg:$rs1,
-                                        simm12_lo:$imm12),
+                                        simm12_lo_optional:$imm12),
                            "$opcode, $funct3, $rs2, ${imm12}(${rs1})">;
 } // isCodeGenOnly, hasSideEffects, mayLoad, mayStore, hasNoSchedulingInfo
 
@@ -1346,10 +1341,7 @@ def : InstAlias<".insn_i $opcode, $funct3, $rd, $rs1, $imm12",
                        simm12_lo:$imm12)>;
 def : InstAlias<".insn_i $opcode, $funct3, $rd, ${imm12}(${rs1})",
                 (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3,
-                           AnyReg:$rs1, simm12_lo:$imm12)>;
-def : InstAlias<".insn_i $opcode, $funct3, $rd, (${rs1})",
-                (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3,
-                           AnyReg:$rs1, 0)>;
+                           AnyReg:$rs1, simm12_lo_optional:$imm12)>;
 def : InstAlias<".insn_b $opcode, $funct3, $rs1, $rs2, $imm12",
                 (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1,
                        AnyReg:$rs2, bare_simm13_lsb0:$imm12)>;
@@ -1366,10 +1358,7 @@ def : InstAlias<".insn_uj $opcode, $rd, $imm20",
                 (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>;
 def : InstAlias<".insn_s $opcode, $funct3, $rs2, ${imm12}(${rs1})",
                 (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2,
-                       AnyReg:$rs1, simm12_lo:$imm12)>;
-def : InstAlias<".insn_s $opcode, $funct3, $rs2, (${rs1})",
-                (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2,
-                       AnyReg:$rs1, 0)>;
+                       AnyReg:$rs1, simm12_lo_optional:$imm12)>;
 }
 
 //===----------------------------------------------------------------------===//
@@ -1791,10 +1780,14 @@ let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in {
 // Use GPRJALRNonX7 to avoid X7 which is reserved for landing pad labels
 // in cf-protection-branch. The NonX7 constraint is applied unconditionally
 // to simplify the code at a negligible performance cost.
-def PseudoBRIND : Pseudo<(outs), (ins GPRJALRNonX7:$rs1, simm12_lo:$imm12), []>,
-                  PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12_lo:$imm12)>;
-def PseudoBRINDX7 : Pseudo<(outs), (ins GPRX7:$rs1, simm12_lo:$imm12), []>,
-                    PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12_lo:$imm12)>;
+def PseudoBRIND : Pseudo<(outs),
+                         (ins GPRJALRNonX7:$rs1, simm12_lo_optional:$imm12), []>,
+                  PseudoInstExpansion<(JALR X0, GPR:$rs1,
+                                       simm12_lo_optional:$imm12)>;
+def PseudoBRINDX7 : Pseudo<(outs), (ins GPRX7:$rs1, simm12_lo_optional:$imm12),
+                           []>,
+                    PseudoInstExpansion<(JALR X0, GPR:$rs1,
+                                         simm12_lo_optional:$imm12)>;
 }
 
 def : Pat<(riscv_sw_guarded_brind GPRX7:$rs1), (PseudoBRINDX7 GPRX7:$rs1, 0)>;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td
index d8f9c551d9e5d..f659d20288044 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td
@@ -185,9 +185,6 @@ def FMV_D_X : FPUnaryOp_r<0b1111001, 0b00000, 0b000, FPR64, GPR, "fmv.d.x">,
 //===----------------------------------------------------------------------===//
 
 let Predicates = [HasStdExtD] in {
-def : InstAlias<"fld $rd, (${rs1})",  (FLD FPR64:$rd,  GPR:$rs1, 0), 0>;
-def : InstAlias<"fsd $rs2, (${rs1})", (FSD FPR64:$rs2, GPR:$rs1, 0), 0>;
-
 def : InstAlias<"fmv.d $rd, $rs",  (FSGNJ_D  FPR64:$rd, FPR64:$rs, FPR64:$rs)>;
 def : InstAlias<"fabs.d $rd, $rs", (FSGNJX_D FPR64:$rd, FPR64:$rs, FPR64:$rs)>;
 def : InstAlias<"fneg.d $rd, $rs", (FSGNJN_D FPR64:$rd, FPR64:$rs, FPR64:$rs)>;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td
index 1ccbc7e76de30..4823634f62a7a 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td
@@ -199,7 +199,7 @@ let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
 class FPLoad_r<bits<3> funct3, string opcodestr, DAGOperand rty,
                SchedWrite sw>
     : RVInstI<funct3, OPC_LOAD_FP, (outs rty:$rd),
-              (ins BasePtr:$rs1, simm12_lo:$imm12),
+              (ins BasePtr:$rs1, simm12_lo_optional:$imm12),
               opcodestr, "$rd, ${imm12}(${rs1})">,
       Sched<[sw, ReadFMemBase]>;
 
@@ -207,7 +207,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
 class FPStore_r<bits<3> funct3, string opcodestr, DAGOperand rty,
                 SchedWrite sw>
     : RVInstS<funct3, OPC_STORE_FP, (outs),
-              (ins rty:$rs2, BasePtr:$rs1, simm12_lo:$imm12),
+              (ins rty:$rs2, BasePtr:$rs1, simm12_lo_optional:$imm12),
               opcodestr, "$rs2, ${imm12}(${rs1})">,
       Sched<[sw, ReadFStoreData, ReadFMemBase]>;
 
@@ -475,9 +475,6 @@ def : InstAlias<"fsflagsi $imm",      (CSRRWI      X0, SysRegFFLAGS.Encoding, ui
 } // Predicates = [HasStdExtFOrZfinx]
 
 let Predicates = [HasStdExtF] in {
-def : InstAlias<"flw $rd, (${rs1})",  (FLW FPR32:$rd,  GPR:$rs1, 0), 0>;
-def : InstAlias<"fsw $rs2, (${rs1})", (FSW FPR32:$rs2, GPR:$rs1, 0), 0>;
-
 def : InstAlias<"fmv.s $rd, $rs",  (FSGNJ_S  FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
 def : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
 def : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoQ.td b/llvm/lib/Target/RISCV/RISCVInstrInfoQ.td
index 4d0d71b93a055..1bb3d30eda1ea 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoQ.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoQ.td
@@ -145,9 +145,6 @@ foreach Ext = QExtsRV64 in {
 //===----------------------------------------------------------------------===//
 
 let Predicates = [HasStdExtQ] in {
-  def : InstAlias<"flq $rd, (${rs1})",  (FLQ FPR128:$rd,  GPR:$rs1, 0), 0>;
-  def : InstAlias<"fsq $rs2, (${rs1})", (FSQ FPR128:$rs2, GPR:$rs1, 0), 0>;
-
   def : InstAlias<"fmv.q $rd, $rs",  (FSGNJ_Q FPR128:$rd, FPR128:$rs,
                                       FPR128:$rs)>;
   def : InstAlias<"fabs.q $rd, $rs", (FSGNJX_Q FPR128:$rd, FPR128:$rs,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index ea3c5927f1da8..ace5547610a06 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -1922,27 +1922,27 @@ def : CompressPat<(QC_E_LW GPRC:$rd, BasePtrC:$rs1, uimm7_lsb00:$imm),
                   (C_LW GPRC:$rd, BasePtrC:$rs1, uimm7_lsb00:$imm)>;
 def : CompressPat<(QC_E_LW GPRNoX0:$rd, SPMem:$rs1,  uimm8_lsb00:$imm),
                   (C_LWSP GPRNoX0:$rd, SPMem:$rs1, uimm8_lsb00:$imm)>;
-def : CompressPat<(QC_E_LB GPR:$rd, BasePtr:$rs1, simm12_lo:$imm12),
-                  (LB GPR:$rd, BasePtr:$rs1, simm12_lo:$imm12)>;
-def : CompressPat<(QC_E_LBU GPR:$rd, BasePtr:$rs1, simm12_lo:$imm12),
-                  (LBU GPR:$rd, BasePtr:$rs1, simm12_lo:$imm12)>;
-def : CompressPat<(QC_E_LH GPR:$rd, BasePtr:$rs1, simm12_lo:$imm12),
-                  (LH GPR:$rd, BasePtr:$rs1, simm12_lo:$imm12)>;
-def : CompressPat<(QC_E_LHU GPR:$rd, BasePtr:$rs1, simm12_lo:$imm12),
-                  (LHU GPR:$rd, BasePtr:$rs1, simm12_lo:$imm12)>;
-def : CompressPat<(QC_E_LW GPR:$rd, BasePtr:$rs1, simm12_lo:$imm12),
-                  (LW GPR:$rd, BasePtr:$rs1, simm12_lo:$imm12)>;
+def : CompressPat<(QC_E_LB GPR:$rd, BasePtr:$rs1, simm12_lo_optional:$imm12),
+                  (LB GPR:$rd, BasePtr:$rs1, simm12_lo_optional:$imm12)>;
+def : CompressPat<(QC_E_LBU GPR:$rd, BasePtr:$rs1, simm12_lo_optional:$imm12),
+                  (LBU GPR:$rd, BasePtr:$rs1, simm12_lo_optional:$imm12)>;
+def : CompressPat<(QC_E_LH GPR:$rd, BasePtr:$rs1, simm12_lo_optional:$imm12),
+                  (LH GPR:$rd, BasePtr:$rs1, simm12_lo_optional:$imm12)>;
+def : CompressPat<(QC_E_LHU GPR:$rd, BasePtr:$rs1, simm12_lo_optional:$imm12),
+                  (LHU GPR:$rd, BasePtr:$rs1, simm12_lo_optional:$imm12)>;
+def : CompressPat<(QC_E_LW GPR:$rd, BasePtr:$rs1, simm12_lo_optional:$imm12),
+                  (LW GPR:$rd, BasePtr:$rs1, simm12_lo_optional:$imm12)>;
 
 def : CompressPat<(QC_E_SW GPRC:$rs2, BasePtrC:$rs1, uimm7_lsb00:$imm),
                   (C_SW GPRC:$rs2, BasePtrC:$rs1, uimm7_lsb00:$imm)>;
 def : CompressPat<(QC_E_SW GPR:$rs2, SPMem:$rs1, uimm8_lsb00:$imm),
                   (C_SWSP GPR:$rs2, SPMem:$rs1, uimm8_lsb00:$imm)>;
-def : CompressPat<(QC_E_SB GPR:$rs2, BasePtr:$rs1, simm12_lo:$imm12),
-                  (SB GPR:$rs2, BasePtr:$rs1, simm12_lo:$imm12)>;
-def : CompressPat<(QC_E_SH GPR:$rs2, BasePtr:$rs1, simm12_lo:$imm12),
-                  (SH GPR:$rs2, BasePtr:$rs1, simm12_lo:$imm12)>;
-def : CompressPat<(QC_E_SW GPR:$rs2, BasePtr:$rs1, simm12_lo:$imm12),
-                  (SW GPR:$rs2, BasePtr:$rs1, simm12_lo:$imm12)>;
+def : CompressPat<(QC_E_SB GPR:$rs2, BasePtr:$rs1, simm12_lo_optional:$imm12),
+                  (SB GPR:$rs2, BasePtr:$rs1, simm12_lo_optional:$imm12)>;
+def : CompressPat<(QC_E_SH GPR:$rs2, BasePtr:$rs1, simm12_lo_optional:$imm12),
+                  (SH GPR:$rs2, BasePtr:$rs1, simm12_lo_optional:$imm12)>;
+def : CompressPat<(QC_E_SW GPR:$rs2, BasePtr:$rs1, simm12_lo_optional:$imm12),
+                  (SW GPR:$rs2, BasePtr:$rs1, simm12_lo_optional:$imm12)>;
 } // isCompressOnly = true, Predicates = [HasVendorXqcilo, IsRV32]
 
 let Predicates = [HasVendorXqcicm, IsRV32] in {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td
index 79a4a95ab3448..b128919626ca4 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td
@@ -228,11 +228,6 @@ foreach Ext = ZfhminDExts in {
 // Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
 //===----------------------------------------------------------------------===//
 
-let Predicates = [HasHalfFPLoadStoreMove] in {
-def : InstAlias<"flh $rd, (${rs1})",  (FLH FPR16:$rd,  GPR:$rs1, 0), 0>;
-def : InstAlias<"fsh $rs2, (${rs1})", (FSH FPR16:$rs2, GPR:$rs1, 0), 0>;
-} // Predicates = [HasStdExtZfhmin]
-
 let Predicates = [HasStdExtZfh] in {
 def : InstAlias<"fmv.h $rd, $rs",  (FSGNJ_H  FPR16:$rd, FPR16:$rs, FPR16:$rs)>;
 def : InstAlias<"fabs.h $rd, $rs", (FSGNJX_H FPR16:$rd, FPR16:$rs, FPR16:$rs)>;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZilsd.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZilsd.td
index 4fc859f2547c1..26b826ac6d691 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZilsd.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZilsd.td
@@ -50,7 +50,7 @@ def PseudoSD_RV32 : PseudoStore<"sd", GPRPairRV32>;
 // Pseudo instructions for load/store optimization with 2 separate registers
 def PseudoLD_RV32_OPT :
     Pseudo<(outs GPR:$rd1, GPR:$rd2),
-           (ins GPR:$rs1, simm12_lo:$imm12), [], "", ""> {
+           (ins GPR:$rs1, simm12_lo_optional:$imm12), [], "", ""> {
   let hasSideEffects = 0;
   let mayLoad = 1;
   let mayStore = 0;
@@ -58,12 +58,9 @@ def PseudoLD_RV32_OPT :
 
 def PseudoSD_RV32_OPT :
     Pseudo<(outs),
-           (ins GPR:$rs1, GPR:$rs2, GPR:$rs3, simm12_lo:$imm12), [], "", ""> {
+           (ins GPR:$rs1, GPR:$rs2, GPR:$rs3, simm12_lo_optional:$imm12), [], "", ""> {
   let hasSideEffects = 0;
   let mayLoad = 0;
   let mayStore = 1;
 }
-
-def : InstAlias<"ld $rd, (${rs1})", (LD_RV32 GPRPairRV32:$rd, GPR:$rs1, 0), 0>;
-def : InstAlias<"sd $rs2, (${rs1})", (SD_RV32 GPRPairRV32:$rs2, GPR:$rs1, 0), 0>;
 }

>From 6e051128860f5cbc852d9cd536e77f4eaa64586c Mon Sep 17 00:00:00 2001
From: Alexander Richardson <mail at alexrichardson.me>
Date: Wed, 5 Aug 2026 09:35:14 -0700
Subject: [PATCH 2/4] use simm12_optional for xqci

Created using spr 1.3.8-beta.1-arichardson
---
 llvm/lib/Target/RISCV/RISCVInstrInfo.td     | 5 ++++-
 llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td | 4 ++--
 llvm/test/MC/RISCV/rv32i-invalid.s          | 1 +
 llvm/test/MC/RISCV/tlsdesc.s                | 1 +
 4 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index c7de1d58271e8..28839d869ab85 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -378,8 +378,11 @@ def simm12_lo : Simm12LoOp {
   let ParserMatchClass = SImmAsmOperand<12, "LO">;
 }
 
-// Variant of simm12_lo for memory-operand offsets that may be omitted
+// Variants of simm12(_lo) for memory-operand offsets that may be omitted
 // entirely, e.g. "lb a0, (a1)". See OptionalMemOffsetAsmOperand.
+def simm12_optional : Simm12LoOp {
+  let ParserMatchClass = OptionalMemOffsetAsmOperand<simm12.ParserMatchClass>;
+}
 def simm12_lo_optional : Simm12LoOp {
   let ParserMatchClass = OptionalMemOffsetAsmOperand<simm12_lo.ParserMatchClass>;
 }
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index aec381a84e0d2..f0ae8fbd2aab6 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -1392,13 +1392,13 @@ let hasSideEffects = false, mayLoad = true, mayStore = false, Size = 4,
     isCodeGenOnly = false in
 class PseudoQCAccessLoad_ri<string opcodestr>
   : Pseudo<(outs GPR:$rd),
-           (ins BasePtr:$rs1, simm12_lo_optional:$imm12, qc_access_symbol:$expr), [],
+           (ins BasePtr:$rs1, simm12_optional:$imm12, qc_access_symbol:$expr), [],
            opcodestr, "$rd, ${imm12}(${rs1}), $expr">;
 
 let hasSideEffects = false, mayLoad = false, mayStore = true, Size = 4,
     isCodeGenOnly = false in
 class PseudoQCAccessStore_rri<string opcodestr>
-  : Pseudo<(outs), (ins GPR:$rs2, BasePtr:$rs1, simm12_lo_optional:$imm12, qc_access_symbol:$expr),
+  : Pseudo<(outs), (ins GPR:$rs2, BasePtr:$rs1, simm12_optional:$imm12, qc_access_symbol:$expr),
            [], opcodestr, "$rs2, ${imm12}(${rs1}), $expr">;
 
 
diff --git a/llvm/test/MC/RISCV/rv32i-invalid.s b/llvm/test/MC/RISCV/rv32i-invalid.s
index be624a578650d..80af2c12d5287 100644
--- a/llvm/test/MC/RISCV/rv32i-invalid.s
+++ b/llvm/test/MC/RISCV/rv32i-invalid.s
@@ -80,6 +80,7 @@ lw a0, -2049(f0)
 # CHECK: :[[@LINE-1]]:1: error: invalid instruction, any one of the following would fix this:
 # CHECK: :[[@LINE-2]]:8: note: operand must be a bare symbol name
 # CHECK: :[[@LINE-3]]:8: note: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo specifier or an integer in the range [-2048, 2047]
+# CHECK: :[[@LINE-4]]:8: note: immediate must be an integer in the range [-2048, 2047]
 ld a0, (a3)
 # CHECK: :[[@LINE-1]]:1: error: instruction requires the following: 'Zilsd' (Load/Store pair instructions)
 
diff --git a/llvm/test/MC/RISCV/tlsdesc.s b/llvm/test/MC/RISCV/tlsdesc.s
index 4ebbffa1f3122..32a110d789392 100644
--- a/llvm/test/MC/RISCV/tlsdesc.s
+++ b/llvm/test/MC/RISCV/tlsdesc.s
@@ -53,6 +53,7 @@ start:                                  # @start
 # ERR: :[[#@LINE-1]]:2: error: invalid instruction, any one of the following would fix this:
 # ERR: :[[#@LINE-2]]:15: note: unexpected extra operand for instruction
 # ERR: :[[#@LINE-3]]:11: note: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo specifier or an integer in the range [-2048, 2047]
+# ERR: :[[#@LINE-4]]:11: note: immediate must be an integer in the range [-2048, 2047]
 
 	addi a0, t0, %tlsdesc_add_lo(a_symbol)(a4)
 # ERR: :[[#@LINE-1]]:41: error: unexpected extra operand for instruction

>From 133c0d9c63628e0ff8a81e186f7ce4e75aca63ae Mon Sep 17 00:00:00 2001
From: Alexander Richardson <mail at alexrichardson.me>
Date: Wed, 5 Aug 2026 09:50:46 -0700
Subject: [PATCH 3/4] fix simm12_optional inheritance

Created using spr 1.3.8-beta.1-arichardson
---
 llvm/lib/Target/RISCV/RISCVInstrInfo.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 28839d869ab85..f393115e35ac0 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -383,7 +383,7 @@ def simm12_lo : Simm12LoOp {
 def simm12_optional : Simm12LoOp {
   let ParserMatchClass = OptionalMemOffsetAsmOperand<simm12.ParserMatchClass>;
 }
-def simm12_lo_optional : Simm12LoOp {
+def simm12_lo_optional : RISCVSImmLeafOp<12> {
   let ParserMatchClass = OptionalMemOffsetAsmOperand<simm12_lo.ParserMatchClass>;
 }
 

>From 78da6bebd43b18b3526ee7d932b2eec1efc0b662 Mon Sep 17 00:00:00 2001
From: Alexander Richardson <mail at alexrichardson.me>
Date: Wed, 5 Aug 2026 14:45:31 -0700
Subject: [PATCH 4/4] fix inverted inheritance that broke tests

Created using spr 1.3.8-beta.1-arichardson
---
 llvm/lib/Target/RISCV/RISCVInstrInfo.td | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index f393115e35ac0..bc3c9525a3d72 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -380,10 +380,10 @@ def simm12_lo : Simm12LoOp {
 
 // Variants of simm12(_lo) for memory-operand offsets that may be omitted
 // entirely, e.g. "lb a0, (a1)". See OptionalMemOffsetAsmOperand.
-def simm12_optional : Simm12LoOp {
+def simm12_optional : RISCVSImmLeafOp<12> {
   let ParserMatchClass = OptionalMemOffsetAsmOperand<simm12.ParserMatchClass>;
 }
-def simm12_lo_optional : RISCVSImmLeafOp<12> {
+def simm12_lo_optional : Simm12LoOp {
   let ParserMatchClass = OptionalMemOffsetAsmOperand<simm12_lo.ParserMatchClass>;
 }
 



More information about the llvm-commits mailing list