From e356c1699737f8af84951b42118fba604ba74f14 Mon Sep 17 00:00:00 2001 From: amodra Date: Tue, 1 May 2012 04:03:21 +0000 Subject: [PATCH] PR target/53038 * config/rs6000/rs6000.c (load_lr_save, restore_saved_lr, load_cr_save, add_crlr_cfa_restore): New functions. (rs6000_restore_saved_cr): Rename to.. (restore_saved_cr): ..this. Add cfa_restore notes for cr. (rs6000_emit_epilogue): Use new functions. Adjust condition for emitting lr and cr cfa_restore. Emit cfa_restores for fp regs when using out-of-line restore only when shrink wrapping. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@187010 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 11 ++++ gcc/config/rs6000/rs6000.c | 159 +++++++++++++++++++++++++++++++-------------- 2 files changed, 120 insertions(+), 50 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 478ba87..e7999fb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2012-05-01 Alan Modra + + PR target/53038 + * config/rs6000/rs6000.c (load_lr_save, restore_saved_lr, + load_cr_save, add_crlr_cfa_restore): New functions. + (rs6000_restore_saved_cr): Rename to.. + (restore_saved_cr): ..this. Add cfa_restore notes for cr. + (rs6000_emit_epilogue): Use new functions. Adjust condition + for emitting lr and cr cfa_restore. Emit cfa_restores for fp + regs when using out-of-line restore only when shrink wrapping. + 2012-04-30 Uros Bizjak PR middle-end/53136 diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index eccbbdf..dca434b 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -952,7 +952,6 @@ static void rs6000_set_default_type_attributes (tree); static bool rs6000_reg_live_or_pic_offset_p (int); static tree rs6000_builtin_vectorized_libmass (tree, tree, tree); static tree rs6000_builtin_vectorized_function (tree, tree, tree); -static void rs6000_restore_saved_cr (rtx, int); static bool rs6000_output_addr_const_extra (FILE *, rtx); static void rs6000_output_function_prologue (FILE *, HOST_WIDE_INT); static void rs6000_output_function_epilogue (FILE *, HOST_WIDE_INT); @@ -20276,10 +20275,37 @@ rs6000_output_function_prologue (FILE *file, we restore after the pop when possible. */ #define ALWAYS_RESTORE_ALTIVEC_BEFORE_POP 0 +/* Restoring cr is a two step process: loading a reg from the frame + save, then moving the reg to cr. For ABI_V4 we must let the + unwinder know that the stack location is no longer valid at or + before the stack deallocation, but we can't emit a cfa_restore for + cr at the stack deallocation like we do for other registers. + The trouble is that it is possible for the move to cr to be + scheduled after the stack deallocation. So say exactly where cr + is located on each of the two insns. */ + +static rtx +load_cr_save (int regno, rtx frame_reg_rtx, int offset, bool exit_func) +{ + rtx mem = gen_frame_mem_offset (SImode, frame_reg_rtx, offset); + rtx reg = gen_rtx_REG (SImode, regno); + rtx insn = emit_move_insn (reg, mem); + + if (!exit_func && DEFAULT_ABI == ABI_V4) + { + rtx cr = gen_rtx_REG (SImode, CR2_REGNO); + rtx set = gen_rtx_SET (VOIDmode, reg, cr); + + add_reg_note (insn, REG_CFA_REGISTER, set); + RTX_FRAME_RELATED_P (insn) = 1; + } + return reg; +} + /* Reload CR from REG. */ static void -rs6000_restore_saved_cr (rtx reg, int using_mfcr_multiple) +restore_saved_cr (rtx reg, int using_mfcr_multiple, bool exit_func) { int count = 0; int i; @@ -20317,11 +20343,59 @@ rs6000_restore_saved_cr (rtx reg, int using_mfcr_multiple) else for (i = 0; i < 8; i++) if (df_regs_ever_live_p (CR0_REGNO+i) && ! call_used_regs[CR0_REGNO+i]) - { - emit_insn (gen_movsi_to_cr_one (gen_rtx_REG (CCmode, - CR0_REGNO+i), - reg)); - } + emit_insn (gen_movsi_to_cr_one (gen_rtx_REG (CCmode, CR0_REGNO+i), + reg)); + + if (!exit_func && (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)) + { + rtx insn = get_last_insn (); + rtx cr = gen_rtx_REG (SImode, CR2_REGNO); + + add_reg_note (insn, REG_CFA_RESTORE, cr); + RTX_FRAME_RELATED_P (insn) = 1; + } +} + +/* Like cr, the move to lr instruction can be scheduled after the + stack deallocation, but unlike cr, its stack frame save is still + valid. So we only need to emit the cfa_restore on the correct + instruction. */ + +static void +load_lr_save (int regno, rtx frame_reg_rtx, int offset) +{ + rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx, offset); + rtx reg = gen_rtx_REG (Pmode, regno); + + emit_move_insn (reg, mem); +} + +static void +restore_saved_lr (int regno, bool exit_func) +{ + rtx reg = gen_rtx_REG (Pmode, regno); + rtx lr = gen_rtx_REG (Pmode, LR_REGNO); + rtx insn = emit_move_insn (lr, reg); + + if (!exit_func && flag_shrink_wrap) + { + add_reg_note (insn, REG_CFA_RESTORE, lr); + RTX_FRAME_RELATED_P (insn) = 1; + } +} + +static rtx +add_crlr_cfa_restore (const rs6000_stack_t *info, rtx cfa_restores) +{ + if (info->cr_save_p) + cfa_restores = alloc_reg_note (REG_CFA_RESTORE, + gen_rtx_REG (SImode, CR2_REGNO), + cfa_restores); + if (info->lr_save_p) + cfa_restores = alloc_reg_note (REG_CFA_RESTORE, + gen_rtx_REG (Pmode, LR_REGNO), + cfa_restores); + return cfa_restores; } /* Return true if OFFSET from stack pointer can be clobbered by signals. @@ -20372,6 +20446,7 @@ rs6000_emit_epilogue (int sibcall) enum machine_mode reg_mode = Pmode; int reg_size = TARGET_32BIT ? 4 : 8; int i; + bool exit_func; unsigned ptr_regno; info = rs6000_stack_info (); @@ -20824,22 +20899,22 @@ rs6000_emit_epilogue (int sibcall) emit_insn (generate_set_vrsave (reg, info, 1)); } + /* If we exit by an out-of-line restore function on ABI_V4 then that + function will deallocate the stack, so we don't need to worry + about the unwinder restoring cr from an invalid stack frame + location. */ + exit_func = (!restoring_FPRs_inline + || (!restoring_GPRs_inline + && info->first_fp_reg_save == 64)); + /* Get the old lr if we saved it. If we are restoring registers out-of-line, then the out-of-line routines can do this for us. */ if (restore_lr && restoring_GPRs_inline) - { - rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx, - info->lr_save_offset + frame_off); - - emit_move_insn (gen_rtx_REG (Pmode, 0), mem); - } + load_lr_save (0, frame_reg_rtx, info->lr_save_offset + frame_off); /* Get the old cr if we saved it. */ if (info->cr_save_p) { - rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, - GEN_INT (info->cr_save_offset + frame_off)); - rtx mem = gen_frame_mem (SImode, addr); unsigned cr_save_regno = 12; if (!restoring_GPRs_inline) @@ -20857,14 +20932,14 @@ rs6000_emit_epilogue (int sibcall) else if (REGNO (frame_reg_rtx) == 12) cr_save_regno = 11; - cr_save_reg = gen_rtx_REG (SImode, cr_save_regno); - emit_move_insn (cr_save_reg, mem); + cr_save_reg = load_cr_save (cr_save_regno, frame_reg_rtx, + info->cr_save_offset + frame_off, + exit_func); } /* Set LR here to try to overlap restores below. */ if (restore_lr && restoring_GPRs_inline) - emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO), - gen_rtx_REG (Pmode, 0)); + restore_saved_lr (0, exit_func); /* Load exception handler data registers, if needed. */ if (crtl->calls_eh_return) @@ -20983,7 +21058,7 @@ rs6000_emit_epilogue (int sibcall) frame_off = -end_save; if (can_use_exit && info->cr_save_p) - rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple); + restore_saved_cr (cr_save_reg, using_mtcr_multiple, true); ptr_off = -end_save; rs6000_emit_savres_rtx (info, ptr_reg, @@ -21046,23 +21121,14 @@ rs6000_emit_epilogue (int sibcall) The cfa_restores must be emitted on or before the insn that invalidates the stack, and of course must not be emitted before the insn that actually does the restore. The latter - is why the LR cfa_restore condition below is a little - complicated. It's also why it is a bad idea to emit the - cfa_restores as a group on the last instruction here that - actually does a restore: That insn may be reordered with - respect to others doing restores. */ - if (info->cr_save_p) - cfa_restores = alloc_reg_note (REG_CFA_RESTORE, - gen_rtx_REG (SImode, CR2_REGNO), - cfa_restores); + is why it is a bad idea to emit the cfa_restores as a group + on the last instruction here that actually does a restore: + That insn may be reordered with respect to others doing + restores. */ if (flag_shrink_wrap - && (restore_lr - || (info->lr_save_p - && !restoring_GPRs_inline - && info->first_fp_reg_save == 64))) - cfa_restores = alloc_reg_note (REG_CFA_RESTORE, - gen_rtx_REG (Pmode, LR_REGNO), - cfa_restores); + && !restoring_GPRs_inline + && info->first_fp_reg_save == 64) + cfa_restores = add_crlr_cfa_restore (info, cfa_restores); for (i = info->first_gp_reg_save; i < 32; i++) if (!restoring_GPRs_inline @@ -21086,12 +21152,8 @@ rs6000_emit_epilogue (int sibcall) if (restore_lr && !restoring_GPRs_inline) { - rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx, - info->lr_save_offset + frame_off); - - emit_move_insn (gen_rtx_REG (Pmode, 0), mem); - emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO), - gen_rtx_REG (Pmode, 0)); + load_lr_save (0, frame_reg_rtx, info->lr_save_offset + frame_off); + restore_saved_lr (0, exit_func); } /* Restore fpr's if we need to do it without calling a function. */ @@ -21118,7 +21180,7 @@ rs6000_emit_epilogue (int sibcall) /* If we saved cr, restore it here. Just those that were used. */ if (info->cr_save_p) - rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple); + restore_saved_cr (cr_save_reg, using_mtcr_multiple, exit_func); /* If this is V.4, unwind the stack pointer after all of the loads have been done, or set up r11 if we are restoring fp out of line. */ @@ -21198,11 +21260,8 @@ rs6000_emit_epilogue (int sibcall) int i; rtx sym; - if ((DEFAULT_ABI == ABI_V4 || flag_shrink_wrap) - && lr) - cfa_restores = alloc_reg_note (REG_CFA_RESTORE, - gen_rtx_REG (Pmode, LR_REGNO), - cfa_restores); + if (flag_shrink_wrap) + cfa_restores = add_crlr_cfa_restore (info, cfa_restores); sym = rs6000_savres_routine_sym (info, SAVRES_FPR | (lr ? SAVRES_LR : 0)); @@ -21221,7 +21280,7 @@ rs6000_emit_epilogue (int sibcall) reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i); RTVEC_ELT (p, i + 4) = gen_rtx_SET (VOIDmode, reg, mem); - if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap) + if (flag_shrink_wrap) cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores); } -- 2.7.4