re PR target/35907 (64-bit power6 glibc miscompilation)
PR target/35907 * config/rs6000/rs6000.c (rs6000_emit_epilogue): Restore vr and vrsave regs before frame pop when needed. If use_backchain_to_restore_sp then load backchain into a temp reg to restore vr and vrsave. Add code to restore vr after frame pop if possible. From-SVN: r134387
This commit is contained in:
parent
35485e124c
commit
e6477eaa4d
2 changed files with 116 additions and 31 deletions
|
@ -1,3 +1,11 @@
|
|||
2008-04-17 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
PR target/35907
|
||||
* config/rs6000/rs6000.c (rs6000_emit_epilogue): Restore vr and vrsave
|
||||
regs before frame pop when needed. If use_backchain_to_restore_sp
|
||||
then load backchain into a temp reg to restore vr and vrsave. Add
|
||||
code to restore vr after frame pop if possible.
|
||||
|
||||
2008-04-17 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
* tree-vn.c (expressions_equal_p): Do not check type
|
||||
|
|
|
@ -16370,8 +16370,108 @@ rs6000_emit_epilogue (int sibcall)
|
|||
if (info->push_p)
|
||||
sp_offset = info->total_size;
|
||||
|
||||
/* Restore AltiVec registers if needed. */
|
||||
if (TARGET_ALTIVEC_ABI && info->altivec_size != 0)
|
||||
/* Restore AltiVec registers if we must do so before adjusting the
|
||||
stack. */
|
||||
if (TARGET_ALTIVEC_ABI
|
||||
&& info->altivec_size != 0
|
||||
&& DEFAULT_ABI != ABI_V4
|
||||
&& info->altivec_save_offset < (TARGET_32BIT ? -220 : -288))
|
||||
{
|
||||
int i;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
|
||||
if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
|
||||
{
|
||||
rtx addr, areg, mem;
|
||||
|
||||
areg = gen_rtx_REG (Pmode, 0);
|
||||
emit_move_insn
|
||||
(areg, GEN_INT (info->altivec_save_offset
|
||||
+ sp_offset
|
||||
+ 16 * (i - info->first_altivec_reg_save)));
|
||||
|
||||
/* AltiVec addressing mode is [reg+reg]. */
|
||||
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg);
|
||||
mem = gen_frame_mem (V4SImode, addr);
|
||||
|
||||
emit_move_insn (gen_rtx_REG (V4SImode, i), mem);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore VRSAVE if we must do so before adjusting the stack. */
|
||||
if (TARGET_ALTIVEC
|
||||
&& TARGET_ALTIVEC_VRSAVE
|
||||
&& info->vrsave_mask != 0
|
||||
&& 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)
|
||||
{
|
||||
frame_reg_rtx = gen_rtx_REG (Pmode, 11);
|
||||
emit_move_insn (frame_reg_rtx,
|
||||
gen_rtx_MEM (Pmode, sp_reg_rtx));
|
||||
sp_offset = 0;
|
||||
}
|
||||
|
||||
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
|
||||
GEN_INT (info->vrsave_save_offset + sp_offset));
|
||||
mem = gen_frame_mem (SImode, addr);
|
||||
reg = gen_rtx_REG (SImode, 12);
|
||||
emit_move_insn (reg, mem);
|
||||
|
||||
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 (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
|
||||
{
|
||||
/* Under V.4, don't reset the stack pointer until after we're done
|
||||
loading the saved registers. */
|
||||
if (DEFAULT_ABI == ABI_V4)
|
||||
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 (info->push_p
|
||||
&& DEFAULT_ABI != ABI_V4
|
||||
&& !current_function_calls_eh_return)
|
||||
{
|
||||
emit_insn (TARGET_32BIT
|
||||
? gen_addsi3 (sp_reg_rtx, sp_reg_rtx,
|
||||
GEN_INT (info->total_size))
|
||||
: gen_adddi3 (sp_reg_rtx, sp_reg_rtx,
|
||||
GEN_INT (info->total_size)));
|
||||
sp_offset = 0;
|
||||
}
|
||||
|
||||
/* Restore AltiVec registers if we have not done so already. */
|
||||
if (TARGET_ALTIVEC_ABI
|
||||
&& info->altivec_size != 0
|
||||
&& (DEFAULT_ABI == ABI_V4
|
||||
|| info->altivec_save_offset >= (TARGET_32BIT ? -220 : -288)))
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -16394,35 +16494,12 @@ rs6000_emit_epilogue (int sibcall)
|
|||
}
|
||||
}
|
||||
|
||||
/* 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 (use_backchain_to_restore_sp)
|
||||
{
|
||||
/* Under V.4, don't reset the stack pointer until after we're done
|
||||
loading the saved registers. */
|
||||
if (DEFAULT_ABI == ABI_V4)
|
||||
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 (info->push_p
|
||||
&& DEFAULT_ABI != ABI_V4
|
||||
&& !current_function_calls_eh_return)
|
||||
{
|
||||
emit_insn (TARGET_32BIT
|
||||
? gen_addsi3 (sp_reg_rtx, sp_reg_rtx,
|
||||
GEN_INT (info->total_size))
|
||||
: gen_adddi3 (sp_reg_rtx, sp_reg_rtx,
|
||||
GEN_INT (info->total_size)));
|
||||
sp_offset = 0;
|
||||
}
|
||||
|
||||
/* Restore VRSAVE if needed. */
|
||||
if (TARGET_ALTIVEC && TARGET_ALTIVEC_VRSAVE
|
||||
&& info->vrsave_mask != 0)
|
||||
/* Restore VRSAVE if we have not done so already. */
|
||||
if (TARGET_ALTIVEC
|
||||
&& TARGET_ALTIVEC_VRSAVE
|
||||
&& info->vrsave_mask != 0
|
||||
&& (DEFAULT_ABI == ABI_V4
|
||||
|| info->vrsave_save_offset >= (TARGET_32BIT ? -220 : -288)))
|
||||
{
|
||||
rtx addr, mem, reg;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue