Skip to content

[RISCV] Loosen the requirement of shadow stack codegen to Zimop #152251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

jaidTw
Copy link
Contributor

@jaidTw jaidTw commented Aug 6, 2025

Zicfiss (Shadow Stack) instructions are implemented using the encoding space defined in the "Zimop" May-Be-Operations Extension, where the instruction behaviors turn into NOP if Zimop is implemented but the redefining extension does not present.
This means we can safely loosen the codegen requirement of shadow stack to Zimop, in that those processors with Zimop but no Zicfiss can still execute the instructions without problem.

This patch

  1. Modify the requirement predicate for shadow stack instructions, setup a new DecoderTableZicfiss32 and favor it over the DecoderTable32, thus they will only be decoded as shadow stack instructions if Zicfiss is specified in the disassembler, and fallback to mop instructions.
  2. Loosen the hardware shadow stack codegen in RISCVFrameLoweriing from checking Zicfiss to Zimop

@llvmbot llvmbot added backend:RISC-V llvm:mc Machine (object) code labels Aug 6, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 6, 2025

@llvm/pr-subscribers-mc

Author: Jesse Huang (jaidTw)

Changes

Zicfiss (Shadow Stack) instructions are implemented using the encoding space defined in the "Zimop" May-Be-Operations Extension, where the instruction behaviors turn into NOP if Zimop is implemented but the redefining extension does not present.
This means we can safely loosen the codegen requirement of shadow stack to Zimop, in that those processors with Zimop but no Zicfiss can still execute the instructions without problem.

This patches

  1. Modify the requirement predicate for shadow stack instructions, setup a new DecoderTableZicfiss32 and favor it over the DecoderTable32, thus they will only be decoded as shadow stack instructions if Zicfiss is specified in the disassembler, and fallback to mop instructions.
  2. Loosen the hardware shadow stack codegen in RISCVFrameLoweriing from checking Zicfiss to Zimop

Full diff: https://github.com/llvm/llvm-project/pull/152251.diff

