[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