This is added to the cfun structure. */
typedef struct GTY(()) machine_function
{
- /* Flags if __builtin_return_address (n) with n >= 1 was used. */
- int ra_needs_full_frame;
/* Some local-dynamic symbol. */
const char *some_ld_name;
/* Whether the instruction chain has been scanned already. */
int insn_chain_scanned_p;
+ /* Flags if __builtin_return_address (n) with n >= 1 was used. */
+ int ra_needs_full_frame;
/* Flags if __builtin_return_address (0) was used. */
int ra_need_lr;
+ /* Cache lr_save_p after expansion of builtin_eh_return. */
+ int lr_save_state;
/* Offset from virtual_stack_vars_rtx to the start of the ABI_V4
varargs save area. */
HOST_WIDE_INT varargs_save_offset;
static void emit_frame_save (rtx, rtx, enum machine_mode, unsigned int,
int, HOST_WIDE_INT);
static rtx gen_frame_mem_offset (enum machine_mode, rtx, int);
-static void rs6000_emit_allocate_stack (HOST_WIDE_INT, int, int);
static unsigned rs6000_hash_constant (rtx);
static unsigned toc_hash_function (const void *);
static int toc_hash_eq (const void *, const void *);
int, int *)
= rs6000_legitimize_reload_address;
-static bool rs6000_mode_dependent_address (rtx);
-static bool rs6000_debug_mode_dependent_address (rtx);
-bool (*rs6000_mode_dependent_address_ptr) (rtx)
+static bool rs6000_mode_dependent_address (const_rtx);
+static bool rs6000_debug_mode_dependent_address (const_rtx);
+bool (*rs6000_mode_dependent_address_ptr) (const_rtx)
= rs6000_mode_dependent_address;
static enum reg_class rs6000_secondary_reload_class (enum reg_class,
sub-words of a TFmode operand, which is what we had before. */
static bool
-rs6000_mode_dependent_address (rtx addr)
+rs6000_mode_dependent_address (const_rtx addr)
{
switch (GET_CODE (addr))
{
/* Debug version of rs6000_mode_dependent_address. */
static bool
-rs6000_debug_mode_dependent_address (rtx addr)
+rs6000_debug_mode_dependent_address (const_rtx addr)
{
bool ret = rs6000_mode_dependent_address (addr);
{
rtx basereg = XEXP (XEXP (dst, 0), 0);
rtx offsetreg = XEXP (XEXP (dst, 0), 1);
- gcc_assert (GET_CODE (XEXP (dst, 0)) == PLUS
- && REG_P (basereg)
- && REG_P (offsetreg)
- && REGNO (basereg) != REGNO (offsetreg));
- if (REGNO (basereg) == 0)
- {
- rtx tmp = offsetreg;
- offsetreg = basereg;
- basereg = tmp;
- }
emit_insn (gen_add3_insn (basereg, basereg, offsetreg));
restore_basereg = gen_sub3_insn (basereg, basereg, offsetreg);
dst = replace_equiv_address (dst, basereg);
if (cfun->is_thunk)
return 0;
+ if (cfun->machine->lr_save_state)
+ return cfun->machine->lr_save_state - 1;
+
/* regs_ever_live has LR marked as used if any sibcalls are present,
but this should not force saving and restoring in the
pro/epilogue. Likewise, reg_set_between_p thinks a sibcall
}
else
emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO), operands[0]);
+
+ /* Freeze lr_save_p. We've just emitted rtl that depends on the
+ state of lr_save_p so any change from here on would be a bug. In
+ particular, stop rs6000_ra_ever_killed from considering the SET
+ of lr we may have added just above. */
+ cfun->machine->lr_save_state = info->lr_save_p + 1;
}
static GTY(()) alias_set_type set = -1;
}
/* Emit the correct code for allocating stack space, as insns.
- If COPY_R12, make sure a copy of the old frame is left in r12.
- If COPY_R11, make sure a copy of the old frame is left in r11,
- in preference to r12 if COPY_R12.
+ If COPY_REG, make sure a copy of the old frame is left there.
The generated code may use hard register 0 as a temporary. */
static void
-rs6000_emit_allocate_stack (HOST_WIDE_INT size, int copy_r12, int copy_r11)
+rs6000_emit_allocate_stack (HOST_WIDE_INT size, rtx copy_reg)
{
rtx insn;
rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
warning (0, "stack limit expression is not supported");
}
- if (copy_r12 || copy_r11)
- emit_move_insn (copy_r11
- ? gen_rtx_REG (Pmode, 11)
- : gen_rtx_REG (Pmode, 12),
- stack_reg);
+ if (copy_reg)
+ emit_move_insn (copy_reg, stack_reg);
if (size > 32767)
{
? (!saving_GPRs_inline
&& info->spe_64bit_regs_used == 0)
: (!saving_FPRs_inline || !saving_GPRs_inline));
+ rtx copy_reg = need_r11 ? gen_rtx_REG (Pmode, 11) : NULL;
+
if (info->total_size < 32767)
sp_offset = info->total_size;
+ else if (need_r11)
+ frame_reg_rtx = copy_reg;
+ else if (info->cr_save_p
+ || info->lr_save_p
+ || info->first_fp_reg_save < 64
+ || info->first_gp_reg_save < 32
+ || info->altivec_size != 0
+ || info->vrsave_mask != 0
+ || crtl->calls_eh_return)
+ {
+ copy_reg = frame_ptr_rtx;
+ frame_reg_rtx = copy_reg;
+ }
else
- frame_reg_rtx = (need_r11
- ? gen_rtx_REG (Pmode, 11)
- : frame_ptr_rtx);
- rs6000_emit_allocate_stack (info->total_size,
- (frame_reg_rtx != sp_reg_rtx
- && (info->cr_save_p
- || info->lr_save_p
- || info->first_fp_reg_save < 64
- || info->first_gp_reg_save < 32
- )),
- need_r11);
+ {
+ /* The prologue won't be saving any regs so there is no need
+ to set up a frame register to access any frame save area.
+ We also won't be using sp_offset anywhere below, but set
+ the correct value anyway to protect against future
+ changes to this function. */
+ sp_offset = info->total_size;
+ }
+ rs6000_emit_allocate_stack (info->total_size, copy_reg);
if (frame_reg_rtx != sp_reg_rtx)
rs6000_emit_stack_tie ();
}
if (!WORLD_SAVE_P (info) && info->push_p
&& !(DEFAULT_ABI == ABI_V4 || crtl->calls_eh_return))
{
+ rtx copy_reg = NULL;
+
if (info->total_size < 32767)
- sp_offset = info->total_size;
+ sp_offset = info->total_size;
+ else if (info->altivec_size != 0
+ || info->vrsave_mask != 0)
+ {
+ copy_reg = frame_ptr_rtx;
+ frame_reg_rtx = copy_reg;
+ }
else
- frame_reg_rtx = frame_ptr_rtx;
- rs6000_emit_allocate_stack (info->total_size,
- (frame_reg_rtx != sp_reg_rtx
- && ((info->altivec_size != 0)
- || (info->vrsave_mask != 0)
- )),
- FALSE);
+ sp_offset = info->total_size;
+ rs6000_emit_allocate_stack (info->total_size, copy_reg);
if (frame_reg_rtx != sp_reg_rtx)
rs6000_emit_stack_tie ();
}