Commit 1c9c5e43 by Alan Modra Committed by Alan Modra

rs6000.c (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP): Define.

	* config/rs6000/rs6000.c (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP): Define.
	(rs6000_emit_epilogue): Use backchain to restore only when we
	have a large frame.  Make use of frame pointer to restore if we
	have one.  Handle ALWAYS_RESTORE_ALTIVEC_BEFORE_POP.

From-SVN: r134816
parent d4f90ccc
2008-04-30 Alan Modra <amodra@bigpond.net.au>
* config/rs6000/rs6000.c (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP): Define.
(rs6000_emit_epilogue): Use backchain to restore only when we
have a large frame. Make use of frame pointer to restore if we
have one. Handle ALWAYS_RESTORE_ALTIVEC_BEFORE_POP.
2008-04-29 Paolo Bonzini <bonzini@gnu.org> 2008-04-29 Paolo Bonzini <bonzini@gnu.org>
* config/avr/avr.md (*sbrx_branch, *sbix_branch, *sbix_branch_tmp): * config/avr/avr.md (*sbrx_branch, *sbix_branch, *sbix_branch_tmp):
......
/* Subroutines used for code generation on IBM RS/6000. /* Subroutines used for code generation on IBM RS/6000.
Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc. Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
...@@ -16244,6 +16244,10 @@ rs6000_output_function_prologue (FILE *file, ...@@ -16244,6 +16244,10 @@ rs6000_output_function_prologue (FILE *file,
rs6000_pic_labelno++; rs6000_pic_labelno++;
} }
/* Non-zero if vmx regs are restored before the frame pop, zero if
we restore after the pop when possible. */
#define ALWAYS_RESTORE_ALTIVEC_BEFORE_POP 0
/* Emit function epilogue as insns. /* Emit function epilogue as insns.
At present, dwarf2out_frame_debug_expr doesn't understand At present, dwarf2out_frame_debug_expr doesn't understand
...@@ -16283,13 +16287,18 @@ rs6000_emit_epilogue (int sibcall) ...@@ -16283,13 +16287,18 @@ rs6000_emit_epilogue (int sibcall)
|| crtl->calls_eh_return || crtl->calls_eh_return
|| info->first_fp_reg_save == 64 || info->first_fp_reg_save == 64
|| FP_SAVE_INLINE (info->first_fp_reg_save)); || FP_SAVE_INLINE (info->first_fp_reg_save));
use_backchain_to_restore_sp = (frame_pointer_needed
|| cfun->calls_alloca
|| info->total_size > 32767);
using_mtcr_multiple = (rs6000_cpu == PROCESSOR_PPC601 using_mtcr_multiple = (rs6000_cpu == PROCESSOR_PPC601
|| rs6000_cpu == PROCESSOR_PPC603 || rs6000_cpu == PROCESSOR_PPC603
|| rs6000_cpu == PROCESSOR_PPC750 || rs6000_cpu == PROCESSOR_PPC750
|| optimize_size); || optimize_size);
/* Restore via the backchain when we have a large frame, since this
is more efficient than an addis, addi pair. The second condition
here will not trigger at the moment; We don't actually need a
frame pointer for alloca, but the generic parts of the compiler
give us one anyway. */
use_backchain_to_restore_sp = (info->total_size > 32767
|| (cfun->calls_alloca
&& !frame_pointer_needed));
if (WORLD_SAVE_P (info)) if (WORLD_SAVE_P (info))
{ {
...@@ -16390,8 +16399,9 @@ rs6000_emit_epilogue (int sibcall) ...@@ -16390,8 +16399,9 @@ rs6000_emit_epilogue (int sibcall)
stack. */ stack. */
if (TARGET_ALTIVEC_ABI if (TARGET_ALTIVEC_ABI
&& info->altivec_size != 0 && info->altivec_size != 0
&& DEFAULT_ABI != ABI_V4 && (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
&& info->altivec_save_offset < (TARGET_32BIT ? -220 : -288)) || (DEFAULT_ABI != ABI_V4
&& info->altivec_save_offset < (TARGET_32BIT ? -220 : -288))))
{ {
int i; int i;
...@@ -16402,6 +16412,8 @@ rs6000_emit_epilogue (int sibcall) ...@@ -16402,6 +16412,8 @@ rs6000_emit_epilogue (int sibcall)
gen_rtx_MEM (Pmode, sp_reg_rtx)); gen_rtx_MEM (Pmode, sp_reg_rtx));
sp_offset = 0; sp_offset = 0;
} }
else if (frame_pointer_needed)
frame_reg_rtx = hard_frame_pointer_rtx;
for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i) for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
if (info->vrsave_mask & ALTIVEC_REG_BIT (i)) if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
...@@ -16426,18 +16438,23 @@ rs6000_emit_epilogue (int sibcall) ...@@ -16426,18 +16438,23 @@ rs6000_emit_epilogue (int sibcall)
if (TARGET_ALTIVEC if (TARGET_ALTIVEC
&& TARGET_ALTIVEC_VRSAVE && TARGET_ALTIVEC_VRSAVE
&& info->vrsave_mask != 0 && info->vrsave_mask != 0
&& DEFAULT_ABI != ABI_V4 && (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
&& info->vrsave_save_offset < (TARGET_32BIT ? -220 : -288)) || (DEFAULT_ABI != ABI_V4
&& info->vrsave_save_offset < (TARGET_32BIT ? -220 : -288))))
{ {
rtx addr, mem, reg; rtx addr, mem, reg;
if (use_backchain_to_restore_sp if (frame_reg_rtx == sp_reg_rtx)
&& frame_reg_rtx == sp_reg_rtx)
{ {
frame_reg_rtx = gen_rtx_REG (Pmode, 11); if (use_backchain_to_restore_sp)
emit_move_insn (frame_reg_rtx, {
gen_rtx_MEM (Pmode, sp_reg_rtx)); frame_reg_rtx = gen_rtx_REG (Pmode, 11);
sp_offset = 0; emit_move_insn (frame_reg_rtx,
gen_rtx_MEM (Pmode, sp_reg_rtx));
sp_offset = 0;
}
else if (frame_pointer_needed)
frame_reg_rtx = hard_frame_pointer_rtx;
} }
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
...@@ -16449,17 +16466,11 @@ rs6000_emit_epilogue (int sibcall) ...@@ -16449,17 +16466,11 @@ rs6000_emit_epilogue (int sibcall)
emit_insn (generate_set_vrsave (reg, info, 1)); emit_insn (generate_set_vrsave (reg, info, 1));
} }
/* If we have a frame pointer, a call to alloca, or a large stack /* If we have a large stack frame, restore the old stack pointer
frame, restore the old stack pointer using the backchain. Otherwise, using the backchain. */
we know what size to update it with. */
if (use_backchain_to_restore_sp) if (use_backchain_to_restore_sp)
{ {
if (frame_reg_rtx != sp_reg_rtx) if (frame_reg_rtx == sp_reg_rtx)
{
emit_move_insn (sp_reg_rtx, frame_reg_rtx);
frame_reg_rtx = sp_reg_rtx;
}
else
{ {
/* Under V.4, don't reset the stack pointer until after we're done /* Under V.4, don't reset the stack pointer until after we're done
loading the saved registers. */ loading the saved registers. */
...@@ -16470,6 +16481,30 @@ rs6000_emit_epilogue (int sibcall) ...@@ -16470,6 +16481,30 @@ rs6000_emit_epilogue (int sibcall)
gen_rtx_MEM (Pmode, sp_reg_rtx)); gen_rtx_MEM (Pmode, sp_reg_rtx));
sp_offset = 0; sp_offset = 0;
} }
else if (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
&& DEFAULT_ABI == ABI_V4)
/* frame_reg_rtx has been set up by the altivec restore. */
;
else
{
emit_move_insn (sp_reg_rtx, frame_reg_rtx);
frame_reg_rtx = sp_reg_rtx;
}
}
/* If we have a frame pointer, we can restore the old stack pointer
from it. */
else if (frame_pointer_needed)
{
frame_reg_rtx = sp_reg_rtx;
if (DEFAULT_ABI == ABI_V4)
frame_reg_rtx = gen_rtx_REG (Pmode, 11);
emit_insn (TARGET_32BIT
? gen_addsi3 (frame_reg_rtx, hard_frame_pointer_rtx,
GEN_INT (info->total_size))
: gen_adddi3 (frame_reg_rtx, hard_frame_pointer_rtx,
GEN_INT (info->total_size)));
sp_offset = 0;
} }
else if (info->push_p else if (info->push_p
&& DEFAULT_ABI != ABI_V4 && DEFAULT_ABI != ABI_V4
...@@ -16484,7 +16519,8 @@ rs6000_emit_epilogue (int sibcall) ...@@ -16484,7 +16519,8 @@ rs6000_emit_epilogue (int sibcall)
} }
/* Restore AltiVec registers if we have not done so already. */ /* Restore AltiVec registers if we have not done so already. */
if (TARGET_ALTIVEC_ABI if (!ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
&& TARGET_ALTIVEC_ABI
&& info->altivec_size != 0 && info->altivec_size != 0
&& (DEFAULT_ABI == ABI_V4 && (DEFAULT_ABI == ABI_V4
|| info->altivec_save_offset >= (TARGET_32BIT ? -220 : -288))) || info->altivec_save_offset >= (TARGET_32BIT ? -220 : -288)))
...@@ -16511,7 +16547,8 @@ rs6000_emit_epilogue (int sibcall) ...@@ -16511,7 +16547,8 @@ rs6000_emit_epilogue (int sibcall)
} }
/* Restore VRSAVE if we have not done so already. */ /* Restore VRSAVE if we have not done so already. */
if (TARGET_ALTIVEC if (!ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
&& TARGET_ALTIVEC
&& TARGET_ALTIVEC_VRSAVE && TARGET_ALTIVEC_VRSAVE
&& info->vrsave_mask != 0 && info->vrsave_mask != 0
&& (DEFAULT_ABI == ABI_V4 && (DEFAULT_ABI == ABI_V4
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment