[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 08:44:27 PDT 2025
https://github.com/jaidTw updated https://github.com/llvm/llvm-project/pull/152251
>From 44c10ccb83ee820de23e1af68e6692b7a84f0078 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/4] [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 8bd383033f11c..556d2bd88aa82 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -2320,7 +2320,6 @@ include "RISCVInstrInfoZalasr.td"
include "RISCVInstrInfoZimop.td"
include "RISCVInstrInfoZicbo.td"
include "RISCVInstrInfoZicond.td"
-include "RISCVInstrInfoZicfiss.td"
include "RISCVInstrInfoZilsd.td"
// Scalar FP
@@ -2349,6 +2348,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..aa1ed0e2883da 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 = 0, mayLoad = 0, mayStore = 1 in
+def PseudoMOP_SSPUSH : Pseudo<(outs), (ins GPRX1X5:$rs2), []>,
+ PseudoInstExpansion<(MOPRR7 X0, X0, GPR:$rs2)>;
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+def PseudoMOP_SSPOPCHK : Pseudo<(outs), (ins GPRX1X5:$rs1), []>,
+ PseudoInstExpansion<(MOPR28 X0, GPR:$rs1)>;
+} // Predicates = [HasStdExtZimop]
+
+let Predicates = [HasStdExtZcmop] in {
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
+def PseudoMOP_C_SSPUSH : Pseudo<(outs), (ins GPRX1:$ra), []>,
+ PseudoInstExpansion<(C_MOP1)>;
+} // Predicates = [HasStdExtZcmop]
+
//===----------------------------------------------------------------------===/
// Compress Instruction tablegen backend.
//===----------------------------------------------------------------------===//
>From da6abefd42d589d6cb827d447c519252f93741c6 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/4] [RISCV] Loosen the requirement of shadow stack codegen to
Zimop
---
llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 11 +++--
llvm/test/CodeGen/RISCV/shadowcallstack.ll | 48 ++++++++++----------
2 files changed, 31 insertions(+), 28 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 9fc0d815ceee3..f4ddbd2263308 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -107,7 +107,7 @@ static void emitSCSPrologue(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)
@@ -124,7 +124,10 @@ 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())
+ BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoMOP_C_SSPUSH)).addReg(RAReg);
+ else
+ BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoMOP_SSPUSH)).addReg(RAReg);
return;
}
@@ -172,7 +175,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 +189,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
>From 5a54452fe13e811a80bd09bbad897574034e456a Mon Sep 17 00:00:00 2001
From: Jesse Huang <jesse.huang at sifive.com>
Date: Mon, 25 Aug 2025 01:24:39 -0700
Subject: [PATCH 3/4] !fixup Ensure the operand of c.sspush is X1
---
llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 6 ++++--
llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td | 4 ++--
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index f4ddbd2263308..cb2c958a418be 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -124,8 +124,10 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
const RISCVInstrInfo *TII = STI.getInstrInfo();
if (HasHWShadowStack) {
- if (STI.hasStdExtZcmop())
- BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoMOP_C_SSPUSH)).addReg(RAReg);
+ if (STI.hasStdExtZcmop()) {
+ static_assert(RAReg == RISCV::X1);
+ BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoMOP_C_SSPUSH));
+ }
else
BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoMOP_SSPUSH)).addReg(RAReg);
return;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td
index aa1ed0e2883da..69120ec468cd6 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td
@@ -72,8 +72,8 @@ def PseudoMOP_SSPOPCHK : Pseudo<(outs), (ins GPRX1X5:$rs1), []>,
} // Predicates = [HasStdExtZimop]
let Predicates = [HasStdExtZcmop] in {
-let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
-def PseudoMOP_C_SSPUSH : Pseudo<(outs), (ins GPRX1:$ra), []>,
+let Uses = [X1], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
+def PseudoMOP_C_SSPUSH : Pseudo<(outs), (ins), []>,
PseudoInstExpansion<(C_MOP1)>;
} // Predicates = [HasStdExtZcmop]
>From 7b976647cd64e0d3f2ceb820875264b27b1bfceb Mon Sep 17 00:00:00 2001
From: Jesse Huang <jesse.huang at sifive.com>
Date: Mon, 25 Aug 2025 01:33:26 -0700
Subject: [PATCH 4/4] !fixup Add comment for extension checking
---
llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index cb2c958a418be..62966ab565ca7 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -106,6 +106,12 @@ 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.hasStdExtZimop();
bool HasSWShadowStack =
More information about the llvm-commits
mailing list