rs6000.c (rs6000_make_savres_rtx): Delete unneeded declaration.
* config/rs6000/rs6000.c (rs6000_make_savres_rtx): Delete unneeded declaration. (rs6000_emit_stack_reset): Only return insn emitted when it adjusts sp. (rs6000_make_savres_rtx): Rename to rs6000_emit_savres_rtx. Use simple_return in pattern, emit instruction, and set jump_label. (rs6000_emit_prologue): Update for rs6000_emit_savres_rtx. Use simple_return rather than return. (emit_cfa_restores): New function. (rs6000_emit_epilogue): Emit cfa_restores when flag_shrink_wrap. Add missing cfa_restores for SAVE_WORLD. Add missing LR cfa_restore when using out-of-line gpr restore. Add missing LR and FP regs cfa_restores for out-of-line fpr restore. Consolidate code setting up cfa_restores. Formatting. Use LR_REGNO define. (rs6000_output_mi_thunk): Use simple_return rather than return. * config/rs6000/rs6000.md (sibcall*, sibcall_value*): Likewise. (return_internal*): Likewise. (any_return, return_pred, return_str): New iterators. (return, conditional return insns): Provide both return and simple_return variants. * config/rs6000/rs6000.h (EARLY_R12, LATE_R12): Define. (REG_ALLOC_ORDER): Move r12 before call-saved regs when FIXED_R13. Move r11 and r0 later to suit shrink-wrapping. From-SVN: r180522
This commit is contained in:
parent
4559db79d8
commit
d44b26bdf4
4 changed files with 283 additions and 189 deletions
|
@ -1,3 +1,28 @@
|
|||
2011-10-26 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* config/rs6000/rs6000.c (rs6000_make_savres_rtx): Delete unneeded
|
||||
declaration.
|
||||
(rs6000_emit_stack_reset): Only return insn emitted when it adjusts sp.
|
||||
(rs6000_make_savres_rtx): Rename to rs6000_emit_savres_rtx. Use
|
||||
simple_return in pattern, emit instruction, and set jump_label.
|
||||
(rs6000_emit_prologue): Update for rs6000_emit_savres_rtx. Use
|
||||
simple_return rather than return.
|
||||
(emit_cfa_restores): New function.
|
||||
(rs6000_emit_epilogue): Emit cfa_restores when flag_shrink_wrap.
|
||||
Add missing cfa_restores for SAVE_WORLD. Add missing LR cfa_restore
|
||||
when using out-of-line gpr restore. Add missing LR and FP regs
|
||||
cfa_restores for out-of-line fpr restore. Consolidate code setting
|
||||
up cfa_restores. Formatting. Use LR_REGNO define.
|
||||
(rs6000_output_mi_thunk): Use simple_return rather than return.
|
||||
* config/rs6000/rs6000.md (sibcall*, sibcall_value*): Likewise.
|
||||
(return_internal*): Likewise.
|
||||
(any_return, return_pred, return_str): New iterators.
|
||||
(return, conditional return insns): Provide both return and
|
||||
simple_return variants.
|
||||
* config/rs6000/rs6000.h (EARLY_R12, LATE_R12): Define.
|
||||
(REG_ALLOC_ORDER): Move r12 before call-saved regs when FIXED_R13.
|
||||
Move r11 and r0 later to suit shrink-wrapping.
|
||||
|
||||
2011-10-26 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
* lto-wrapper.c (run_gcc): Properly init/free obstack.
|
||||
|
|
|
@ -899,8 +899,6 @@ static const char *rs6000_mangle_type (const_tree);
|
|||
static void rs6000_set_default_type_attributes (tree);
|
||||
static rtx rs6000_savres_routine_sym (rs6000_stack_t *, bool, bool, bool);
|
||||
static rtx rs6000_emit_stack_reset (rs6000_stack_t *, rtx, rtx, int, bool);
|
||||
static rtx rs6000_make_savres_rtx (rs6000_stack_t *, rtx, int,
|
||||
enum machine_mode, bool, bool, bool);
|
||||
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);
|
||||
|
@ -19643,8 +19641,10 @@ rs6000_emit_stack_reset (rs6000_stack_t *info,
|
|||
if (sp_offset != 0)
|
||||
{
|
||||
rtx dest_reg = savres ? gen_rtx_REG (Pmode, 11) : sp_reg_rtx;
|
||||
return emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx,
|
||||
GEN_INT (sp_offset)));
|
||||
rtx insn = emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx,
|
||||
GEN_INT (sp_offset)));
|
||||
if (!savres)
|
||||
return insn;
|
||||
}
|
||||
else if (!savres)
|
||||
return emit_move_insn (sp_reg_rtx, frame_reg_rtx);
|
||||
|
@ -19668,10 +19668,11 @@ rs6000_emit_stack_reset (rs6000_stack_t *info,
|
|||
}
|
||||
|
||||
/* Construct a parallel rtx describing the effect of a call to an
|
||||
out-of-line register save/restore routine. */
|
||||
out-of-line register save/restore routine, and emit the insn
|
||||
or jump_insn as appropriate. */
|
||||
|
||||
static rtx
|
||||
rs6000_make_savres_rtx (rs6000_stack_t *info,
|
||||
rs6000_emit_savres_rtx (rs6000_stack_t *info,
|
||||
rtx frame_reg_rtx, int save_area_offset,
|
||||
enum machine_mode reg_mode,
|
||||
bool savep, bool gpr, bool lr)
|
||||
|
@ -19681,6 +19682,7 @@ rs6000_make_savres_rtx (rs6000_stack_t *info,
|
|||
int reg_size = GET_MODE_SIZE (reg_mode);
|
||||
rtx sym;
|
||||
rtvec p;
|
||||
rtx par, insn;
|
||||
|
||||
offset = 0;
|
||||
start_reg = (gpr
|
||||
|
@ -19694,7 +19696,7 @@ rs6000_make_savres_rtx (rs6000_stack_t *info,
|
|||
RTVEC_ELT (p, offset++) = ret_rtx;
|
||||
|
||||
RTVEC_ELT (p, offset++)
|
||||
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 65));
|
||||
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO));
|
||||
|
||||
sym = rs6000_savres_routine_sym (info, savep, gpr, lr);
|
||||
RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, sym);
|
||||
|
@ -19727,7 +19729,16 @@ rs6000_make_savres_rtx (rs6000_stack_t *info,
|
|||
RTVEC_ELT (p, i + offset) = gen_rtx_SET (VOIDmode, mem, reg);
|
||||
}
|
||||
|
||||
return gen_rtx_PARALLEL (VOIDmode, p);
|
||||
par = gen_rtx_PARALLEL (VOIDmode, p);
|
||||
|
||||
if (!savep && lr)
|
||||
{
|
||||
insn = emit_jump_insn (par);
|
||||
JUMP_LABEL (insn) = ret_rtx;
|
||||
}
|
||||
else
|
||||
insn = emit_insn (par);
|
||||
return insn;
|
||||
}
|
||||
|
||||
/* Determine whether the gp REG is really used. */
|
||||
|
@ -20026,16 +20037,13 @@ rs6000_emit_prologue (void)
|
|||
}
|
||||
else if (!WORLD_SAVE_P (info) && info->first_fp_reg_save != 64)
|
||||
{
|
||||
rtx par;
|
||||
|
||||
par = rs6000_make_savres_rtx (info, frame_reg_rtx,
|
||||
info->fp_save_offset + sp_offset,
|
||||
DFmode,
|
||||
/*savep=*/true, /*gpr=*/false,
|
||||
/*lr=*/(strategy
|
||||
& SAVE_NOINLINE_FPRS_SAVES_LR)
|
||||
!= 0);
|
||||
insn = emit_insn (par);
|
||||
insn = rs6000_emit_savres_rtx (info, frame_reg_rtx,
|
||||
info->fp_save_offset + sp_offset,
|
||||
DFmode,
|
||||
/*savep=*/true, /*gpr=*/false,
|
||||
/*lr=*/((strategy
|
||||
& SAVE_NOINLINE_FPRS_SAVES_LR)
|
||||
!= 0));
|
||||
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
|
||||
NULL_RTX, NULL_RTX);
|
||||
}
|
||||
|
@ -20125,13 +20133,10 @@ rs6000_emit_prologue (void)
|
|||
}
|
||||
else
|
||||
{
|
||||
rtx par;
|
||||
|
||||
par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11),
|
||||
0, reg_mode,
|
||||
/*savep=*/true, /*gpr=*/true,
|
||||
/*lr=*/false);
|
||||
insn = emit_insn (par);
|
||||
insn = rs6000_emit_savres_rtx (info, gen_rtx_REG (Pmode, 11),
|
||||
0, reg_mode,
|
||||
/*savep=*/true, /*gpr=*/true,
|
||||
/*lr=*/false);
|
||||
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
|
||||
NULL_RTX, NULL_RTX);
|
||||
}
|
||||
|
@ -20143,8 +20148,6 @@ rs6000_emit_prologue (void)
|
|||
}
|
||||
else if (!WORLD_SAVE_P (info) && !saving_GPRs_inline)
|
||||
{
|
||||
rtx par;
|
||||
|
||||
/* Need to adjust r11 (r12) if we saved any FPRs. */
|
||||
if (info->first_fp_reg_save != 64)
|
||||
{
|
||||
|
@ -20155,14 +20158,13 @@ rs6000_emit_prologue (void)
|
|||
emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx, offset));
|
||||
}
|
||||
|
||||
par = rs6000_make_savres_rtx (info, frame_reg_rtx,
|
||||
info->gp_save_offset + sp_offset,
|
||||
reg_mode,
|
||||
/*savep=*/true, /*gpr=*/true,
|
||||
/*lr=*/(strategy
|
||||
& SAVE_NOINLINE_GPRS_SAVES_LR)
|
||||
!= 0);
|
||||
insn = emit_insn (par);
|
||||
insn = rs6000_emit_savres_rtx (info, frame_reg_rtx,
|
||||
info->gp_save_offset + sp_offset,
|
||||
reg_mode,
|
||||
/*savep=*/true, /*gpr=*/true,
|
||||
/*lr=*/((strategy
|
||||
& SAVE_NOINLINE_GPRS_SAVES_LR)
|
||||
!= 0));
|
||||
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
|
||||
NULL_RTX, NULL_RTX);
|
||||
}
|
||||
|
@ -20611,6 +20613,20 @@ offset_below_red_zone_p (HOST_WIDE_INT offset)
|
|||
: TARGET_32BIT ? -220 : -288);
|
||||
}
|
||||
|
||||
/* Append CFA_RESTORES to any existing REG_NOTES on the last insn. */
|
||||
|
||||
static void
|
||||
emit_cfa_restores (rtx cfa_restores)
|
||||
{
|
||||
rtx insn = get_last_insn ();
|
||||
rtx *loc = ®_NOTES (insn);
|
||||
|
||||
while (*loc)
|
||||
loc = &XEXP (*loc, 1);
|
||||
*loc = cfa_restores;
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
/* Emit function epilogue as insns. */
|
||||
|
||||
void
|
||||
|
@ -20708,6 +20724,14 @@ rs6000_emit_epilogue (int sibcall)
|
|||
rtx mem = gen_frame_mem (reg_mode, addr);
|
||||
|
||||
RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
|
||||
|
||||
if (flag_shrink_wrap)
|
||||
{
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
|
||||
gen_rtx_REG (Pmode, LR_REGNO),
|
||||
cfa_restores);
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 32 - info->first_gp_reg_save; i++)
|
||||
|
@ -20719,6 +20743,8 @@ rs6000_emit_epilogue (int sibcall)
|
|||
rtx mem = gen_frame_mem (reg_mode, addr);
|
||||
|
||||
RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
|
||||
if (flag_shrink_wrap)
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
|
||||
}
|
||||
for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
|
||||
{
|
||||
|
@ -20729,6 +20755,8 @@ rs6000_emit_epilogue (int sibcall)
|
|||
rtx mem = gen_frame_mem (V4SImode, addr);
|
||||
|
||||
RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
|
||||
if (flag_shrink_wrap)
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
|
||||
}
|
||||
for (i = 0; info->first_fp_reg_save + i <= 63; i++)
|
||||
{
|
||||
|
@ -20742,6 +20770,8 @@ rs6000_emit_epilogue (int sibcall)
|
|||
? DFmode : SFmode), addr);
|
||||
|
||||
RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
|
||||
if (flag_shrink_wrap)
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
|
||||
}
|
||||
RTVEC_ELT (p, j++)
|
||||
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 0));
|
||||
|
@ -20753,8 +20783,14 @@ rs6000_emit_epilogue (int sibcall)
|
|||
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 8));
|
||||
RTVEC_ELT (p, j++)
|
||||
= gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, 10));
|
||||
emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
|
||||
insn = emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
|
||||
|
||||
if (flag_shrink_wrap)
|
||||
{
|
||||
REG_NOTES (insn) = cfa_restores;
|
||||
add_reg_note (insn, REG_CFA_DEF_CFA, sp_reg_rtx);
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -20799,9 +20835,10 @@ rs6000_emit_epilogue (int sibcall)
|
|||
|
||||
reg = gen_rtx_REG (V4SImode, i);
|
||||
emit_move_insn (reg, mem);
|
||||
if (offset_below_red_zone_p (info->altivec_save_offset
|
||||
+ (i - info->first_altivec_reg_save)
|
||||
* 16))
|
||||
if (flag_shrink_wrap
|
||||
|| offset_below_red_zone_p (info->altivec_save_offset
|
||||
+ (i - info->first_altivec_reg_save)
|
||||
* 16))
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
|
||||
cfa_restores);
|
||||
}
|
||||
|
@ -20940,7 +20977,7 @@ rs6000_emit_epilogue (int sibcall)
|
|||
|
||||
reg = gen_rtx_REG (V4SImode, i);
|
||||
emit_move_insn (reg, mem);
|
||||
if (DEFAULT_ABI == ABI_V4)
|
||||
if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
|
||||
cfa_restores);
|
||||
}
|
||||
|
@ -20990,8 +21027,7 @@ rs6000_emit_epilogue (int sibcall)
|
|||
emit_move_insn (cr_save_reg, mem);
|
||||
}
|
||||
|
||||
/* Set LR here to try to overlap restores below. LR is always saved
|
||||
above incoming stack, so it never needs REG_CFA_RESTORE. */
|
||||
/* 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));
|
||||
|
@ -21029,7 +21065,7 @@ rs6000_emit_epilogue (int sibcall)
|
|||
/* Restore GPRs. This is done as a PARALLEL if we are using
|
||||
the load-multiple instructions. */
|
||||
if (TARGET_SPE_ABI
|
||||
&& info->spe_64bit_regs_used != 0
|
||||
&& info->spe_64bit_regs_used
|
||||
&& info->first_gp_reg_save != 32)
|
||||
{
|
||||
/* Determine whether we can address all of the registers that need
|
||||
|
@ -21053,7 +21089,7 @@ rs6000_emit_epilogue (int sibcall)
|
|||
int ool_adjust = (restoring_GPRs_inline
|
||||
? 0
|
||||
: (info->first_gp_reg_save
|
||||
- (FIRST_SAVRES_REGISTER+1))*8);
|
||||
- (FIRST_SAVRES_REGISTER + 1)) * 8);
|
||||
|
||||
if (frame_reg_rtx == sp_reg_rtx)
|
||||
frame_reg_rtx = gen_rtx_REG (Pmode, 11);
|
||||
|
@ -21084,48 +21120,28 @@ rs6000_emit_epilogue (int sibcall)
|
|||
mem = gen_rtx_MEM (V2SImode, addr);
|
||||
reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
|
||||
|
||||
insn = emit_move_insn (reg, mem);
|
||||
if (DEFAULT_ABI == ABI_V4)
|
||||
{
|
||||
if (frame_pointer_needed
|
||||
&& info->first_gp_reg_save + i
|
||||
== HARD_FRAME_POINTER_REGNUM)
|
||||
{
|
||||
add_reg_note (insn, REG_CFA_DEF_CFA,
|
||||
plus_constant (frame_reg_rtx,
|
||||
sp_offset));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
|
||||
cfa_restores);
|
||||
}
|
||||
emit_move_insn (reg, mem);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx par;
|
||||
|
||||
par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11),
|
||||
0, reg_mode,
|
||||
/*savep=*/false, /*gpr=*/true,
|
||||
/*lr=*/true);
|
||||
emit_jump_insn (par);
|
||||
/* We don't want anybody else emitting things after we jumped
|
||||
back. */
|
||||
return;
|
||||
}
|
||||
rs6000_emit_savres_rtx (info, gen_rtx_REG (Pmode, 11),
|
||||
0, reg_mode,
|
||||
/*savep=*/false, /*gpr=*/true,
|
||||
/*lr=*/true);
|
||||
}
|
||||
else if (!restoring_GPRs_inline)
|
||||
{
|
||||
/* We are jumping to an out-of-line function. */
|
||||
bool can_use_exit = info->first_fp_reg_save == 64;
|
||||
rtx par;
|
||||
|
||||
/* Emit stack reset code if we need it. */
|
||||
if (can_use_exit)
|
||||
rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx,
|
||||
sp_offset, can_use_exit);
|
||||
{
|
||||
rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx,
|
||||
sp_offset, can_use_exit);
|
||||
if (info->cr_save_p)
|
||||
rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_insn (gen_add3_insn (gen_rtx_REG (Pmode, DEFAULT_ABI == ABI_AIX
|
||||
|
@ -21136,45 +21152,10 @@ rs6000_emit_epilogue (int sibcall)
|
|||
sp_offset += info->fp_size;
|
||||
}
|
||||
|
||||
par = rs6000_make_savres_rtx (info, frame_reg_rtx,
|
||||
info->gp_save_offset, reg_mode,
|
||||
/*savep=*/false, /*gpr=*/true,
|
||||
/*lr=*/can_use_exit);
|
||||
|
||||
if (can_use_exit)
|
||||
{
|
||||
if (info->cr_save_p)
|
||||
{
|
||||
rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
|
||||
if (DEFAULT_ABI == ABI_V4)
|
||||
cfa_restores
|
||||
= alloc_reg_note (REG_CFA_RESTORE,
|
||||
gen_rtx_REG (SImode, CR2_REGNO),
|
||||
cfa_restores);
|
||||
}
|
||||
|
||||
emit_jump_insn (par);
|
||||
|
||||
/* We don't want anybody else emitting things after we jumped
|
||||
back. */
|
||||
return;
|
||||
}
|
||||
|
||||
insn = emit_insn (par);
|
||||
if (DEFAULT_ABI == ABI_V4)
|
||||
{
|
||||
if (frame_pointer_needed)
|
||||
{
|
||||
add_reg_note (insn, REG_CFA_DEF_CFA,
|
||||
plus_constant (frame_reg_rtx, sp_offset));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
for (i = info->first_gp_reg_save; i < 32; i++)
|
||||
cfa_restores
|
||||
= alloc_reg_note (REG_CFA_RESTORE,
|
||||
gen_rtx_REG (reg_mode, i), cfa_restores);
|
||||
}
|
||||
rs6000_emit_savres_rtx (info, frame_reg_rtx,
|
||||
info->gp_save_offset, reg_mode,
|
||||
/*savep=*/false, /*gpr=*/true,
|
||||
/*lr=*/can_use_exit);
|
||||
}
|
||||
else if (using_load_multiple)
|
||||
{
|
||||
|
@ -21190,17 +21171,8 @@ rs6000_emit_epilogue (int sibcall)
|
|||
rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
|
||||
|
||||
RTVEC_ELT (p, i) = gen_rtx_SET (VOIDmode, reg, mem);
|
||||
if (DEFAULT_ABI == ABI_V4)
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
|
||||
cfa_restores);
|
||||
}
|
||||
insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
|
||||
if (DEFAULT_ABI == ABI_V4 && frame_pointer_needed)
|
||||
{
|
||||
add_reg_note (insn, REG_CFA_DEF_CFA,
|
||||
plus_constant (frame_reg_rtx, sp_offset));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -21214,24 +21186,70 @@ rs6000_emit_epilogue (int sibcall)
|
|||
rtx mem = gen_frame_mem (reg_mode, addr);
|
||||
rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
|
||||
|
||||
insn = emit_move_insn (reg, mem);
|
||||
if (DEFAULT_ABI == ABI_V4)
|
||||
{
|
||||
if (frame_pointer_needed
|
||||
&& info->first_gp_reg_save + i
|
||||
== HARD_FRAME_POINTER_REGNUM)
|
||||
{
|
||||
add_reg_note (insn, REG_CFA_DEF_CFA,
|
||||
plus_constant (frame_reg_rtx, sp_offset));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
|
||||
cfa_restores);
|
||||
}
|
||||
emit_move_insn (reg, mem);
|
||||
}
|
||||
}
|
||||
|
||||
if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
|
||||
{
|
||||
/* If the frame pointer was used then we can't delay emitting
|
||||
a REG_CFA_DEF_CFA note. This must happen on the insn that
|
||||
restores the frame pointer, r31. We may have already emitted
|
||||
a REG_CFA_DEF_CFA note, but that's OK; A duplicate is
|
||||
discarded by dwarf2cfi.c/dwarf2out.c, and in any case would
|
||||
be harmless if emitted. */
|
||||
if (frame_pointer_needed)
|
||||
{
|
||||
insn = get_last_insn ();
|
||||
add_reg_note (insn, REG_CFA_DEF_CFA,
|
||||
plus_constant (frame_reg_rtx, sp_offset));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
/* Set up cfa_restores. We always need these when
|
||||
shrink-wrapping. If not shrink-wrapping then we only need
|
||||
the cfa_restore when the stack location is no longer valid.
|
||||
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);
|
||||
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);
|
||||
|
||||
for (i = info->first_gp_reg_save; i < 32; i++)
|
||||
if (!restoring_GPRs_inline
|
||||
|| using_load_multiple
|
||||
|| rs6000_reg_live_or_pic_offset_p (i))
|
||||
{
|
||||
rtx reg = gen_rtx_REG (reg_mode, i);
|
||||
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
|
||||
}
|
||||
}
|
||||
|
||||
if (!restoring_GPRs_inline
|
||||
&& info->first_fp_reg_save == 64)
|
||||
{
|
||||
/* We are jumping to an out-of-line function. */
|
||||
if (cfa_restores)
|
||||
emit_cfa_restores (cfa_restores);
|
||||
return;
|
||||
}
|
||||
|
||||
if (restore_lr && !restoring_GPRs_inline)
|
||||
{
|
||||
rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx,
|
||||
|
@ -21245,8 +21263,8 @@ rs6000_emit_epilogue (int sibcall)
|
|||
/* Restore fpr's if we need to do it without calling a function. */
|
||||
if (restoring_FPRs_inline)
|
||||
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
|
||||
if ((df_regs_ever_live_p (info->first_fp_reg_save+i)
|
||||
&& ! call_used_regs[info->first_fp_reg_save+i]))
|
||||
if ((df_regs_ever_live_p (info->first_fp_reg_save + i)
|
||||
&& !call_used_regs[info->first_fp_reg_save + i]))
|
||||
{
|
||||
rtx addr, mem, reg;
|
||||
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
|
||||
|
@ -21260,20 +21278,13 @@ rs6000_emit_epilogue (int sibcall)
|
|||
info->first_fp_reg_save + i);
|
||||
|
||||
emit_move_insn (reg, mem);
|
||||
if (DEFAULT_ABI == ABI_V4)
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
|
||||
cfa_restores);
|
||||
if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (DEFAULT_ABI == ABI_V4)
|
||||
cfa_restores
|
||||
= alloc_reg_note (REG_CFA_RESTORE, gen_rtx_REG (SImode, CR2_REGNO),
|
||||
cfa_restores);
|
||||
}
|
||||
rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
|
||||
|
||||
/* If this is V.4, unwind the stack pointer after all of the loads
|
||||
have been done. */
|
||||
|
@ -21301,15 +21312,40 @@ rs6000_emit_epilogue (int sibcall)
|
|||
rtvec p;
|
||||
bool lr = (strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
|
||||
if (! restoring_FPRs_inline)
|
||||
p = rtvec_alloc (4 + 64 - info->first_fp_reg_save);
|
||||
{
|
||||
p = rtvec_alloc (4 + 64 - info->first_fp_reg_save);
|
||||
RTVEC_ELT (p, 0) = ret_rtx;
|
||||
}
|
||||
else
|
||||
p = rtvec_alloc (2);
|
||||
{
|
||||
if (cfa_restores)
|
||||
{
|
||||
/* We can't hang the cfa_restores off a simple return,
|
||||
since the shrink-wrap code sometimes uses an existing
|
||||
return. This means there might be a path from
|
||||
pre-prologue code to this return, and dwarf2cfi code
|
||||
wants the eh_frame unwinder state to be the same on
|
||||
all paths to any point. So we need to emit the
|
||||
cfa_restores before the return. For -m64 we really
|
||||
don't need epilogue cfa_restores at all, except for
|
||||
this irritating dwarf2cfi with shrink-wrap
|
||||
requirement; The stack red-zone means eh_frame info
|
||||
from the prologue telling the unwinder to restore
|
||||
from the stack is perfectly good right to the end of
|
||||
the function. */
|
||||
emit_insn (gen_blockage ());
|
||||
emit_cfa_restores (cfa_restores);
|
||||
cfa_restores = NULL_RTX;
|
||||
}
|
||||
p = rtvec_alloc (2);
|
||||
RTVEC_ELT (p, 0) = simple_return_rtx;
|
||||
}
|
||||
|
||||
RTVEC_ELT (p, 0) = ret_rtx;
|
||||
RTVEC_ELT (p, 1) = ((restoring_FPRs_inline || !lr)
|
||||
? gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 65))
|
||||
? gen_rtx_USE (VOIDmode,
|
||||
gen_rtx_REG (Pmode, LR_REGNO))
|
||||
: gen_rtx_CLOBBER (VOIDmode,
|
||||
gen_rtx_REG (Pmode, 65)));
|
||||
gen_rtx_REG (Pmode, LR_REGNO)));
|
||||
|
||||
/* If we have to restore more than two FP registers, branch to the
|
||||
restore function. It will return to our caller. */
|
||||
|
@ -21318,6 +21354,12 @@ 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);
|
||||
|
||||
sym = rs6000_savres_routine_sym (info,
|
||||
/*savep=*/false,
|
||||
/*gpr=*/false,
|
||||
|
@ -21329,20 +21371,32 @@ rs6000_emit_epilogue (int sibcall)
|
|||
? 1 : 11));
|
||||
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
|
||||
{
|
||||
rtx addr, mem;
|
||||
addr = gen_rtx_PLUS (Pmode, sp_reg_rtx,
|
||||
GEN_INT (info->fp_save_offset + 8*i));
|
||||
mem = gen_frame_mem (DFmode, addr);
|
||||
rtx addr, mem, reg;
|
||||
|
||||
RTVEC_ELT (p, i+4) =
|
||||
gen_rtx_SET (VOIDmode,
|
||||
gen_rtx_REG (DFmode, info->first_fp_reg_save + i),
|
||||
mem);
|
||||
addr = gen_rtx_PLUS (Pmode, sp_reg_rtx,
|
||||
GEN_INT (info->fp_save_offset + 8 * i));
|
||||
mem = gen_frame_mem (DFmode, addr);
|
||||
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)
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
|
||||
cfa_restores);
|
||||
}
|
||||
}
|
||||
|
||||
emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
|
||||
}
|
||||
|
||||
if (cfa_restores)
|
||||
{
|
||||
if (sibcall)
|
||||
/* Ensure the cfa_restores are hung off an insn that won't
|
||||
be reordered above other restores. */
|
||||
emit_insn (gen_blockage ());
|
||||
|
||||
emit_cfa_restores (cfa_restores);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write function epilogue. */
|
||||
|
@ -21707,7 +21761,7 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
|
|||
gen_rtx_USE (VOIDmode,
|
||||
gen_rtx_REG (SImode,
|
||||
LR_REGNO)),
|
||||
ret_rtx)));
|
||||
simple_return_rtx)));
|
||||
SIBLING_CALL_P (insn) = 1;
|
||||
emit_barrier ();
|
||||
|
||||
|
|
|
@ -894,10 +894,11 @@ extern unsigned rs6000_pointer_size;
|
|||
cr1 (not saved, but used for FP operations)
|
||||
cr0 (not saved, but used for arithmetic operations)
|
||||
cr4, cr3, cr2 (saved)
|
||||
r0 (not saved; cannot be base reg)
|
||||
r9 (not saved; best for TImode)
|
||||
r11, r10, r8-r4 (not saved; highest used first to make less conflict)
|
||||
r10, r8-r4 (not saved; highest first for less conflict with params)
|
||||
r3 (not saved; return value register)
|
||||
r11 (not saved; later alloc to help shrink-wrap)
|
||||
r0 (not saved; cannot be base reg)
|
||||
r31 - r13 (saved; order given to save least number)
|
||||
r12 (not saved; if used for DImode or DFmode would use r13)
|
||||
mq (not saved; best to use it if we can)
|
||||
|
@ -922,6 +923,14 @@ extern unsigned rs6000_pointer_size;
|
|||
#define MAYBE_R2_FIXED
|
||||
#endif
|
||||
|
||||
#if FIXED_R13 == 1
|
||||
#define EARLY_R12 12,
|
||||
#define LATE_R12
|
||||
#else
|
||||
#define EARLY_R12
|
||||
#define LATE_R12 12,
|
||||
#endif
|
||||
|
||||
#define REG_ALLOC_ORDER \
|
||||
{32, \
|
||||
45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, \
|
||||
|
@ -929,11 +938,11 @@ extern unsigned rs6000_pointer_size;
|
|||
63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \
|
||||
50, 49, 48, 47, 46, \
|
||||
75, 74, 69, 68, 72, 71, 70, \
|
||||
0, MAYBE_R2_AVAILABLE \
|
||||
9, 11, 10, 8, 7, 6, 5, 4, \
|
||||
3, \
|
||||
MAYBE_R2_AVAILABLE \
|
||||
9, 10, 8, 7, 6, 5, 4, \
|
||||
3, EARLY_R12 11, 0, \
|
||||
31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, \
|
||||
18, 17, 16, 15, 14, 13, 12, \
|
||||
18, 17, 16, 15, 14, 13, LATE_R12 \
|
||||
64, 66, 65, \
|
||||
73, 1, MAYBE_R2_FIXED 67, 76, \
|
||||
/* AltiVec registers. */ \
|
||||
|
|
|
@ -264,6 +264,12 @@
|
|||
; Iterator for just SF/DF
|
||||
(define_mode_iterator SFDF [SF DF])
|
||||
|
||||
; Conditional returns.
|
||||
(define_code_iterator any_return [return simple_return])
|
||||
(define_code_attr return_pred [(return "direct_return ()")
|
||||
(simple_return "")])
|
||||
(define_code_attr return_str [(return "") (simple_return "simple_")])
|
||||
|
||||
; Various instructions that come in SI and DI forms.
|
||||
; A generic w/d attribute, for things like cmpw/cmpd.
|
||||
(define_mode_attr wd [(QI "b") (HI "h") (SI "w") (DI "d")])
|
||||
|
@ -12718,7 +12724,7 @@
|
|||
(match_operand 1 "" ""))
|
||||
(use (match_operand 2 "" ""))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(return)])]
|
||||
(simple_return)])]
|
||||
""
|
||||
"
|
||||
{
|
||||
|
@ -12742,7 +12748,7 @@
|
|||
(match_operand 1 "" "g,g"))
|
||||
(use (match_operand:SI 2 "immediate_operand" "O,n"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(return)]
|
||||
(simple_return)]
|
||||
"(INTVAL (operands[2]) & CALL_LONG) == 0"
|
||||
"*
|
||||
{
|
||||
|
@ -12762,7 +12768,7 @@
|
|||
(match_operand 1 "" "g,g"))
|
||||
(use (match_operand:SI 2 "immediate_operand" "O,n"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(return)]
|
||||
(simple_return)]
|
||||
"TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 0"
|
||||
"*
|
||||
{
|
||||
|
@ -12783,7 +12789,7 @@
|
|||
(match_operand 2 "" "g,g")))
|
||||
(use (match_operand:SI 3 "immediate_operand" "O,n"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(return)]
|
||||
(simple_return)]
|
||||
"(INTVAL (operands[3]) & CALL_LONG) == 0"
|
||||
"*
|
||||
{
|
||||
|
@ -12805,7 +12811,7 @@
|
|||
(match_operand 2 "" "g,g")))
|
||||
(use (match_operand:SI 3 "immediate_operand" "O,n"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(return)]
|
||||
(simple_return)]
|
||||
"TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0"
|
||||
"*
|
||||
{
|
||||
|
@ -12825,7 +12831,7 @@
|
|||
(match_operand 1 "" "g,g"))
|
||||
(use (match_operand:SI 2 "immediate_operand" "O,O"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(return)]
|
||||
(simple_return)]
|
||||
"DEFAULT_ABI == ABI_AIX
|
||||
&& (INTVAL (operands[2]) & CALL_LONG) == 0"
|
||||
"@
|
||||
|
@ -12840,7 +12846,7 @@
|
|||
(match_operand 2 "" "g,g")))
|
||||
(use (match_operand:SI 3 "immediate_operand" "O,O"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(return)]
|
||||
(simple_return)]
|
||||
"DEFAULT_ABI == ABI_AIX
|
||||
&& (INTVAL (operands[3]) & CALL_LONG) == 0"
|
||||
"@
|
||||
|
@ -12854,7 +12860,7 @@
|
|||
(match_operand 1 "" ""))
|
||||
(use (match_operand 2 "immediate_operand" "O,n,O,n"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(return)]
|
||||
(simple_return)]
|
||||
"(DEFAULT_ABI == ABI_DARWIN
|
||||
|| DEFAULT_ABI == ABI_V4)
|
||||
&& (INTVAL (operands[2]) & CALL_LONG) == 0"
|
||||
|
@ -12885,7 +12891,7 @@
|
|||
(match_operand 2 "" "")))
|
||||
(use (match_operand 3 "" ""))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(return)])]
|
||||
(simple_return)])]
|
||||
""
|
||||
"
|
||||
{
|
||||
|
@ -12906,7 +12912,7 @@
|
|||
(match_operand 2 "" "")))
|
||||
(use (match_operand:SI 3 "immediate_operand" "O,n,O,n"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(return)]
|
||||
(simple_return)]
|
||||
"(DEFAULT_ABI == ABI_DARWIN
|
||||
|| DEFAULT_ABI == ABI_V4)
|
||||
&& (INTVAL (operands[3]) & CALL_LONG) == 0"
|
||||
|
@ -15236,9 +15242,9 @@
|
|||
[(match_operand 1
|
||||
"cc_reg_operand" "y")
|
||||
(const_int 0)])
|
||||
(return)
|
||||
(any_return)
|
||||
(pc)))]
|
||||
"direct_return ()"
|
||||
"<return_pred>"
|
||||
"*
|
||||
{
|
||||
return output_cbranch (operands[0], NULL, 0, insn);
|
||||
|
@ -15268,8 +15274,8 @@
|
|||
"cc_reg_operand" "y")
|
||||
(const_int 0)])
|
||||
(pc)
|
||||
(return)))]
|
||||
"direct_return ()"
|
||||
(any_return)))]
|
||||
"<return_pred>"
|
||||
"*
|
||||
{
|
||||
return output_cbranch (operands[0], NULL, 1, insn);
|
||||
|
@ -15399,9 +15405,9 @@
|
|||
"b %l0"
|
||||
[(set_attr "type" "branch")])
|
||||
|
||||
(define_insn "return"
|
||||
[(return)]
|
||||
"direct_return ()"
|
||||
(define_insn "<return_str>return"
|
||||
[(any_return)]
|
||||
"<return_pred>"
|
||||
"{br|blr}"
|
||||
[(set_attr "type" "jmpreg")])
|
||||
|
||||
|
@ -15923,7 +15929,7 @@
|
|||
(set_attr "cell_micro" "always")])
|
||||
|
||||
(define_insn "*return_internal_<mode>"
|
||||
[(return)
|
||||
[(simple_return)
|
||||
(use (match_operand:P 0 "register_operand" "lc"))]
|
||||
""
|
||||
"b%T0"
|
||||
|
|
Loading…
Add table
Reference in a new issue