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:
Alan Modra 2008-04-17 12:27:31 +00:00 committed by Alan Modra
parent 35485e124c
commit e6477eaa4d
2 changed files with 116 additions and 31 deletions

View File

@ -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

View File

@ -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;