[llvm-branch-commits] [RISC-V][RVY] Add support for compressed stack-pointer addition (PR #203598)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Jun 12 11:02:57 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>
In RVY mode, the c.addi4spn/c.addi16sp instructions expand to YADDI to
perform arithmetic on the YLEN stack pointer instead.
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/203598.diff
6 Files Affected:
- (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+1)
- (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+2-2)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoC.td (+6)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoY.td (+34)
- (modified) llvm/lib/Target/RISCV/RISCVSubtarget.h (+2)
- (added) llvm/test/MC/RISCV/rvy/rvyc-valid-addi.s (+73)
``````````diff
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 93cb83027af3f..c7dbdcd5fab78 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -641,6 +641,7 @@ static constexpr DecoderListEntry DecoderList16[]{
{DecoderTableRVY64Only16,
{RISCV::FeatureStdExtY, RISCV::Feature64Bit},
"RVY64-only 16-bit instructions"},
+ {DecoderTableRVY16, {RISCV::FeatureStdExtY}, "RVY 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/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 3b1013fb15c3e..804b7c133b804 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1894,11 +1894,11 @@ def IsRV32 : Predicate<"!Subtarget->is64Bit()">,
AssemblerPredicate<(all_of (not Feature64Bit)),
"RV32I Base Instruction Set">;
def IsStdExtYCapMode
- : Predicate<"Subtarget->hasStdExtY() && !Subtarget->isRVYIntMode()">,
+ : Predicate<"Subtarget->isStdExtYCapMode()">,
AssemblerPredicate<(all_of FeatureStdExtY, (not FeatureVendorXLLVMRVYIPM)),
"Using RVY Capability pointer mode">;
def NotStdExtYCapMode
- : Predicate<"!Subtarget->hasStdExtY() || Subtarget->isRVYIntMode()">,
+ : Predicate<"!Subtarget->isStdExtYCapMode()">,
AssemblerPredicate<(any_of (not FeatureStdExtY), FeatureVendorXLLVMRVYIPM),
"Not using RVY Capability Pointer Mode">;
defvar RV32I = DefaultMode;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
index bf58d4b72d47f..b3b28cfc17813 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
@@ -266,6 +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),
@@ -371,6 +374,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),
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoY.td b/llvm/lib/Target/RISCV/RISCVInstrInfoY.td
index e7f3e08c77522..4f588a4a7c695 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoY.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoY.td
@@ -219,6 +219,40 @@ def : CompressPat<(SY YGPR:$rs2, SPMem:$rs1, uimm9_lsb000:$imm),
(C_SYSP_RV32 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)>;
+def : CompressPat<(YADDI X2_Y, X2_Y, simm10_lsb0000nonzero:$imm),
+ (C_YADDI16SP X2_Y, simm10_lsb0000nonzero:$imm)>;
+} // Predicates = [HasStdExtZca, IsStdExtYCapMode]
+
let Predicates = [HasStdExtZca, IsStdExtYCapMode, IsRV64] in {
// DecoderNamespace needed since RVY64 reuses Zcd/Zcm* encodings
let DecoderNamespace = "RVY64Only" in {
diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h
index 4cf2c80323532..5bc8a1fe9ad69 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -176,6 +176,8 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
bool GETTER() const { return ATTRIBUTE; }
#include "RISCVGenSubtargetInfo.inc"
+ bool isStdExtYCapMode() const { return hasStdExtY() && !isRVYIntMode(); }
+
LLVM_DEPRECATED("Now Equivalent to hasStdExtZcd", "hasStdExtZcd")
bool hasStdExtCOrZcd() const { return HasStdExtZcd; }
LLVM_DEPRECATED("Now Equivalent to hasStdExtZcf", "hasStdExtZcf")
diff --git a/llvm/test/MC/RISCV/rvy/rvyc-valid-addi.s b/llvm/test/MC/RISCV/rvy/rvyc-valid-addi.s
new file mode 100644
index 0000000000000..88cf60884c966
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvy/rvyc-valid-addi.s
@@ -0,0 +1,73 @@
+/// Check that addi/yaddi uses compressed instructions correctly depending on the mode.
+// RUN: llvm-mc --triple=riscv32 --mattr=+zca,+zcb,+zcf,+zcd,+f,+d,+zfh,+xllvmrvyipm --riscv-no-aliases --show-encoding --show-inst < %s \
+// RUN: | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ,CHECK-ASM,CHECK-INT,CHECK-INT-ASM-AND-OBJ %s
+// RUN: llvm-mc --triple=riscv32 --mattr=+zca,+zcb,+zcd,+f,+d,+zfh,+experimental-y --defsym=RVY=1 --riscv-no-aliases --show-encoding --show-inst < %s \
+// RUN: | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ,CHECK-ASM,CHECK-CAP,CHECK-CAP-ASM-AND-OBJ %s
+// RUN: llvm-mc --filetype=obj --triple=riscv32 --mattr=+zca,+zcb,+zcf,+zcd,+f,+d,+zfh,+xllvmrvyipm --riscv-add-build-attributes < %s \
+// RUN: | llvm-objdump --mattr=+xllvmrvyipm -M no-aliases -d --no-print-imm-hex - | FileCheck %s --check-prefixes=CHECK-ASM-AND-OBJ,CHECK-INT-ASM-AND-OBJ
+// RUN: llvm-mc --filetype=obj --triple=riscv32 --mattr=+zca,+zcb,+zcd,+f,+d,+zfh,+experimental-y --defsym=RVY=1 --riscv-add-build-attributes < %s \
+// RUN: | llvm-objdump -M no-aliases -d --no-print-imm-hex - | FileCheck %s --check-prefixes=CHECK-ASM-AND-OBJ,CHECK-CAP-ASM-AND-OBJ
+//
+// RUN: llvm-mc --triple=riscv64 --mattr=+zca,+zcb,+zcd,+f,+d,+zfh,+xllvmrvyipm --defsym=RV64=1 --riscv-no-aliases --show-encoding --show-inst < %s \
+// RUN: | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ,CHECK-ASM,CHECK-INT,CHECK-INT-ASM-AND-OBJ %s
+// RUN: llvm-mc --triple=riscv64 --mattr=+zca,+zcb,+f,+d,+zfh,+experimental-y --defsym=RVY=1 --defsym=RV64=1 --defsym=RV64_CAP=1 --riscv-no-aliases --show-encoding --show-inst < %s \
+// RUN: | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ,CHECK-ASM,CHECK-CAP,CHECK-CAP-ASM-AND-OBJ %s
+// RUN: llvm-mc --filetype=obj --triple=riscv64 --mattr=+zca,+zcb,+zcd,+f,+d,+zfh,+xllvmrvyipm --defsym=RV64=1 --riscv-add-build-attributes < %s \
+// RUN: | llvm-objdump --mattr=+xllvmrvyipm -M no-aliases -d --no-print-imm-hex - | FileCheck %s --check-prefixes=CHECK-ASM-AND-OBJ,CHECK-INT-ASM-AND-OBJ
+// RUN: llvm-mc --filetype=obj --triple=riscv64 --mattr=+zca,+zcb,+f,+d,+zfh,+experimental-y --defsym=RVY=1 --defsym=RV64=1 --defsym=RV64_CAP=1 --riscv-add-build-attributes < %s \
+// RUN: | llvm-objdump -M no-aliases -d --no-print-imm-hex - | FileCheck %s --check-prefixes=CHECK-ASM-AND-OBJ,CHECK-CAP-ASM-AND-OBJ
+
+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-INT-NEXT: # <MCOperand Reg:X10>
+// CHECK-CAP-NEXT: # <MCOperand Reg:X10_Y>
+// CHECK-INT-NEXT: # <MCOperand Reg:X2>
+// CHECK-CAP-NEXT: # <MCOperand Reg:X2_Y>
+// CHECK-ASM-NEXT: # <MCOperand Imm: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-INT-NEXT: # <MCOperand Reg:X2>
+// CHECK-CAP-NEXT: # <MCOperand Reg:X2_Y>
+// CHECK-INT-NEXT: # <MCOperand Reg:X2>
+// CHECK-CAP-NEXT: # <MCOperand Reg:X2_Y>
+// CHECK-ASM-NEXT: # <MCOperand Imm:16>>
+
+addi a0, sp, 12
+// CHECK-INT-ASM-AND-OBJ: c.addi4spn a0, sp, 12
+// CHECK-INT-SAME: # encoding: [0x68,0x00]
+// CHECK-CAP-ASM-AND-OBJ: addi a0, sp, 12
+// CHECK-CAP-SAME: # encoding: [0x13,0x05,0xc1,0x00]
+// CHECK-INT-NEXT: # <MCInst #[[#]] C_ADDI4SPN{{$}}
+// CHECK-CAP-NEXT: # <MCInst #[[#]] ADDI{{$}}
+// CHECK-ASM-NEXT: # <MCOperand Reg:X10>
+// CHECK-ASM-NEXT: # <MCOperand Reg:X2>
+// CHECK-ASM-NEXT: # <MCOperand Imm:12>>
+
+yaddi a0, sp, 12
+// CHECK-INT-ASM-AND-OBJ: yaddi a0, sp, 12
+// CHECK-INT-SAME: # encoding: [0x7b,0x45,0xc1,0x00]
+// 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-ASM-NEXT: # <MCOperand Reg:X10_Y>
+// CHECK-ASM-NEXT: # <MCOperand Reg:X2_Y>
+// CHECK-ASM-NEXT: # <MCOperand Imm:12>>
+
+yaddi sp, sp, 16
+// CHECK-INT-ASM-AND-OBJ: yaddi sp, sp, 16
+// CHECK-INT-SAME: # encoding: [0x7b,0x41,0x01,0x01]
+// 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-ASM-NEXT: # <MCOperand Reg:X2_Y>
+// CHECK-ASM-NEXT: # <MCOperand Reg:X2_Y>
+// CHECK-ASM-NEXT: # <MCOperand Imm:16>>
``````````
</details>
https://github.com/llvm/llvm-project/pull/203598
More information about the llvm-branch-commits
mailing list