[llvm] [RISCV] Loosen the requirement of shadow stack codegen to Zimop (PR #152251)
Jesse Huang via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 25 22:21:20 PDT 2025
https://github.com/jaidTw updated https://github.com/llvm/llvm-project/pull/152251
>From 287accd76f245b563a221ecc147bb5e2570b1100 Mon Sep 17 00:00:00 2001
From: Jesse Huang <jesse.huang at sifive.com>
Date: Sun, 24 Aug 2025 03:05:18 -0700
Subject: [PATCH 1/2] [RISCV] Add Pseudo for MOPs that representing shadow
stack insns
---
llvm/lib/Target/RISCV/RISCVInstrInfo.td | 4 +++-
llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td | 15 +++++++++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 23f5a848137c4..df55ee9652fdf 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -2330,7 +2330,6 @@ include "RISCVInstrInfoZalasr.td"
include "RISCVInstrInfoZimop.td"
include "RISCVInstrInfoZicbo.td"
include "RISCVInstrInfoZicond.td"
-include "RISCVInstrInfoZicfiss.td"
include "RISCVInstrInfoZilsd.td"
// Scalar FP
@@ -2359,6 +2358,9 @@ include "RISCVInstrInfoZc.td"
include "RISCVInstrInfoZcmop.td"
include "RISCVInstrInfoZclsd.td"
+// Control Flow Integriy, this requires Zimop/Zcmop
+include "RISCVInstrInfoZicfiss.td"
+
// Short Forward Branch
include "RISCVInstrInfoSFB.td"
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td
index 49a57f86cccd6..50ebaa9951979 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td
@@ -62,6 +62,21 @@ defm SSAMOSWAP_W : AMO_rr_aq_rl<0b01001, 0b010, "ssamoswap.w">;
let Predicates = [HasStdExtZicfiss, IsRV64] in
defm SSAMOSWAP_D : AMO_rr_aq_rl<0b01001, 0b011, "ssamoswap.d">;
+let Predicates = [HasStdExtZimop] in {
+let hasSideEffects = 1, mayLoad = 0, mayStore = 1 in
+def PseudoMOP_SSPUSH : Pseudo<(outs), (ins GPRX1X5:$rs2), []>,
+ PseudoInstExpansion<(MOP_RR_7 X0, X0, GPR:$rs2)>;
+let hasSideEffects = 1, mayLoad = 1, mayStore = 0 in
+def PseudoMOP_SSPOPCHK : Pseudo<(outs), (ins GPRX1X5:$rs1), []>,
+ PseudoInstExpansion<(MOP_R_28 X0, GPR:$rs1)>;
+} // Predicates = [HasStdExtZimop]
+
+let Predicates = [HasStdExtZcmop] in {
+let Uses = [X1], hasSideEffects = 1, mayLoad = 0, mayStore = 1 in
+def PseudoMOP_C_SSPUSH : Pseudo<(outs), (ins), []>,
+ PseudoInstExpansion<(C_MOP_1)>;
+} // Predicates = [HasStdExtZcmop]
+
//===----------------------------------------------------------------------===/
// Compress Instruction tablegen backend.
//===----------------------------------------------------------------------===//
>From 3fb3743e97ea6cd9f8706e3b22db45b2073574b6 Mon Sep 17 00:00:00 2001
From: Jesse Huang <jesse.huang at sifive.com>
Date: Sun, 24 Aug 2025 03:06:54 -0700
Subject: [PATCH 2/2] [RISCV] Loosen the requirement of shadow stack codegen to
Zimop
---
llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 19 ++++++--
llvm/test/CodeGen/RISCV/shadowcallstack.ll | 48 ++++++++++----------
2 files changed, 39 insertions(+), 28 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 9fc0d815ceee3..0984da2b8f025 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -106,8 +106,14 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const DebugLoc &DL) {
const auto &STI = MF.getSubtarget<RISCVSubtarget>();
+ // We check Zimop instead of Zimop || Zcmop to determine whether HW shadow
+ // stack is available despite the fact that sspush/sspopchk both have a
+ // compressed form because if only Zcmop is available, we would need to
+ // reserve X5 due to c.sspopchk only takes X5 and we currently doesn't not
+ // support using X5 as the return address regsister.
+ // However, we can still aggressively use c.sspush x1 if zcmop is available.
bool HasHWShadowStack = MF.getFunction().hasFnAttribute("hw-shadow-stack") &&
- STI.hasStdExtZicfiss();
+ STI.hasStdExtZimop();
bool HasSWShadowStack =
MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack);
if (!HasHWShadowStack && !HasSWShadowStack)
@@ -124,7 +130,12 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
const RISCVInstrInfo *TII = STI.getInstrInfo();
if (HasHWShadowStack) {
- BuildMI(MBB, MI, DL, TII->get(RISCV::SSPUSH)).addReg(RAReg);
+ if (STI.hasStdExtZcmop()) {
+ static_assert(RAReg == RISCV::X1, "C.SSPUSH only accepts X1");
+ BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoMOP_C_SSPUSH));
+ } else {
+ BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoMOP_SSPUSH)).addReg(RAReg);
+ }
return;
}
@@ -172,7 +183,7 @@ static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB,
const DebugLoc &DL) {
const auto &STI = MF.getSubtarget<RISCVSubtarget>();
bool HasHWShadowStack = MF.getFunction().hasFnAttribute("hw-shadow-stack") &&
- STI.hasStdExtZicfiss();
+ STI.hasStdExtZimop();
bool HasSWShadowStack =
MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack);
if (!HasHWShadowStack && !HasSWShadowStack)
@@ -186,7 +197,7 @@ static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB,
const RISCVInstrInfo *TII = STI.getInstrInfo();
if (HasHWShadowStack) {
- BuildMI(MBB, MI, DL, TII->get(RISCV::SSPOPCHK)).addReg(RAReg);
+ BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoMOP_SSPOPCHK)).addReg(RAReg);
return;
}
diff --git a/llvm/test/CodeGen/RISCV/shadowcallstack.ll b/llvm/test/CodeGen/RISCV/shadowcallstack.ll
index 03acd9491fed8..5d4ecbf21790a 100644
--- a/llvm/test/CodeGen/RISCV/shadowcallstack.ll
+++ b/llvm/test/CodeGen/RISCV/shadowcallstack.ll
@@ -427,7 +427,7 @@ define i32 @f3_hw() "hw-shadow-stack" {
;
; RV32-ZICFISS-LABEL: f3_hw:
; RV32-ZICFISS: # %bb.0:
-; RV32-ZICFISS-NEXT: sspush ra
+; RV32-ZICFISS-NEXT: mop.rr.7 zero, zero, ra
; RV32-ZICFISS-NEXT: addi sp, sp, -16
; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 16
; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
@@ -437,12 +437,12 @@ define i32 @f3_hw() "hw-shadow-stack" {
; RV32-ZICFISS-NEXT: .cfi_restore ra
; RV32-ZICFISS-NEXT: addi sp, sp, 16
; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 0
-; RV32-ZICFISS-NEXT: sspopchk ra
+; RV32-ZICFISS-NEXT: mop.r.28 zero, ra
; RV32-ZICFISS-NEXT: ret
;
; RV64-ZICFISS-LABEL: f3_hw:
; RV64-ZICFISS: # %bb.0:
-; RV64-ZICFISS-NEXT: sspush ra
+; RV64-ZICFISS-NEXT: mop.rr.7 zero, zero, ra
; RV64-ZICFISS-NEXT: addi sp, sp, -16
; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 16
; RV64-ZICFISS-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
@@ -452,7 +452,7 @@ define i32 @f3_hw() "hw-shadow-stack" {
; RV64-ZICFISS-NEXT: .cfi_restore ra
; RV64-ZICFISS-NEXT: addi sp, sp, 16
; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 0
-; RV64-ZICFISS-NEXT: sspopchk ra
+; RV64-ZICFISS-NEXT: mop.r.28 zero, ra
; RV64-ZICFISS-NEXT: ret
%res = call i32 @bar()
%res1 = add i32 %res, 1
@@ -530,7 +530,7 @@ define i32 @f4_hw() "hw-shadow-stack" {
;
; RV32-ZICFISS-LABEL: f4_hw:
; RV32-ZICFISS: # %bb.0:
-; RV32-ZICFISS-NEXT: sspush ra
+; RV32-ZICFISS-NEXT: mop.rr.7 zero, zero, ra
; RV32-ZICFISS-NEXT: addi sp, sp, -16
; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 16
; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
@@ -561,12 +561,12 @@ define i32 @f4_hw() "hw-shadow-stack" {
; RV32-ZICFISS-NEXT: .cfi_restore s2
; RV32-ZICFISS-NEXT: addi sp, sp, 16
; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 0
-; RV32-ZICFISS-NEXT: sspopchk ra
+; RV32-ZICFISS-NEXT: mop.r.28 zero, ra
; RV32-ZICFISS-NEXT: ret
;
; RV64-ZICFISS-LABEL: f4_hw:
; RV64-ZICFISS: # %bb.0:
-; RV64-ZICFISS-NEXT: sspush ra
+; RV64-ZICFISS-NEXT: mop.rr.7 zero, zero, ra
; RV64-ZICFISS-NEXT: addi sp, sp, -32
; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 32
; RV64-ZICFISS-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
@@ -597,7 +597,7 @@ define i32 @f4_hw() "hw-shadow-stack" {
; RV64-ZICFISS-NEXT: .cfi_restore s2
; RV64-ZICFISS-NEXT: addi sp, sp, 32
; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 0
-; RV64-ZICFISS-NEXT: sspopchk ra
+; RV64-ZICFISS-NEXT: mop.r.28 zero, ra
; RV64-ZICFISS-NEXT: ret
%res1 = call i32 @bar()
%res2 = call i32 @bar()
@@ -630,24 +630,24 @@ define i32 @f5_hw() "hw-shadow-stack" nounwind {
;
; RV32-ZICFISS-LABEL: f5_hw:
; RV32-ZICFISS: # %bb.0:
-; RV32-ZICFISS-NEXT: sspush ra
+; RV32-ZICFISS-NEXT: mop.rr.7 zero, zero, ra
; RV32-ZICFISS-NEXT: addi sp, sp, -16
; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32-ZICFISS-NEXT: call bar
; RV32-ZICFISS-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32-ZICFISS-NEXT: addi sp, sp, 16
-; RV32-ZICFISS-NEXT: sspopchk ra
+; RV32-ZICFISS-NEXT: mop.r.28 zero, ra
; RV32-ZICFISS-NEXT: ret
;
; RV64-ZICFISS-LABEL: f5_hw:
; RV64-ZICFISS: # %bb.0:
-; RV64-ZICFISS-NEXT: sspush ra
+; RV64-ZICFISS-NEXT: mop.rr.7 zero, zero, ra
; RV64-ZICFISS-NEXT: addi sp, sp, -16
; RV64-ZICFISS-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64-ZICFISS-NEXT: call bar
; RV64-ZICFISS-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64-ZICFISS-NEXT: addi sp, sp, 16
-; RV64-ZICFISS-NEXT: sspopchk ra
+; RV64-ZICFISS-NEXT: mop.r.28 zero, ra
; RV64-ZICFISS-NEXT: ret
%res = call i32 @bar()
%res1 = add i32 %res, 1
@@ -734,7 +734,7 @@ define i32 @f3_both() "hw-shadow-stack" shadowcallstack {
;
; RV32-ZICFISS-LABEL: f3_both:
; RV32-ZICFISS: # %bb.0:
-; RV32-ZICFISS-NEXT: sspush ra
+; RV32-ZICFISS-NEXT: mop.rr.7 zero, zero, ra
; RV32-ZICFISS-NEXT: addi sp, sp, -16
; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 16
; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
@@ -744,12 +744,12 @@ define i32 @f3_both() "hw-shadow-stack" shadowcallstack {
; RV32-ZICFISS-NEXT: .cfi_restore ra
; RV32-ZICFISS-NEXT: addi sp, sp, 16
; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 0
-; RV32-ZICFISS-NEXT: sspopchk ra
+; RV32-ZICFISS-NEXT: mop.r.28 zero, ra
; RV32-ZICFISS-NEXT: ret
;
; RV64-ZICFISS-LABEL: f3_both:
; RV64-ZICFISS: # %bb.0:
-; RV64-ZICFISS-NEXT: sspush ra
+; RV64-ZICFISS-NEXT: mop.rr.7 zero, zero, ra
; RV64-ZICFISS-NEXT: addi sp, sp, -16
; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 16
; RV64-ZICFISS-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
@@ -759,7 +759,7 @@ define i32 @f3_both() "hw-shadow-stack" shadowcallstack {
; RV64-ZICFISS-NEXT: .cfi_restore ra
; RV64-ZICFISS-NEXT: addi sp, sp, 16
; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 0
-; RV64-ZICFISS-NEXT: sspopchk ra
+; RV64-ZICFISS-NEXT: mop.r.28 zero, ra
; RV64-ZICFISS-NEXT: ret
%res = call i32 @bar()
%res1 = add i32 %res, 1
@@ -849,7 +849,7 @@ define i32 @f4_both() "hw-shadow-stack" shadowcallstack {
;
; RV32-ZICFISS-LABEL: f4_both:
; RV32-ZICFISS: # %bb.0:
-; RV32-ZICFISS-NEXT: sspush ra
+; RV32-ZICFISS-NEXT: mop.rr.7 zero, zero, ra
; RV32-ZICFISS-NEXT: addi sp, sp, -16
; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 16
; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
@@ -880,12 +880,12 @@ define i32 @f4_both() "hw-shadow-stack" shadowcallstack {
; RV32-ZICFISS-NEXT: .cfi_restore s2
; RV32-ZICFISS-NEXT: addi sp, sp, 16
; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 0
-; RV32-ZICFISS-NEXT: sspopchk ra
+; RV32-ZICFISS-NEXT: mop.r.28 zero, ra
; RV32-ZICFISS-NEXT: ret
;
; RV64-ZICFISS-LABEL: f4_both:
; RV64-ZICFISS: # %bb.0:
-; RV64-ZICFISS-NEXT: sspush ra
+; RV64-ZICFISS-NEXT: mop.rr.7 zero, zero, ra
; RV64-ZICFISS-NEXT: addi sp, sp, -32
; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 32
; RV64-ZICFISS-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
@@ -916,7 +916,7 @@ define i32 @f4_both() "hw-shadow-stack" shadowcallstack {
; RV64-ZICFISS-NEXT: .cfi_restore s2
; RV64-ZICFISS-NEXT: addi sp, sp, 32
; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 0
-; RV64-ZICFISS-NEXT: sspopchk ra
+; RV64-ZICFISS-NEXT: mop.r.28 zero, ra
; RV64-ZICFISS-NEXT: ret
%res1 = call i32 @bar()
%res2 = call i32 @bar()
@@ -957,24 +957,24 @@ define i32 @f5_both() "hw-shadow-stack" shadowcallstack nounwind {
;
; RV32-ZICFISS-LABEL: f5_both:
; RV32-ZICFISS: # %bb.0:
-; RV32-ZICFISS-NEXT: sspush ra
+; RV32-ZICFISS-NEXT: mop.rr.7 zero, zero, ra
; RV32-ZICFISS-NEXT: addi sp, sp, -16
; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32-ZICFISS-NEXT: call bar
; RV32-ZICFISS-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32-ZICFISS-NEXT: addi sp, sp, 16
-; RV32-ZICFISS-NEXT: sspopchk ra
+; RV32-ZICFISS-NEXT: mop.r.28 zero, ra
; RV32-ZICFISS-NEXT: ret
;
; RV64-ZICFISS-LABEL: f5_both:
; RV64-ZICFISS: # %bb.0:
-; RV64-ZICFISS-NEXT: sspush ra
+; RV64-ZICFISS-NEXT: mop.rr.7 zero, zero, ra
; RV64-ZICFISS-NEXT: addi sp, sp, -16
; RV64-ZICFISS-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64-ZICFISS-NEXT: call bar
; RV64-ZICFISS-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64-ZICFISS-NEXT: addi sp, sp, 16
-; RV64-ZICFISS-NEXT: sspopchk ra
+; RV64-ZICFISS-NEXT: mop.r.28 zero, ra
; RV64-ZICFISS-NEXT: ret
%res = call i32 @bar()
%res1 = add i32 %res, 1
More information about the llvm-commits
mailing list