commit 1467907e405bc18fb6935b5d432cfa5f936e838d Author: Andreas Krebbel Date: Thu Mar 30 13:57:54 2023 +0200 IBM zSystems: Make stack_tie to work with hard frame pointer With this patch a scheduling barrier is created to prevent the insn setting up the frame-pointer and instructions which save GPRs to the stack to be swapped. Otherwise broken CFI information would be generated since the stack save insns would use a base register which is not currently declared as holding the CFA. Without -mpreserve-args this did not happen because the store multiple we used for saving the GPRs would also cover the frame-pointer register and therefore creates a dependency on the frame-pointer hardreg. However, with this patch the stack_tie is emitted regardless of -mpreserve-args since this in general appears to be the safer approach. * config/s390/s390.c (save_gprs): Use gen_frame_mem. (restore_gprs): Likewise. (s390_emit_stack_tie): Make the stack_tie to be dependent on the frame pointer if a frame-pointer is used. (s390_emit_prologue): Emit stack_tie when frame-pointer is needed. * config/s390/s390.md (stack_tie): Add a register operand and rename to ... (stack_tiesi, stack_tiedi): ... this. diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 20424537558..952c708be7a 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -10921,9 +10921,7 @@ save_gprs (rtx base, int offset, int first, int last) int i; addr = plus_constant (Pmode, base, offset); - addr = gen_rtx_MEM (Pmode, addr); - - set_mem_alias_set (addr, get_frame_alias_set ()); + addr = gen_frame_mem (Pmode, addr); /* Special-case single register. */ if (first == last) @@ -11035,8 +11033,7 @@ restore_gprs (rtx base, int offset, int first, int last) rtx addr, insn; addr = plus_constant (Pmode, base, offset); - addr = gen_rtx_MEM (Pmode, addr); - set_mem_alias_set (addr, get_frame_alias_set ()); + addr = gen_frame_mem (Pmode, addr); /* Special-case single register. */ if (first == last) @@ -11105,10 +11102,14 @@ s390_load_got (void) static void s390_emit_stack_tie (void) { - rtx mem = gen_frame_mem (BLKmode, - gen_rtx_REG (Pmode, STACK_POINTER_REGNUM)); - - emit_insn (gen_stack_tie (mem)); + rtx mem = gen_frame_mem (BLKmode, stack_pointer_rtx); + rtx stack_reg = (frame_pointer_needed + ? hard_frame_pointer_rtx + : stack_pointer_rtx); + if (TARGET_64BIT) + emit_insn (gen_stack_tiedi (mem, stack_reg)); + else + emit_insn (gen_stack_tiesi (mem, stack_reg)); } /* Copy GPRS into FPR save slots. */ @@ -11701,6 +11702,7 @@ s390_emit_prologue (void) if (frame_pointer_needed) { + s390_emit_stack_tie (); insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); RTX_FRAME_RELATED_P (insn) = 1; } diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 7114609b676..f235df3a25d 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -11366,10 +11366,19 @@ ; This is used in s390_emit_prologue in order to prevent insns ; adjusting the stack pointer to be moved over insns writing stack ; slots using a copy of the stack pointer in a different register. -(define_insn "stack_tie" +(define_insn "stack_tiesi" [(set (match_operand:BLK 0 "memory_operand" "+m") - (unspec:BLK [(match_dup 0)] UNSPEC_TIE))] + (unspec:BLK [(match_dup 0) + (match_operand:SI 1 "register_operand" "r")] UNSPEC_TIE))] + "!TARGET_64BIT" "" + [(set_attr "length" "0")]) + +(define_insn "stack_tiedi" + [(set (match_operand:BLK 0 "memory_operand" "+m") + (unspec:BLK [(match_dup 0) + (match_operand:DI 1 "register_operand" "r")] UNSPEC_TIE))] + "TARGET_64BIT" "" [(set_attr "length" "0")])