aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSegher Boessenkool <segher@kernel.crashing.org>2016-11-29 06:29:47 +0100
committerSegher Boessenkool <segher@gcc.gnu.org>2016-11-29 06:29:47 +0100
commitdfed7971fb42cbd5196ee92e27e8292f46fa72e9 (patch)
tree0b1ed8816a840b84d110cc33df30aca22480a93b
parent08dd2b683f98c6a721329f02f16a9a815a143f48 (diff)
downloadgcc-dfed7971fb42cbd5196ee92e27e8292f46fa72e9.zip
gcc-dfed7971fb42cbd5196ee92e27e8292f46fa72e9.tar.gz
gcc-dfed7971fb42cbd5196ee92e27e8292f46fa72e9.tar.bz2
rs6000: Make deallocation of a large frame work (PR77687)
If we use ABI_V4 and we have a big stack frame, we end the epilogue with a "mr 1,11" (or similar) instruction. This instruction however has no dependencies on the earlier restores from stack (done via r11), so sched2 can end up reordering the insns, which is bad because we have no red zone so that you then restore from stack that is already deallocated. This fixes it by making that restore depend on the memory accesses. PR target/77687 * config/rs6000/rs6000.c (rs6000_emit_stack_reset): Emit the stack_restore_tie insn instead of stack_tie, for the SVR4 and SPE ABIs. * config/rs6000/rs6000.md (stack_restore_tie): New define_insn. From-SVN: r242949
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/rs6000/rs6000.c13
-rw-r--r--gcc/config/rs6000/rs6000.md16
3 files changed, 32 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index da6c640..27f4137 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2016-11-29 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/77687
+ * config/rs6000/rs6000.c (rs6000_emit_stack_reset): Emit the
+ stack_restore_tie insn instead of stack_tie, for the SVR4 and
+ SPE ABIs.
+ * config/rs6000/rs6000.md (stack_restore_tie): New define_insn.
+
2016-11-28 Segher Boessenkool <segher@kernel.crashing.org>
* shrink-wrap.c (init_separate_shrink_wrap): Do not clear
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index dfb5dc8..0a6a784 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -27534,7 +27534,11 @@ rs6000_emit_stack_reset (rs6000_stack_t *info,
rtx frame_reg_rtx, HOST_WIDE_INT frame_off,
unsigned updt_regno)
{
- rtx updt_reg_rtx;
+ /* If there is nothing to do, don't do anything. */
+ if (frame_off == 0 && REGNO (frame_reg_rtx) == updt_regno)
+ return NULL_RTX;
+
+ rtx updt_reg_rtx = gen_rtx_REG (Pmode, updt_regno);
/* This blockage is needed so that sched doesn't decide to move
the sp change before the register restores. */
@@ -27542,18 +27546,17 @@ rs6000_emit_stack_reset (rs6000_stack_t *info,
|| (TARGET_SPE_ABI
&& info->spe_64bit_regs_used != 0
&& info->first_gp_reg_save != 32))
- rs6000_emit_stack_tie (frame_reg_rtx, frame_pointer_needed);
+ return emit_insn (gen_stack_restore_tie (updt_reg_rtx, frame_reg_rtx,
+ GEN_INT (frame_off)));
/* If we are restoring registers out-of-line, we will be using the
"exit" variants of the restore routines, which will reset the
stack for us. But we do need to point updt_reg into the
right place for those routines. */
- updt_reg_rtx = gen_rtx_REG (Pmode, updt_regno);
-
if (frame_off != 0)
return emit_insn (gen_add3_insn (updt_reg_rtx,
frame_reg_rtx, GEN_INT (frame_off)));
- else if (REGNO (frame_reg_rtx) != updt_regno)
+ else
return emit_move_insn (updt_reg_rtx, frame_reg_rtx);
return NULL_RTX;
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index f3d1d715..cb982d3 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -12813,6 +12813,22 @@
""
[(set_attr "length" "0")])
+; Some 32-bit ABIs do not have a red zone, so the stack deallocation has to
+; stay behind all restores from the stack, it cannot be reordered to before
+; one. See PR77687. This insn is an add or mr, and a stack_tie on the
+; operands of that.
+(define_insn "stack_restore_tie"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+ (plus:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+ (match_operand:SI 2 "reg_or_cint_operand" "O,rI")))
+ (set (mem:BLK (match_dup 0)) (const_int 0))
+ (set (mem:BLK (match_dup 1)) (const_int 0))]
+ "TARGET_32BIT"
+ "@
+ mr %0,%1
+ add%I2 %0,%1,%2"
+ [(set_attr "type" "*,add")])
+
(define_expand "epilogue"
[(use (const_int 0))]
""