aarch64: Robustify stack tie handling

The SVE handling of stack clash protection copied the stack
pointer to X11 before the probe and set up X11 as the CFA
for unwind purposes:

    /* This is done to provide unwinding information for the stack
       adjustments we're about to do, however to prevent the optimizers
       from removing the R11 move and leaving the CFA note (which would be
       very wrong) we tie the old and new stack pointer together.
       The tie will expand to nothing but the optimizers will not touch
       the instruction.  */
    rtx stack_ptr_copy = gen_rtx_REG (Pmode, STACK_CLASH_SVE_CFA_REGNUM);
    emit_move_insn (stack_ptr_copy, stack_pointer_rtx);
    emit_insn (gen_stack_tie (stack_ptr_copy, stack_pointer_rtx));

    /* We want the CFA independent of the stack pointer for the
       duration of the loop.  */
    add_reg_note (insn, REG_CFA_DEF_CFA, stack_ptr_copy);
    RTX_FRAME_RELATED_P (insn) = 1;

-fcprop-registers is now smart enough to realise that X11 = SP,
replace X11 with SP in the stack tie, and delete the instruction
created above.

This patch tries to prevent that by making stack_tie fussy about
the register numbers.  It fixes failures in
gcc.target/aarch64/sve/pcs/stack_clash*.c.

gcc/
	* config/aarch64/aarch64.md (stack_tie): Hard-code the first
	register operand to the stack pointer.  Require the second register
	operand to have the number specified in a separate const_int operand.
	* config/aarch64/aarch64.cc (aarch64_emit_stack_tie): New function.
	(aarch64_allocate_and_probe_stack_space): Use it.
	(aarch64_expand_prologue, aarch64_expand_epilogue): Likewise.
	(aarch64_expand_epilogue): Likewise.
This commit is contained in:
Richard Sandiford 2023-06-20 21:48:38 +01:00
parent f8f68c4ca6
commit 580b74a791
2 changed files with 18 additions and 7 deletions

View file

@ -9664,6 +9664,16 @@ aarch64_stack_clash_protection_alloca_probe_range (void)
return STACK_CLASH_CALLER_GUARD;
}
/* Emit a stack tie that acts as a scheduling barrier for all previous and
subsequent memory accesses and that requires the stack pointer and REG
to have their current values. REG can be stack_pointer_rtx if no
other register's value needs to be fixed. */
static void
aarch64_emit_stack_tie (rtx reg)
{
emit_insn (gen_stack_tie (reg, gen_int_mode (REGNO (reg), DImode)));
}
/* Allocate POLY_SIZE bytes of stack space using TEMP1 and TEMP2 as scratch
registers. If POLY_SIZE is not large enough to require a probe this function
@ -9776,7 +9786,7 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
the instruction. */
rtx stack_ptr_copy = gen_rtx_REG (Pmode, STACK_CLASH_SVE_CFA_REGNUM);
emit_move_insn (stack_ptr_copy, stack_pointer_rtx);
emit_insn (gen_stack_tie (stack_ptr_copy, stack_pointer_rtx));
aarch64_emit_stack_tie (stack_ptr_copy);
/* We want the CFA independent of the stack pointer for the
duration of the loop. */
@ -10145,7 +10155,7 @@ aarch64_expand_prologue (void)
aarch64_add_cfa_expression (insn, regno_reg_rtx[reg1],
hard_frame_pointer_rtx, 0);
}
emit_insn (gen_stack_tie (stack_pointer_rtx, hard_frame_pointer_rtx));
aarch64_emit_stack_tie (hard_frame_pointer_rtx);
}
aarch64_save_callee_saves (saved_regs_offset, R0_REGNUM, R30_REGNUM,
@ -10248,7 +10258,7 @@ aarch64_expand_epilogue (bool for_sibcall)
|| cfun->calls_alloca
|| crtl->calls_eh_return)
{
emit_insn (gen_stack_tie (stack_pointer_rtx, stack_pointer_rtx));
aarch64_emit_stack_tie (stack_pointer_rtx);
need_barrier_p = false;
}
@ -10287,7 +10297,7 @@ aarch64_expand_epilogue (bool for_sibcall)
callee_adjust != 0, &cfi_ops);
if (need_barrier_p)
emit_insn (gen_stack_tie (stack_pointer_rtx, stack_pointer_rtx));
aarch64_emit_stack_tie (stack_pointer_rtx);
if (callee_adjust != 0)
aarch64_pop_regs (reg1, reg2, callee_adjust, &cfi_ops);

View file

@ -7325,10 +7325,11 @@
(define_insn "stack_tie"
[(set (mem:BLK (scratch))
(unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
(match_operand:DI 1 "register_operand" "rk")]
(unspec:BLK [(reg:DI SP_REGNUM)
(match_operand:DI 0 "register_operand" "rk")
(match_operand:DI 1 "const_int_operand")]
UNSPEC_PRLG_STK))]
""
"REGNO (operands[0]) == INTVAL (operands[1])"
""
[(set_attr "length" "0")]
)