107 lines
3.9 KiB
Diff
107 lines
3.9 KiB
Diff
commit 1467907e405bc18fb6935b5d432cfa5f936e838d
|
|
Author: Andreas Krebbel <krebbel@linux.ibm.com>
|
|
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")])
|
|
|