On 7/15/2026 8:26 AM, Jin Ma wrote:
Epilogue stack ties referenced s0 without a frame pointer, making the
unsaved register ever live.  Regrename could then select it and
corrupt callee-saved state during exception unwinding.

The simpler fix of allowing equal operands in the existing pattern is
unsafe: copy propagation can fold stack_tie (sp, t3) used by stack
probing into stack_tie (sp, sp).  This removes t3 = sp while CFI
still names t3 as the CFA.
Presumably you mean it removes the CFI note that tells the unwinder to find the frame in t3 when we're in a probing loop?


Keep the two-register pattern distinct and add an SP-only form for
epilogue barriers.
It's not clear we really need an sp-only form for the epilogue barrier.  My recollection is the issues the stack tie is trying to fix are limited to cases where we have a frame pointer.  But I don't think having it is necessarily bad, just perhaps not strictly necessary.

gcc/ChangeLog:

        * config/riscv/riscv-sr.cc (riscv_sr_match_epilogue): Accept
        SP-only stack ties.
        * config/riscv/riscv.cc (riscv_emit_stack_tie): Use parameterized
        generators and emit SP-only ties.
        (riscv_expand_epilogue): Use SP ties without a frame pointer.
        * config/riscv/riscv.md (@stack_tie<mode>): Use a parameterized name.
        (@stack_tie_sp<mode>): New pattern.

gcc/testsuite/ChangeLog:

        * g++.target/riscv/stack-tie-unwind.C: New test.
        * gcc.target/riscv/stack-tie-no-fp.c: New test.
@@ -9856,10 +9856,17 @@ riscv_adjust_multi_push_cfi_prologue (int saved_size)
  static void
  riscv_emit_stack_tie (rtx reg)
  {
-  if (Pmode == SImode)
-    emit_insn (gen_stack_tiesi (stack_pointer_rtx, reg));
+  /* A frame-pointer tie requires a saved frame pointer.  */
+  if (REG_P (reg)
+      && REGNO (reg) == HARD_FRAME_POINTER_REGNUM)
+    gcc_assert (frame_pointer_needed
+               && (cfun->machine->frame.mask
+                   & (1U << HARD_FRAME_POINTER_REGNUM)));
In general HOST_WIDE_INT_1U rather than 1U; however, in this case 1U is correct because the mask
field is just an unsigned int.

Anyway, this is probably OK, though I do want to clarify the first two questions/comments before we push it.

jeff

Reply via email to