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
|
@ -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>
|
2008-04-17 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
* tree-vn.c (expressions_equal_p): Do not check type
|
* tree-vn.c (expressions_equal_p): Do not check type
|
||||||
|
|
|
@ -16370,8 +16370,108 @@ rs6000_emit_epilogue (int sibcall)
|
||||||
if (info->push_p)
|
if (info->push_p)
|
||||||
sp_offset = info->total_size;
|
sp_offset = info->total_size;
|
||||||
|
|
||||||
/* Restore AltiVec registers if needed. */
|
/* Restore AltiVec registers if we must do so before adjusting the
|
||||||
if (TARGET_ALTIVEC_ABI && info->altivec_size != 0)
|
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;
|
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
|
/* Restore VRSAVE if we have not done so already. */
|
||||||
frame, restore the old stack pointer using the backchain. Otherwise,
|
if (TARGET_ALTIVEC
|
||||||
we know what size to update it with. */
|
&& TARGET_ALTIVEC_VRSAVE
|
||||||
if (use_backchain_to_restore_sp)
|
&& info->vrsave_mask != 0
|
||||||
{
|
&& (DEFAULT_ABI == ABI_V4
|
||||||
/* Under V.4, don't reset the stack pointer until after we're done
|
|| info->vrsave_save_offset >= (TARGET_32BIT ? -220 : -288)))
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
rtx addr, mem, reg;
|
rtx addr, mem, reg;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue