Commit 52ff33d0 by Nathan Froyd Committed by Nathan Froyd

rs6000.h (FIXED_SCRATCH): Use r0 as a scratch register on SPE targets.

	* config/rs6000/rs6000.h (FIXED_SCRATCH): Use r0 as a scratch
	register on SPE targets.  Change documentation to reflect
	reality.
	* config/rs6000/rs6000.c (rs6000_conditional_register_usage):
	Change FIXED_SCRATCH to 14 and document why we're keeping r14
	out of the register allocation pool.
	(rs6000_reg_live_or_pic_offset_p): New function.
	(rs6000_emit_prologue): Move the actual saving of LR up to free
	r0 for holding r11.  Split saving of SPE 64-bit registers into
	its own case.  Ensure that offsets will always be in-range for
	'evstdd' by using r11 as a scratch register to point at the start
	of the SPE save area.  Save r11 if necessary, as it is the static
	chain register.
	(rs6000_emit_epilogue): Split restoring of SPE 64-bit registers
	into its own case.  Ensure that offsets will always be in-range
	for 'evldd' by using r11 as a scratch register to point at the
	start of the SPE save area.  Also adjust r11 when restoring
	the stack pointer to compensate for pre-loading r11.

From-SVN: r125340
parent b08f991d
2007-06-06 Nathan Froyd <froydnj@codesourcery.com>
* config/rs6000/rs6000.h (FIXED_SCRATCH): Use r0 as a scratch
register on SPE targets. Change documentation to reflect
reality.
* config/rs6000/rs6000.c (rs6000_conditional_register_usage):
Change FIXED_SCRATCH to 14 and document why we're keeping r14
out of the register allocation pool.
(rs6000_reg_live_or_pic_offset_p): New function.
(rs6000_emit_prologue): Move the actual saving of LR up to free
r0 for holding r11. Split saving of SPE 64-bit registers into
its own case. Ensure that offsets will always be in-range for
'evstdd' by using r11 as a scratch register to point at the start
of the SPE save area. Save r11 if necessary, as it is the static
chain register.
(rs6000_emit_epilogue): Split restoring of SPE 64-bit registers
into its own case. Ensure that offsets will always be in-range
for 'evldd' by using r11 as a scratch register to point at the
start of the SPE save area. Also adjust r11 when restoring
the stack pointer to compensate for pre-loading r11.
2007-06-05 Thomas Neumann <tneumann@users.sourceforge.net> 2007-06-05 Thomas Neumann <tneumann@users.sourceforge.net>
* cfg.c (init_flow): Use type safe memory macros. * cfg.c (init_flow): Use type safe memory macros.
......
...@@ -648,6 +648,7 @@ static void rs6000_eliminate_indexed_memrefs (rtx operands[2]); ...@@ -648,6 +648,7 @@ static void rs6000_eliminate_indexed_memrefs (rtx operands[2]);
static const char *rs6000_mangle_fundamental_type (tree); static const char *rs6000_mangle_fundamental_type (tree);
extern const struct attribute_spec rs6000_attribute_table[]; extern const struct attribute_spec rs6000_attribute_table[];
static void rs6000_set_default_type_attributes (tree); static void rs6000_set_default_type_attributes (tree);
static bool rs6000_reg_live_or_pic_offset_p (int);
static void rs6000_output_function_prologue (FILE *, HOST_WIDE_INT); static void rs6000_output_function_prologue (FILE *, HOST_WIDE_INT);
static void rs6000_output_function_epilogue (FILE *, HOST_WIDE_INT); static void rs6000_output_function_epilogue (FILE *, HOST_WIDE_INT);
static void rs6000_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, static void rs6000_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
...@@ -3991,9 +3992,15 @@ rs6000_conditional_register_usage (void) ...@@ -3991,9 +3992,15 @@ rs6000_conditional_register_usage (void)
if (TARGET_SPE) if (TARGET_SPE)
{ {
global_regs[SPEFSCR_REGNO] = 1; global_regs[SPEFSCR_REGNO] = 1;
fixed_regs[FIXED_SCRATCH] /* We used to use r14 as FIXED_SCRATCH to address SPE 64-bit
= call_used_regs[FIXED_SCRATCH] registers in prologues and epilogues. We no longer use r14
= call_really_used_regs[FIXED_SCRATCH] = 1; for FIXED_SCRATCH, but we're keeping r14 out of the allocation
pool for link-compatibility with older versions of GCC. Once
"old" code has died out, we can return r14 to the allocation
pool. */
fixed_regs[14]
= call_used_regs[14]
= call_really_used_regs[14] = 1;
} }
if (! TARGET_ALTIVEC) if (! TARGET_ALTIVEC)
...@@ -14629,6 +14636,20 @@ no_global_regs_above (int first_greg) ...@@ -14629,6 +14636,20 @@ no_global_regs_above (int first_greg)
#define TARGET_FIX_AND_CONTINUE 0 #define TARGET_FIX_AND_CONTINUE 0
#endif #endif
/* Determine whether the gp REG is really used. */
static bool
rs6000_reg_live_or_pic_offset_p (int reg)
{
return ((regs_ever_live[reg]
&& (!call_used_regs[reg]
|| (reg == RS6000_PIC_OFFSET_TABLE_REGNUM
&& TARGET_TOC && TARGET_MINIMAL_TOC)))
|| (reg == RS6000_PIC_OFFSET_TABLE_REGNUM
&& ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
|| (DEFAULT_ABI == ABI_DARWIN && flag_pic))));
}
/* Emit function prologue as insns. */ /* Emit function prologue as insns. */
void void
...@@ -14815,9 +14836,22 @@ rs6000_emit_prologue (void) ...@@ -14815,9 +14836,22 @@ rs6000_emit_prologue (void)
/* If we use the link register, get it into r0. */ /* If we use the link register, get it into r0. */
if (!WORLD_SAVE_P (info) && info->lr_save_p) if (!WORLD_SAVE_P (info) && info->lr_save_p)
{ {
rtx addr, reg, mem;
insn = emit_move_insn (gen_rtx_REG (Pmode, 0), insn = emit_move_insn (gen_rtx_REG (Pmode, 0),
gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)); gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (info->lr_save_offset + sp_offset));
reg = gen_rtx_REG (Pmode, 0);
mem = gen_rtx_MEM (Pmode, addr);
/* This should not be of rs6000_sr_alias_set, because of
__builtin_return_address. */
insn = emit_move_insn (mem, reg);
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
} }
/* If we need to save CR, put it into r12. */ /* If we need to save CR, put it into r12. */
...@@ -14910,59 +14944,99 @@ rs6000_emit_prologue (void) ...@@ -14910,59 +14944,99 @@ rs6000_emit_prologue (void)
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size, rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX); NULL_RTX, NULL_RTX);
} }
else if (!WORLD_SAVE_P (info)
&& TARGET_SPE_ABI
&& info->spe_64bit_regs_used != 0
&& info->first_gp_reg_save != 32)
{
int i;
rtx spe_save_area_ptr;
int using_static_chain_p = (cfun->static_chain_decl != NULL_TREE
&& regs_ever_live[STATIC_CHAIN_REGNUM]
&& !call_used_regs[STATIC_CHAIN_REGNUM]);
/* Determine whether we can address all of the registers that need
to be saved with an offset from the stack pointer that fits in
the small const field for SPE memory instructions. */
int spe_regs_addressable_via_sp
= SPE_CONST_OFFSET_OK(info->spe_gp_save_offset + sp_offset
+ (32 - info->first_gp_reg_save - 1) * reg_size);
int spe_offset;
if (spe_regs_addressable_via_sp)
{
spe_save_area_ptr = sp_reg_rtx;
spe_offset = info->spe_gp_save_offset + sp_offset;
}
else
{
/* Make r11 point to the start of the SPE save area. We need
to be careful here if r11 is holding the static chain. If
it is, then temporarily save it in r0. We would use r0 as
our base register here, but using r0 as a base register in
loads and stores means something different from what we
would like. */
if (using_static_chain_p)
{
rtx r0 = gen_rtx_REG (Pmode, 0);
gcc_assert (info->first_gp_reg_save > 11);
emit_move_insn (r0, gen_rtx_REG (Pmode, 11));
}
spe_save_area_ptr = gen_rtx_REG (Pmode, 11);
emit_insn (gen_addsi3 (spe_save_area_ptr, sp_reg_rtx,
GEN_INT (info->spe_gp_save_offset + sp_offset)));
spe_offset = 0;
}
for (i = 0; i < 32 - info->first_gp_reg_save; i++)
if (rs6000_reg_live_or_pic_offset_p (info->first_gp_reg_save + i))
{
rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
rtx offset, addr, mem;
/* We're doing all this to ensure that the offset fits into
the immediate offset of 'evstdd'. */
gcc_assert (SPE_CONST_OFFSET_OK (reg_size * i + spe_offset));
offset = GEN_INT (reg_size * i + spe_offset);
addr = gen_rtx_PLUS (Pmode, spe_save_area_ptr, offset);
mem = gen_rtx_MEM (V2SImode, addr);
insn = emit_move_insn (mem, reg);
rs6000_frame_related (insn, spe_save_area_ptr,
info->spe_gp_save_offset
+ sp_offset + reg_size * i,
offset, const0_rtx);
}
/* Move the static chain pointer back. */
if (using_static_chain_p && !spe_regs_addressable_via_sp)
emit_move_insn (gen_rtx_REG (Pmode, 11), gen_rtx_REG (Pmode, 0));
}
else if (!WORLD_SAVE_P (info)) else if (!WORLD_SAVE_P (info))
{ {
int i; int i;
for (i = 0; i < 32 - info->first_gp_reg_save; i++) for (i = 0; i < 32 - info->first_gp_reg_save; i++)
if ((regs_ever_live[info->first_gp_reg_save + i] if (rs6000_reg_live_or_pic_offset_p (info->first_gp_reg_save + i))
&& (!call_used_regs[info->first_gp_reg_save + i] {
|| (i + info->first_gp_reg_save rtx addr, reg, mem;
== RS6000_PIC_OFFSET_TABLE_REGNUM reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
&& TARGET_TOC && TARGET_MINIMAL_TOC)))
|| (i + info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
&& ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
|| (DEFAULT_ABI == ABI_DARWIN && flag_pic))))
{
rtx addr, reg, mem;
reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0) addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
{ GEN_INT (info->gp_save_offset
int offset = info->spe_gp_save_offset + sp_offset + 8 * i; + sp_offset
rtx b; + reg_size * i));
mem = gen_frame_mem (reg_mode, addr);
if (!SPE_CONST_OFFSET_OK (offset)) insn = emit_move_insn (mem, reg);
{ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
b = gen_rtx_REG (Pmode, FIXED_SCRATCH); NULL_RTX, NULL_RTX);
emit_move_insn (b, GEN_INT (offset)); }
}
else
b = GEN_INT (offset);
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, b);
mem = gen_frame_mem (V2SImode, addr);
insn = emit_move_insn (mem, reg);
if (GET_CODE (b) == CONST_INT)
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
else
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
b, GEN_INT (offset));
}
else
{
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (info->gp_save_offset
+ sp_offset
+ reg_size * i));
mem = gen_frame_mem (reg_mode, addr);
insn = emit_move_insn (mem, reg);
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
}
}
} }
/* ??? There's no need to emit actual instructions here, but it's the /* ??? There's no need to emit actual instructions here, but it's the
...@@ -15000,21 +15074,6 @@ rs6000_emit_prologue (void) ...@@ -15000,21 +15074,6 @@ rs6000_emit_prologue (void)
} }
} }
/* Save lr if we used it. */
if (!WORLD_SAVE_P (info) && info->lr_save_p)
{
rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (info->lr_save_offset + sp_offset));
rtx reg = gen_rtx_REG (Pmode, 0);
rtx mem = gen_rtx_MEM (Pmode, addr);
/* This should not be of frame_alias_set, because of
__builtin_return_address. */
insn = emit_move_insn (mem, reg);
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
}
/* Save CR if we use any that must be preserved. */ /* Save CR if we use any that must be preserved. */
if (!WORLD_SAVE_P (info) && info->cr_save_p) if (!WORLD_SAVE_P (info) && info->cr_save_p)
{ {
...@@ -15548,15 +15607,58 @@ rs6000_emit_epilogue (int sibcall) ...@@ -15548,15 +15607,58 @@ rs6000_emit_epilogue (int sibcall)
} }
emit_insn (gen_rtx_PARALLEL (VOIDmode, p)); emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
} }
else if (TARGET_SPE_ABI
&& info->spe_64bit_regs_used != 0
&& info->first_gp_reg_save != 32)
{
rtx spe_save_area_ptr;
/* Determine whether we can address all of the registers that need
to be saved with an offset from the stack pointer that fits in
the small const field for SPE memory instructions. */
int spe_regs_addressable_via_sp
= SPE_CONST_OFFSET_OK(info->spe_gp_save_offset + sp_offset
+ (32 - info->first_gp_reg_save - 1) * reg_size);
int spe_offset;
if (spe_regs_addressable_via_sp)
{
spe_save_area_ptr = frame_reg_rtx;
spe_offset = info->spe_gp_save_offset + sp_offset;
}
else
{
/* Make r11 point to the start of the SPE save area. We worried about
not clobbering it when we were saving registers in the prolgoue.
There's no need to worry here because the static chain is passed
anew to every function. */
spe_save_area_ptr = gen_rtx_REG (Pmode, 11);
emit_insn (gen_addsi3 (spe_save_area_ptr, frame_reg_rtx,
GEN_INT (info->spe_gp_save_offset + sp_offset)));
spe_offset = 0;
}
for (i = 0; i < 32 - info->first_gp_reg_save; i++)
if (rs6000_reg_live_or_pic_offset_p (info->first_gp_reg_save + i))
{
rtx offset, addr, mem;
/* We're doing all this to ensure that the immediate offset
fits into the immediate field of 'evldd'. */
gcc_assert (SPE_CONST_OFFSET_OK (spe_offset + reg_size * i));
offset = GEN_INT (spe_offset + reg_size * i);
addr = gen_rtx_PLUS (Pmode, spe_save_area_ptr, offset);
mem = gen_rtx_MEM (V2SImode, addr);
emit_move_insn (gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
mem);
}
}
else else
for (i = 0; i < 32 - info->first_gp_reg_save; i++) for (i = 0; i < 32 - info->first_gp_reg_save; i++)
if ((regs_ever_live[info->first_gp_reg_save + i] if (rs6000_reg_live_or_pic_offset_p (info->first_gp_reg_save + i))
&& (!call_used_regs[info->first_gp_reg_save + i]
|| (i + info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
&& TARGET_TOC && TARGET_MINIMAL_TOC)))
|| (i + info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
&& ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
|| (DEFAULT_ABI == ABI_DARWIN && flag_pic))))
{ {
rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (info->gp_save_offset GEN_INT (info->gp_save_offset
...@@ -15564,24 +15666,6 @@ rs6000_emit_epilogue (int sibcall) ...@@ -15564,24 +15666,6 @@ rs6000_emit_epilogue (int sibcall)
+ reg_size * i)); + reg_size * i));
rtx mem = gen_frame_mem (reg_mode, addr); rtx mem = gen_frame_mem (reg_mode, addr);
/* Restore 64-bit quantities for SPE. */
if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
{
int offset = info->spe_gp_save_offset + sp_offset + 8 * i;
rtx b;
if (!SPE_CONST_OFFSET_OK (offset))
{
b = gen_rtx_REG (Pmode, FIXED_SCRATCH);
emit_move_insn (b, GEN_INT (offset));
}
else
b = GEN_INT (offset);
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, b);
mem = gen_frame_mem (V2SImode, addr);
}
emit_move_insn (gen_rtx_REG (reg_mode, emit_move_insn (gen_rtx_REG (reg_mode,
info->first_gp_reg_save + i), mem); info->first_gp_reg_save + i), mem);
} }
...@@ -15657,7 +15741,13 @@ rs6000_emit_epilogue (int sibcall) ...@@ -15657,7 +15741,13 @@ rs6000_emit_epilogue (int sibcall)
/* This blockage is needed so that sched doesn't decide to move /* This blockage is needed so that sched doesn't decide to move
the sp change before the register restores. */ the sp change before the register restores. */
rs6000_emit_stack_tie (); rs6000_emit_stack_tie ();
emit_move_insn (sp_reg_rtx, frame_reg_rtx); if (TARGET_SPE_ABI
&& info->spe_64bit_regs_used != 0
&& info->first_gp_reg_save != 32)
emit_insn (gen_addsi3 (sp_reg_rtx, gen_rtx_REG (Pmode, 11),
GEN_INT (-(info->spe_gp_save_offset + sp_offset))));
else
emit_move_insn (sp_reg_rtx, frame_reg_rtx);
} }
else if (sp_offset != 0) else if (sp_offset != 0)
emit_insn (TARGET_32BIT emit_insn (TARGET_32BIT
......
...@@ -913,18 +913,12 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops; ...@@ -913,18 +913,12 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
#define LOGICAL_OP_NON_SHORT_CIRCUIT 0 #define LOGICAL_OP_NON_SHORT_CIRCUIT 0
/* A fixed register used at prologue and epilogue generation to fix /* A fixed register used at epilogue generation to address SPE registers
addressing modes. The SPE needs heavy addressing fixes at the last with negative offsets. The 64-bit load/store instructions on the SPE
minute, and it's best to save a register for it. only take positive offsets (and small ones at that), so we need to
reserve a register for consing up negative offsets. */
AltiVec also needs fixes, but we've gotten around using r11, which #define FIXED_SCRATCH 0
is actually wrong because when use_backchain_to_restore_sp is true,
we end up clobbering r11.
The AltiVec case needs to be fixed. Dunno if we should break ABI
compatibility and reserve a register for it as well.. */
#define FIXED_SCRATCH (TARGET_SPE ? 14 : 11)
/* Define this macro to change register usage conditional on target /* Define this macro to change register usage conditional on target
flags. */ flags. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment