From 1c9c5e438249c56845b030f596a7d333a91fb181 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 30 Apr 2008 05:19:11 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 +++ gcc/config/rs6000/rs6000.c | 87 +++++++++++++++++++++++++++----------- 2 files changed, 69 insertions(+), 25 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2e29305b423..e62a91a69fa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2008-04-30 Alan Modra + + * 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 * config/avr/avr.md (*sbrx_branch, *sbix_branch, *sbix_branch_tmp): diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index ec9f83173d4..20cfe95b95d 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1,6 +1,6 @@ /* Subroutines used for code generation on IBM RS/6000. 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. Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) @@ -16244,6 +16244,10 @@ rs6000_output_function_prologue (FILE *file, 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. At present, dwarf2out_frame_debug_expr doesn't understand @@ -16283,13 +16287,18 @@ rs6000_emit_epilogue (int sibcall) || crtl->calls_eh_return || info->first_fp_reg_save == 64 || 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 || rs6000_cpu == PROCESSOR_PPC603 || rs6000_cpu == PROCESSOR_PPC750 || 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)) { @@ -16390,8 +16399,9 @@ rs6000_emit_epilogue (int sibcall) stack. */ if (TARGET_ALTIVEC_ABI && info->altivec_size != 0 - && DEFAULT_ABI != ABI_V4 - && info->altivec_save_offset < (TARGET_32BIT ? -220 : -288)) + && (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP + || (DEFAULT_ABI != ABI_V4 + && info->altivec_save_offset < (TARGET_32BIT ? -220 : -288)))) { int i; @@ -16402,6 +16412,8 @@ rs6000_emit_epilogue (int sibcall) gen_rtx_MEM (Pmode, sp_reg_rtx)); 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) if (info->vrsave_mask & ALTIVEC_REG_BIT (i)) @@ -16426,18 +16438,23 @@ rs6000_emit_epilogue (int sibcall) if (TARGET_ALTIVEC && TARGET_ALTIVEC_VRSAVE && info->vrsave_mask != 0 - && DEFAULT_ABI != ABI_V4 - && info->vrsave_save_offset < (TARGET_32BIT ? -220 : -288)) + && (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP + || (DEFAULT_ABI != ABI_V4 + && info->vrsave_save_offset < (TARGET_32BIT ? -220 : -288)))) { rtx addr, mem, reg; - if (use_backchain_to_restore_sp - && frame_reg_rtx == sp_reg_rtx) + if (frame_reg_rtx == sp_reg_rtx) { - frame_reg_rtx = gen_rtx_REG (Pmode, 11); - emit_move_insn (frame_reg_rtx, - gen_rtx_MEM (Pmode, sp_reg_rtx)); - sp_offset = 0; + if (use_backchain_to_restore_sp) + { + frame_reg_rtx = gen_rtx_REG (Pmode, 11); + 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, @@ -16449,17 +16466,11 @@ rs6000_emit_epilogue (int sibcall) emit_insn (generate_set_vrsave (reg, info, 1)); } - /* If we have a frame pointer, a call to alloca, or a large stack - frame, restore the old stack pointer using the backchain. Otherwise, - we know what size to update it with. */ + /* If we have a large stack frame, restore the old stack pointer + using the backchain. */ if (use_backchain_to_restore_sp) { - if (frame_reg_rtx != sp_reg_rtx) - { - emit_move_insn (sp_reg_rtx, frame_reg_rtx); - frame_reg_rtx = sp_reg_rtx; - } - else + if (frame_reg_rtx == sp_reg_rtx) { /* Under V.4, don't reset the stack pointer until after we're done loading the saved registers. */ @@ -16470,6 +16481,30 @@ rs6000_emit_epilogue (int sibcall) gen_rtx_MEM (Pmode, sp_reg_rtx)); 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 && DEFAULT_ABI != ABI_V4 @@ -16484,7 +16519,8 @@ rs6000_emit_epilogue (int sibcall) } /* 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 && (DEFAULT_ABI == ABI_V4 || info->altivec_save_offset >= (TARGET_32BIT ? -220 : -288))) @@ -16511,7 +16547,8 @@ rs6000_emit_epilogue (int sibcall) } /* Restore VRSAVE if we have not done so already. */ - if (TARGET_ALTIVEC + if (!ALWAYS_RESTORE_ALTIVEC_BEFORE_POP + && TARGET_ALTIVEC && TARGET_ALTIVEC_VRSAVE && info->vrsave_mask != 0 && (DEFAULT_ABI == ABI_V4 -- 2.30.2