https://gcc.gnu.org/g:976bba902f3a8146b7ca5b352795977bc9179132
commit r17-425-g976bba902f3a8146b7ca5b352795977bc9179132 Author: Michiel Derhaeg <[email protected]> Date: Sat May 9 11:22:07 2026 -0600 [PATCH] RISC-V: Don't emit cm.popret when zcmp + zicfiss is enabled [PR125217] Currently when -fcf-protection=return and zcmp are enabled this code is generated: sspush ra cm.push {ra, s0-s1}, -32 .. cm.popret {ra, s0-s1}, 32 riscv_expand_epilogue will skip emitting sspopchk when cm.popret is emitted. After this patch we will no longer emit cm.popret and instead use cm.pop + sspopchk + a regular return: sspush ra cm.push {ra, s0-s1}, -32 .. cm.pop {ra, s0-s1}, 32 sspopchk ra jr ra Regtested for rv32g & rv64g. PR target/125217 gcc/ChangeLog: * config/riscv/riscv.cc (riscv_gen_multi_pop_insn): Rename variable. (riscv_expand_epilogue): Don't emit cm.popret with shadow stack. gcc/testsuite/ChangeLog: * gcc.target/riscv/ssp-zcmp.c: New test. Diff: --- gcc/config/riscv/riscv.cc | 24 +++++++++--------- gcc/testsuite/gcc.target/riscv/ssp-zcmp.c | 42 +++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 108f1c4b3cfd..681b816d248e 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -10123,13 +10123,13 @@ riscv_adjust_libcall_cfi_epilogue () } static void -riscv_gen_multi_pop_insn (bool use_multi_pop_normal, unsigned mask, +riscv_gen_multi_pop_insn (bool use_popret, unsigned mask, unsigned multipop_size) { rtx insn; unsigned regs_count = riscv_multi_push_regs_count (mask); - if (!use_multi_pop_normal) + if (!use_popret) insn = emit_insn ( riscv_gen_multi_push_pop_insn (POP_IDX, multipop_size, regs_count)); else @@ -10158,11 +10158,8 @@ riscv_expand_epilogue (int style) unsigned fmask = frame->fmask; unsigned mask_fprs_push = 0; poly_int64 step2 = 0; - bool use_multi_pop_normal - = ((style == NORMAL_RETURN) && riscv_use_multi_push (frame)); - bool use_multi_pop_sibcall - = ((style == SIBCALL_RETURN) && riscv_use_multi_push (frame)); - bool use_multi_pop = use_multi_pop_normal || use_multi_pop_sibcall; + bool use_multi_pop = ((style == NORMAL_RETURN) || (style == SIBCALL_RETURN)) + && riscv_use_multi_push (frame); bool use_restore_libcall = !use_multi_pop @@ -10430,9 +10427,10 @@ riscv_expand_epilogue (int style) /* Undo the above fib. */ frame->mask = mask; frame->fmask = fmask; - riscv_gen_multi_pop_insn (use_multi_pop_normal, frame->mask, - multipop_size); - if (use_multi_pop_normal) + bool use_popret = style == NORMAL_RETURN + && !need_shadow_stack_push_pop_p (); + riscv_gen_multi_pop_insn (use_popret, frame->mask, multipop_size); + if (use_popret) return; } else if (use_restore_libcall) @@ -10456,7 +10454,8 @@ riscv_expand_epilogue (int style) { if (BITSET_P (cfun->machine->frame.mask, RETURN_ADDR_REGNUM) && style != SIBCALL_RETURN - && !cfun->machine->interrupt_handler_p) + && !cfun->machine->interrupt_handler_p + && !use_multi_pop) emit_insn (gen_sspopchk (Pmode, t0)); else emit_insn (gen_sspopchk (Pmode, ra)); @@ -10483,7 +10482,8 @@ riscv_expand_epilogue (int style) if (need_shadow_stack_push_pop_p () && !((style == EXCEPTION_RETURN) && crtl->calls_eh_return) && BITSET_P (cfun->machine->frame.mask, RETURN_ADDR_REGNUM) - && !cfun->machine->interrupt_handler_p) + && !cfun->machine->interrupt_handler_p + && !use_multi_pop) emit_jump_insn (gen_simple_return_internal (t0)); else emit_jump_insn (gen_simple_return_internal (ra)); diff --git a/gcc/testsuite/gcc.target/riscv/ssp-zcmp.c b/gcc/testsuite/gcc.target/riscv/ssp-zcmp.c new file mode 100644 index 000000000000..096f1e50a58a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/ssp-zcmp.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -march=rv32g_zcmp_zcmop_zicfiss -mabi=ilp32d -fcf-protection=return" } */ +/* { dg-skip-if "needs -Os" { *-*-* } { "-O0" "-O1" "-O2" "-O3" "-Og" "-Oz" } { "" } } */ +/* { dg-final { check-function-bodies "**" "" } } */ +/* { dg-final { scan-assembler-not {cm\.popret} } } */ + +int printf (const char *, ...); + +/* +** printSomething: +** sspush ra +** ... +** cm\.push \{ra, s0-s2\}, -32 +** ... +** cm\.pop \{ra, s0-s2\}, 32 +** sspopchk ra +** jr ra +** ... +*/ +int printSomething (int arr[], int len) { + for (int i = 0; i < len; i++) + printf ("Val[%d]: %d\n", i, arr[i]); + return len; +} + +extern int sibcallee (int); +extern void other (void); + +/* +** sibcaller: +** sspush ra +** cm\.push \{ra\}, -32 +** ... +** cm\.pop \{ra\}, 32 +** ... +** sspopchk ra +** tail sibcallee +*/ +int sibcaller (int x) { + other (); + return sibcallee (x + 1); +}
