diff options
Diffstat (limited to 'gcc/config/rs6000/rs6000.c')
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 68 |
1 files changed, 39 insertions, 29 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 5e6f30183a9..05d03823b2d 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -759,7 +759,6 @@ static bool spe_func_has_64bit_regs_p (void); static void emit_frame_save (rtx, rtx, enum machine_mode, unsigned int, int, HOST_WIDE_INT); static rtx gen_frame_mem_offset (enum machine_mode, rtx, int); -static void rs6000_emit_allocate_stack (HOST_WIDE_INT, int, int); static unsigned rs6000_hash_constant (rtx); static unsigned toc_hash_function (const void *); static int toc_hash_eq (const void *, const void *); @@ -15548,13 +15547,11 @@ rs6000_emit_stack_tie (void) } /* Emit the correct code for allocating stack space, as insns. - If COPY_R12, make sure a copy of the old frame is left in r12. - If COPY_R11, make sure a copy of the old frame is left in r11, - in preference to r12 if COPY_R12. + If COPY_REG, make sure a copy of the old frame is left there. The generated code may use hard register 0 as a temporary. */ static void -rs6000_emit_allocate_stack (HOST_WIDE_INT size, int copy_r12, int copy_r11) +rs6000_emit_allocate_stack (HOST_WIDE_INT size, rtx copy_reg) { rtx insn; rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM); @@ -15604,11 +15601,8 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, int copy_r12, int copy_r11) warning (0, "stack limit expression is not supported"); } - if (copy_r12 || copy_r11) - emit_move_insn (copy_r11 - ? gen_rtx_REG (Pmode, 11) - : gen_rtx_REG (Pmode, 12), - stack_reg); + if (copy_reg) + emit_move_insn (copy_reg, stack_reg); if (size > 32767) { @@ -16180,20 +16174,33 @@ rs6000_emit_prologue (void) ? (!saving_GPRs_inline && info->spe_64bit_regs_used == 0) : (!saving_FPRs_inline || !saving_GPRs_inline)); + rtx copy_reg = need_r11 ? gen_rtx_REG (Pmode, 11) : NULL; + if (info->total_size < 32767) sp_offset = info->total_size; + else if (need_r11) + frame_reg_rtx = copy_reg; + else if (info->cr_save_p + || info->lr_save_p + || info->first_fp_reg_save < 64 + || info->first_gp_reg_save < 32 + || info->altivec_size != 0 + || info->vrsave_mask != 0 + || crtl->calls_eh_return) + { + copy_reg = frame_ptr_rtx; + frame_reg_rtx = copy_reg; + } else - frame_reg_rtx = (need_r11 - ? gen_rtx_REG (Pmode, 11) - : frame_ptr_rtx); - rs6000_emit_allocate_stack (info->total_size, - (frame_reg_rtx != sp_reg_rtx - && (info->cr_save_p - || info->lr_save_p - || info->first_fp_reg_save < 64 - || info->first_gp_reg_save < 32 - )), - need_r11); + { + /* The prologue won't be saving any regs so there is no need + to set up a frame register to access any frame save area. + We also won't be using sp_offset anywhere below, but set + the correct value anyway to protect against future + changes to this function. */ + sp_offset = info->total_size; + } + rs6000_emit_allocate_stack (info->total_size, copy_reg); if (frame_reg_rtx != sp_reg_rtx) rs6000_emit_stack_tie (); } @@ -16627,16 +16634,19 @@ rs6000_emit_prologue (void) if (!WORLD_SAVE_P (info) && info->push_p && !(DEFAULT_ABI == ABI_V4 || crtl->calls_eh_return)) { + rtx copy_reg = NULL; + if (info->total_size < 32767) - sp_offset = info->total_size; + sp_offset = info->total_size; + else if (info->altivec_size != 0 + || info->vrsave_mask != 0) + { + copy_reg = frame_ptr_rtx; + frame_reg_rtx = copy_reg; + } else - frame_reg_rtx = frame_ptr_rtx; - rs6000_emit_allocate_stack (info->total_size, - (frame_reg_rtx != sp_reg_rtx - && ((info->altivec_size != 0) - || (info->vrsave_mask != 0) - )), - FALSE); + sp_offset = info->total_size; + rs6000_emit_allocate_stack (info->total_size, copy_reg); if (frame_reg_rtx != sp_reg_rtx) rs6000_emit_stack_tie (); } |