6 Files Affected:

  • (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+3-1)
  • (modified) llvm/lib/Target/RISCV/RISCVFrameLowering.cpp (+4-2)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td (+9-8)
  • (modified) llvm/test/CodeGen/RISCV/shadowcallstack.ll (+2-2)
  • (modified) llvm/test/MC/RISCV/compressed-zicfiss.s (+8-8)
  • (modified) llvm/test/MC/RISCV/zicfiss-valid.s (+17-17)
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 67cc01e647a04..b981873989f31 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -693,6 +693,8 @@ static constexpr DecoderListEntry DecoderList32[]{
     {DecoderTableXCV32, XCVFeatureGroup, "CORE-V extensions"},
     {DecoderTableXqci32, XqciFeatureGroup, "Qualcomm uC Extensions"},
     {DecoderTableXRivos32, XRivosFeatureGroup, "Rivos"},
+    // DecoderTableZicfiss32 must be checked before DecoderTable32.
+    {DecoderTableZicfiss32, {RISCV::FeatureStdExtZicfiss}, "Zicfiss (Shadow stack)"},
     {DecoderTable32, {}, "standard 32-bit instructions"},
     {DecoderTableRV32Only32, {}, "RV32-only standard 32-bit instructions"},
     {DecoderTableZfinx32, {}, "Zfinx (Float in Integer)"},
@@ -738,7 +740,7 @@ static constexpr DecoderListEntry DecoderList16[]{
     {DecoderTableXwchc16, {RISCV::FeatureVendorXwchc}, "WCH QingKe XW"},
     // Standard Extensions
     // DecoderTableZicfiss16 must be checked before DecoderTable16.
-    {DecoderTableZicfiss16, {}, "Zicfiss (Shadow Stack 16-bit)"},
+    {DecoderTableZicfiss16, {RISCV::FeatureStdExtZicfiss}, "Zicfiss (Shadow Stack 16-bit)"},
     {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/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 9fc0d815ceee3..16392510f5e61 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)
@@ -123,6 +123,7 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
     return;
 
   const RISCVInstrInfo *TII = STI.getInstrInfo();
+  // Prefer HW shadow stack over SW shadow stack.
   if (HasHWShadowStack) {
     BuildMI(MBB, MI, DL, TII->get(RISCV::SSPUSH)).addReg(RAReg);
     return;
@@ -172,7 +173,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)
@@ -185,6 +186,7 @@ static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB,
     return;
 
   const RISCVInstrInfo *TII = STI.getInstrInfo();
+  // Prefer HW shadow stack over SW shadow stack.
   if (HasHWShadowStack) {
     BuildMI(MBB, MI, DL, TII->get(RISCV::SSPOPCHK)).addReg(RAReg);
     return;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td
index 49a57f86cccd6..9618bf3f6dab9 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td
@@ -24,7 +24,8 @@ class RVC_SSInst<bits<5> rs1val, RegisterClass reg_class, string opcodestr> :
 // Instructions
 //===----------------------------------------------------------------------===//
 
-let Predicates = [HasStdExtZicfiss] in {
+let Predicates = [HasStdExtZimop],
+    DecoderNamespace = "Zicfiss" in {
 let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
 def SSPOPCHK : RVInstI<0b100, OPC_SYSTEM, (outs), (ins GPRX1X5:$rs1), "sspopchk",
                        "$rs1"> {
@@ -45,28 +46,28 @@ def SSPUSH : RVInstR<0b1100111, 0b100, OPC_SYSTEM, (outs), (ins GPRX1X5:$rs2),
   let rd = 0b00000;
   let rs1 = 0b00000;
 }
-} // Predicates = [HasStdExtZicfiss]
+} // Predicates = [HasStdExtZimop]
 
-let Predicates = [HasStdExtZicfiss, HasStdExtZcmop],
+let Predicates = [HasStdExtZcmop],
     DecoderNamespace = "Zicfiss" in {
 let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
 def C_SSPUSH : RVC_SSInst<0b00001, GPRX1, "c.sspush">;
 
 let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
 def C_SSPOPCHK : RVC_SSInst<0b00101, GPRX5, "c.sspopchk">;
-} // Predicates = [HasStdExtZicfiss, HasStdExtZcmop]
+} // Predicates = [HasStdExtZcmop]
 
-let Predicates = [HasStdExtZicfiss] in
+let Predicates = [HasStdExtZimop], DecoderNamespace = "Zicfiss" in
 defm SSAMOSWAP_W  : AMO_rr_aq_rl<0b01001, 0b010, "ssamoswap.w">;
 
-let Predicates = [HasStdExtZicfiss, IsRV64] in
+let Predicates = [HasStdExtZimop, IsRV64], DecoderNamespace = "Zicfiss" in
 defm SSAMOSWAP_D  : AMO_rr_aq_rl<0b01001, 0b011, "ssamoswap.d">;
 
 //===----------------------------------------------------------------------===/
 // Compress Instruction tablegen backend.
 //===----------------------------------------------------------------------===//
 
-let Predicates = [HasStdExtZicfiss, HasStdExtZcmop] in {
+let Predicates = [HasStdExtZcmop] in {
 def : CompressPat<(SSPUSH X1), (C_SSPUSH X1)>;
 def : CompressPat<(SSPOPCHK X5), (C_SSPOPCHK X5)>;
-} // Predicates = [HasStdExtZicfiss, HasStdExtZcmop]
+} // Predicates = [HasStdExtZcmop]
diff --git a/llvm/test/CodeGen/RISCV/shadowcallstack.ll b/llvm/test/CodeGen/RISCV/shadowcallstack.ll
index 03acd9491fed8..cab3d641d49d9 100644
--- a/llvm/test/CodeGen/RISCV/shadowcallstack.ll
+++ b/llvm/test/CodeGen/RISCV/shadowcallstack.ll
@@ -3,9 +3,9 @@
 ; RUN:   | FileCheck %s --check-prefix=RV32
 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s --check-prefix=RV64
-; RUN: llc -mtriple=riscv32 -mattr=+experimental-zicfiss < %s \
+; RUN: llc -mtriple=riscv32 -mattr=+zimop < %s \
 ; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=RV32-ZICFISS
-; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicfiss < %s \
+; RUN: llc -mtriple=riscv64 -mattr=+zimop < %s \
 ; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=RV64-ZICFISS
 
 define void @f1() shadowcallstack {
diff --git a/llvm/test/MC/RISCV/compressed-zicfiss.s b/llvm/test/MC/RISCV/compressed-zicfiss.s
index 7d387b257b7b4..acedee587f3e8 100644
--- a/llvm/test/MC/RISCV/compressed-zicfiss.s
+++ b/llvm/test/MC/RISCV/compressed-zicfiss.s
@@ -14,40 +14,40 @@
 
 # CHECK-ASM-AND-OBJ: c.sspopchk t0
 # CHECK-ASM: encoding: [0x81,0x62]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspopchk x5
 
 # CHECK-ASM-AND-OBJ: c.sspopchk t0
 # CHECK-ASM: encoding: [0x81,0x62]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspopchk t0
 
 # CHECK-ASM-AND-OBJ: c.sspush ra
 # CHECK-ASM: encoding: [0x81,0x60]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspush x1
 
 # CHECK-ASM-AND-OBJ: c.sspush ra
 # CHECK-ASM: encoding: [0x81,0x60]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspush ra
 
 # CHECK-ASM-AND-OBJ: c.sspush ra
 # CHECK-ASM: encoding: [0x81,0x60]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations), 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations){{$}}
 c.sspush x1
 
 # CHECK-ASM-AND-OBJ: c.sspush ra
 # CHECK-ASM: encoding: [0x81,0x60]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations), 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations){{$}}
 c.sspush ra
 
 # CHECK-ASM-AND-OBJ: c.sspopchk t0
 # CHECK-ASM: encoding: [0x81,0x62]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations), 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations){{$}}
 c.sspopchk x5
 
 # CHECK-ASM-AND-OBJ: c.sspopchk t0
 # CHECK-ASM: encoding: [0x81,0x62]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations), 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations){{$}}
 c.sspopchk t0
diff --git a/llvm/test/MC/RISCV/zicfiss-valid.s b/llvm/test/MC/RISCV/zicfiss-valid.s
index 5b2ab8d326651..376e971116d67 100644
--- a/llvm/test/MC/RISCV/zicfiss-valid.s
+++ b/llvm/test/MC/RISCV/zicfiss-valid.s
@@ -16,87 +16,87 @@
 
 # CHECK-ASM-AND-OBJ: sspopchk ra
 # CHECK-ASM: encoding: [0x73,0xc0,0xc0,0xcd]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspopchk x1
 
 # CHECK-ASM-AND-OBJ: sspopchk ra
 # CHECK-ASM: encoding: [0x73,0xc0,0xc0,0xcd]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspopchk ra
 
 # CHECK-ASM-AND-OBJ: sspopchk t0
 # CHECK-ASM: encoding: [0x73,0xc0,0xc2,0xcd]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspopchk x5
 
 # CHECK-ASM-AND-OBJ: sspopchk t0
 # CHECK-ASM: encoding: [0x73,0xc0,0xc2,0xcd]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspopchk t0
 
 # CHECK-ASM-AND-OBJ: sspush ra
 # CHECK-ASM: encoding: [0x73,0x40,0x10,0xce]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspush x1
 
 # CHECK-ASM-AND-OBJ: sspush ra
 # CHECK-ASM: encoding: [0x73,0x40,0x10,0xce]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspush ra
 
 # check-asm-and-obj: sspush t0
 # check-asm: encoding: [0x73,0x40,0x50,0xce]
-# check-no-ext: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# check-no-ext: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspush x5
 
 # check-asm-and-obj: sspush t0
 # check-asm: encoding: [0x73,0x40,0x50,0xce]
-# check-no-ext: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# check-no-ext: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspush t0
 
 # CHECK-ASM-AND-OBJ: ssrdp ra
 # CHECK-ASM: encoding: [0xf3,0x40,0xc0,0xcd]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssrdp ra
 
 # CHECK-ASM-AND-OBJ: ssamoswap.w a4, ra, (s0)
 # CHECK-ASM: encoding: [0x2f,0x27,0x14,0x48]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.w a4, ra, (s0)
 
 # CHECK-ASM-AND-OBJ: ssamoswap.w.aq a4, ra, (s0)
 # CHECK-ASM: encoding: [0x2f,0x27,0x14,0x4c]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.w.aq a4, ra, (s0)
 
 # CHECK-ASM-AND-OBJ: ssamoswap.w.rl a4, ra, (s0)
 # CHECK-ASM: encoding: [0x2f,0x27,0x14,0x4a]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.w.rl a4, ra, (s0)
 
 # CHECK-ASM-AND-OBJ: ssamoswap.w.aqrl a4, ra, (s0)
 # CHECK-ASM: encoding: [0x2f,0x27,0x14,0x4e]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.w.aqrl a4, ra, (s0)
 
 .ifdef RV64
 # CHECK-ASM-AND-OBJ-RV64: ssamoswap.d a4, ra, (s0)
 # CHECK-ASM-RV64: encoding: [0x2f,0x37,0x14,0x48]
-# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.d a4, ra, (s0)
 
 # CHECK-ASM-AND-OBJ-RV64: ssamoswap.d.aq a4, ra, (s0)
 # CHECK-ASM-RV64: encoding: [0x2f,0x37,0x14,0x4c]
-# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.d.aq a4, ra, (s0)
 
 # CHECK-ASM-AND-OBJ-RV64: ssamoswap.d.rl a4, ra, (s0)
 # CHECK-ASM-RV64: encoding: [0x2f,0x37,0x14,0x4a]
-# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.d.rl a4, ra, (s0)
 
 # CHECK-ASM-AND-OBJ-RV64: ssamoswap.d.aqrl a4, ra, (s0)
 # CHECK-ASM-RV64: encoding: [0x2f,0x37,0x14,0x4e]
-# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.d.aqrl a4, ra, (s0)
 .endif

@llvmbot
Copy link
Member

llvmbot commented Aug 6, 2025

@llvm/pr-subscribers-backend-risc-v

Author: Jesse Huang (jaidTw)

Changes

Zicfiss (Shadow Stack) instructions are implemented using the encoding space defined in the "Zimop" May-Be-Operations Extension, where the instruction behaviors turn into NOP if Zimop is implemented but the redefining extension does not present.
This means we can safely loosen the codegen requirement of shadow stack to Zimop, in that those processors with Zimop but no Zicfiss can still execute the instructions without problem.

This patches

  1. Modify the requirement predicate for shadow stack instructions, setup a new DecoderTableZicfiss32 and favor it over the DecoderTable32, thus they will only be decoded as shadow stack instructions if Zicfiss is specified in the disassembler, and fallback to mop instructions.
  2. Loosen the hardware shadow stack codegen in RISCVFrameLoweriing from checking Zicfiss to Zimop

Full diff: https://github.com/llvm/llvm-project/pull/152251.diff

6 Files Affected:

  • (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+3-1)
  • (modified) llvm/lib/Target/RISCV/RISCVFrameLowering.cpp (+4-2)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td (+9-8)
  • (modified) llvm/test/CodeGen/RISCV/shadowcallstack.ll (+2-2)
  • (modified) llvm/test/MC/RISCV/compressed-zicfiss.s (+8-8)
  • (modified) llvm/test/MC/RISCV/zicfiss-valid.s (+17-17)
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 67cc01e647a04..b981873989f31 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -693,6 +693,8 @@ static constexpr DecoderListEntry DecoderList32[]{
     {DecoderTableXCV32, XCVFeatureGroup, "CORE-V extensions"},
     {DecoderTableXqci32, XqciFeatureGroup, "Qualcomm uC Extensions"},
     {DecoderTableXRivos32, XRivosFeatureGroup, "Rivos"},
+    // DecoderTableZicfiss32 must be checked before DecoderTable32.
+    {DecoderTableZicfiss32, {RISCV::FeatureStdExtZicfiss}, "Zicfiss (Shadow stack)"},
     {DecoderTable32, {}, "standard 32-bit instructions"},
     {DecoderTableRV32Only32, {}, "RV32-only standard 32-bit instructions"},
     {DecoderTableZfinx32, {}, "Zfinx (Float in Integer)"},
@@ -738,7 +740,7 @@ static constexpr DecoderListEntry DecoderList16[]{
     {DecoderTableXwchc16, {RISCV::FeatureVendorXwchc}, "WCH QingKe XW"},
     // Standard Extensions
     // DecoderTableZicfiss16 must be checked before DecoderTable16.
-    {DecoderTableZicfiss16, {}, "Zicfiss (Shadow Stack 16-bit)"},
+    {DecoderTableZicfiss16, {RISCV::FeatureStdExtZicfiss}, "Zicfiss (Shadow Stack 16-bit)"},
     {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/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 9fc0d815ceee3..16392510f5e61 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)
@@ -123,6 +123,7 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
     return;
 
   const RISCVInstrInfo *TII = STI.getInstrInfo();
+  // Prefer HW shadow stack over SW shadow stack.
   if (HasHWShadowStack) {
     BuildMI(MBB, MI, DL, TII->get(RISCV::SSPUSH)).addReg(RAReg);
     return;
@@ -172,7 +173,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)
@@ -185,6 +186,7 @@ static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB,
     return;
 
   const RISCVInstrInfo *TII = STI.getInstrInfo();
+  // Prefer HW shadow stack over SW shadow stack.
   if (HasHWShadowStack) {
     BuildMI(MBB, MI, DL, TII->get(RISCV::SSPOPCHK)).addReg(RAReg);
     return;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td
index 49a57f86cccd6..9618bf3f6dab9 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td
@@ -24,7 +24,8 @@ class RVC_SSInst<bits<5> rs1val, RegisterClass reg_class, string opcodestr> :
 // Instructions
 //===----------------------------------------------------------------------===//
 
-let Predicates = [HasStdExtZicfiss] in {
+let Predicates = [HasStdExtZimop],
+    DecoderNamespace = "Zicfiss" in {
 let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
 def SSPOPCHK : RVInstI<0b100, OPC_SYSTEM, (outs), (ins GPRX1X5:$rs1), "sspopchk",
                        "$rs1"> {
@@ -45,28 +46,28 @@ def SSPUSH : RVInstR<0b1100111, 0b100, OPC_SYSTEM, (outs), (ins GPRX1X5:$rs2),
   let rd = 0b00000;
   let rs1 = 0b00000;
 }
-} // Predicates = [HasStdExtZicfiss]
+} // Predicates = [HasStdExtZimop]
 
-let Predicates = [HasStdExtZicfiss, HasStdExtZcmop],
+let Predicates = [HasStdExtZcmop],
     DecoderNamespace = "Zicfiss" in {
 let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
 def C_SSPUSH : RVC_SSInst<0b00001, GPRX1, "c.sspush">;
 
 let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
 def C_SSPOPCHK : RVC_SSInst<0b00101, GPRX5, "c.sspopchk">;
-} // Predicates = [HasStdExtZicfiss, HasStdExtZcmop]
+} // Predicates = [HasStdExtZcmop]
 
-let Predicates = [HasStdExtZicfiss] in
+let Predicates = [HasStdExtZimop], DecoderNamespace = "Zicfiss" in
 defm SSAMOSWAP_W  : AMO_rr_aq_rl<0b01001, 0b010, "ssamoswap.w">;
 
-let Predicates = [HasStdExtZicfiss, IsRV64] in
+let Predicates = [HasStdExtZimop, IsRV64], DecoderNamespace = "Zicfiss" in
 defm SSAMOSWAP_D  : AMO_rr_aq_rl<0b01001, 0b011, "ssamoswap.d">;
 
 //===----------------------------------------------------------------------===/
 // Compress Instruction tablegen backend.
 //===----------------------------------------------------------------------===//
 
-let Predicates = [HasStdExtZicfiss, HasStdExtZcmop] in {
+let Predicates = [HasStdExtZcmop] in {
 def : CompressPat<(SSPUSH X1), (C_SSPUSH X1)>;
 def : CompressPat<(SSPOPCHK X5), (C_SSPOPCHK X5)>;
-} // Predicates = [HasStdExtZicfiss, HasStdExtZcmop]
+} // Predicates = [HasStdExtZcmop]
diff --git a/llvm/test/CodeGen/RISCV/shadowcallstack.ll b/llvm/test/CodeGen/RISCV/shadowcallstack.ll
index 03acd9491fed8..cab3d641d49d9 100644
--- a/llvm/test/CodeGen/RISCV/shadowcallstack.ll
+++ b/llvm/test/CodeGen/RISCV/shadowcallstack.ll
@@ -3,9 +3,9 @@
 ; RUN:   | FileCheck %s --check-prefix=RV32
 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s --check-prefix=RV64
-; RUN: llc -mtriple=riscv32 -mattr=+experimental-zicfiss < %s \
+; RUN: llc -mtriple=riscv32 -mattr=+zimop < %s \
 ; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=RV32-ZICFISS
-; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicfiss < %s \
+; RUN: llc -mtriple=riscv64 -mattr=+zimop < %s \
 ; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=RV64-ZICFISS
 
 define void @f1() shadowcallstack {
diff --git a/llvm/test/MC/RISCV/compressed-zicfiss.s b/llvm/test/MC/RISCV/compressed-zicfiss.s
index 7d387b257b7b4..acedee587f3e8 100644
--- a/llvm/test/MC/RISCV/compressed-zicfiss.s
+++ b/llvm/test/MC/RISCV/compressed-zicfiss.s
@@ -14,40 +14,40 @@
 
 # CHECK-ASM-AND-OBJ: c.sspopchk t0
 # CHECK-ASM: encoding: [0x81,0x62]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspopchk x5
 
 # CHECK-ASM-AND-OBJ: c.sspopchk t0
 # CHECK-ASM: encoding: [0x81,0x62]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspopchk t0
 
 # CHECK-ASM-AND-OBJ: c.sspush ra
 # CHECK-ASM: encoding: [0x81,0x60]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspush x1
 
 # CHECK-ASM-AND-OBJ: c.sspush ra
 # CHECK-ASM: encoding: [0x81,0x60]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspush ra
 
 # CHECK-ASM-AND-OBJ: c.sspush ra
 # CHECK-ASM: encoding: [0x81,0x60]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations), 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations){{$}}
 c.sspush x1
 
 # CHECK-ASM-AND-OBJ: c.sspush ra
 # CHECK-ASM: encoding: [0x81,0x60]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations), 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations){{$}}
 c.sspush ra
 
 # CHECK-ASM-AND-OBJ: c.sspopchk t0
 # CHECK-ASM: encoding: [0x81,0x62]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations), 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations){{$}}
 c.sspopchk x5
 
 # CHECK-ASM-AND-OBJ: c.sspopchk t0
 # CHECK-ASM: encoding: [0x81,0x62]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations), 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcmop' (Compressed May-Be-Operations){{$}}
 c.sspopchk t0
diff --git a/llvm/test/MC/RISCV/zicfiss-valid.s b/llvm/test/MC/RISCV/zicfiss-valid.s
index 5b2ab8d326651..376e971116d67 100644
--- a/llvm/test/MC/RISCV/zicfiss-valid.s
+++ b/llvm/test/MC/RISCV/zicfiss-valid.s
@@ -16,87 +16,87 @@
 
 # CHECK-ASM-AND-OBJ: sspopchk ra
 # CHECK-ASM: encoding: [0x73,0xc0,0xc0,0xcd]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspopchk x1
 
 # CHECK-ASM-AND-OBJ: sspopchk ra
 # CHECK-ASM: encoding: [0x73,0xc0,0xc0,0xcd]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspopchk ra
 
 # CHECK-ASM-AND-OBJ: sspopchk t0
 # CHECK-ASM: encoding: [0x73,0xc0,0xc2,0xcd]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspopchk x5
 
 # CHECK-ASM-AND-OBJ: sspopchk t0
 # CHECK-ASM: encoding: [0x73,0xc0,0xc2,0xcd]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspopchk t0
 
 # CHECK-ASM-AND-OBJ: sspush ra
 # CHECK-ASM: encoding: [0x73,0x40,0x10,0xce]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspush x1
 
 # CHECK-ASM-AND-OBJ: sspush ra
 # CHECK-ASM: encoding: [0x73,0x40,0x10,0xce]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspush ra
 
 # check-asm-and-obj: sspush t0
 # check-asm: encoding: [0x73,0x40,0x50,0xce]
-# check-no-ext: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# check-no-ext: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspush x5
 
 # check-asm-and-obj: sspush t0
 # check-asm: encoding: [0x73,0x40,0x50,0xce]
-# check-no-ext: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# check-no-ext: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 sspush t0
 
 # CHECK-ASM-AND-OBJ: ssrdp ra
 # CHECK-ASM: encoding: [0xf3,0x40,0xc0,0xcd]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssrdp ra
 
 # CHECK-ASM-AND-OBJ: ssamoswap.w a4, ra, (s0)
 # CHECK-ASM: encoding: [0x2f,0x27,0x14,0x48]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.w a4, ra, (s0)
 
 # CHECK-ASM-AND-OBJ: ssamoswap.w.aq a4, ra, (s0)
 # CHECK-ASM: encoding: [0x2f,0x27,0x14,0x4c]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.w.aq a4, ra, (s0)
 
 # CHECK-ASM-AND-OBJ: ssamoswap.w.rl a4, ra, (s0)
 # CHECK-ASM: encoding: [0x2f,0x27,0x14,0x4a]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.w.rl a4, ra, (s0)
 
 # CHECK-ASM-AND-OBJ: ssamoswap.w.aqrl a4, ra, (s0)
 # CHECK-ASM: encoding: [0x2f,0x27,0x14,0x4e]
-# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.w.aqrl a4, ra, (s0)
 
 .ifdef RV64
 # CHECK-ASM-AND-OBJ-RV64: ssamoswap.d a4, ra, (s0)
 # CHECK-ASM-RV64: encoding: [0x2f,0x37,0x14,0x48]
-# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.d a4, ra, (s0)
 
 # CHECK-ASM-AND-OBJ-RV64: ssamoswap.d.aq a4, ra, (s0)
 # CHECK-ASM-RV64: encoding: [0x2f,0x37,0x14,0x4c]
-# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.d.aq a4, ra, (s0)
 
 # CHECK-ASM-AND-OBJ-RV64: ssamoswap.d.rl a4, ra, (s0)
 # CHECK-ASM-RV64: encoding: [0x2f,0x37,0x14,0x4a]
-# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.d.rl a4, ra, (s0)
 
 # CHECK-ASM-AND-OBJ-RV64: ssamoswap.d.aqrl a4, ra, (s0)
 # CHECK-ASM-RV64: encoding: [0x2f,0x37,0x14,0x4e]
-# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+# CHECK-NO-EXT-RV64: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
 ssamoswap.d.aqrl a4, ra, (s0)
 .endif

Copy link

github-actions bot commented Aug 6, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@@ -14,40 +14,40 @@

# CHECK-ASM-AND-OBJ: c.sspopchk t0
# CHECK-ASM: encoding: [0x81,0x62]
# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
# CHECK-NO-EXT: error: instruction requires the following: 'Zimop' (May-Be-Operations){{$}}
Copy link
Contributor

@mylai-mtk mylai-mtk Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excuse me, but I would say that the original Zicfiss message should be kept intact. It should not be changed to Zimop nor Zcmop.

It looks like this test takes in Zicfiss insns and outputs its corresponding compressed form, and shouldn't the action of "taking in Zicfiss insns" require Zicfiss instead of Zimop? Zimop/Zcmop do not define these shadow stack insns and it should be an error to use these insns without Zicfiss.

@@ -123,6 +123,7 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
return;

const RISCVInstrInfo *TII = STI.getInstrInfo();
// Prefer HW shadow stack over SW shadow stack.
Copy link
Contributor

@mylai-mtk mylai-mtk Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think emitting Zimop/Zcmop insns that can be interpreted as Zicfiss insns is not the same as simply supporting Zicfiss insns, especially when Zicfiss is not enabled. The former is just using the trick that Zicfiss insns are encoded as MOP insns, so without Zicfiss enabled, what get emitted should actually be MOP insns that happen to have the same encoding as Zicfiss insns, but the insns are actually not and should not be treated as real Zicfiss insns in compiler pipelines, at least not without the assumption that they would only be interpreted as Zicfiss insns.

With this mindset, what I prefer would actually be to emit special insns (perhaps compiler-only pseudo insns, e.g. PseudoMOP_SSPUSH) that are enabled with MOP extensions, and they would be expanded into MOP insns that corresponds to Zicfiss insns later in the pipeline, when Zicfiss is not enabled. This way you don't need to loosen the predicates of Zicfiss insns to MOP extensions and it will be clean and clear that Zicfiss insns are only supported with Zicfiss extensions, especially considering that the predicates are often used in multiple places in surprising ways and sometimes we do not have the infrastructures to properly distinguish when we would like to have the looser predicates of MOP and other times we would like to have the formal predicates of Zicfiss.

jaidTw added 3 commits August 20, 2025 06:55
Loosen the hard requirement of shadow stack codegen to Zimop, and
emit mop/c.mop/zicfiss accordingly to the available extensions.
@jaidTw
Copy link
Contributor Author

jaidTw commented Aug 20, 2025

@mylai-mtk I have adopt your suggestion, while I don't see a way to output mop pseudos mnemonics in different form (shadow stack/mop) in assembly based on the presence of Zicfiss, it will still emit the shadow stack variants directly instead of pseudos if Zicfiss is present

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:RISC-V llvm:mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants