arm.c (use_return_insn): Check TARGET_APCS_FRAME.

2008-03-11  Paul Brook  <paul@codesourcery.com>
	Vladimir Prus  <vladimir@codesourcery.com>

	* config/arm/arm.c (use_return_insn): Check TARGET_APCS_FRAME.
	(arm_compute_save_reg0_reg12_mask): Always
	check if register 11 must be saved.  Always safe hard frame pointer
	when frame_pointer_needeed.
	(arm_compute_save_reg_mask): Save IP and PC
	only with apcs frames.
	(arm_output_epilogue): Adjust Thumb2 codepath to
	be also invoked and work for ARM non-apcs frames.
	(arm_expand_prologue): Don't bother saving IP
	for non-apcs frame, since it's not clobbered by
	prologue code.  Implement non-apcs frame
	layout.

From-SVN: r133117
This commit is contained in:
Paul Brook 2008-03-11 17:43:22 +00:00
parent 2f6025a15b
commit ec6237e440
2 changed files with 86 additions and 41 deletions

View File

@ -1,3 +1,19 @@
2008-03-11 Paul Brook <paul@codesourcery.com>
Vladimir Prus <vladimir@codesourcery.com>
* config/arm/arm.c (use_return_insn): Check TARGET_APCS_FRAME.
(arm_compute_save_reg0_reg12_mask): Always
check if register 11 must be saved. Always safe hard frame pointer
when frame_pointer_needeed.
(arm_compute_save_reg_mask): Save IP and PC
only with apcs frames.
(arm_output_epilogue): Adjust Thumb2 codepath to
be also invoked and work for ARM non-apcs frames.
(arm_expand_prologue): Don't bother saving IP
for non-apcs frame, since it's not clobbered by
prologue code. Implement non-apcs frame
layout.
2008-03-11 Paolo Bonzini <bonzini@gnu.org>
PR rtl-optimization/35281
@ -6,9 +22,9 @@
2008-03-11 Paolo Bonzini <bonzini@gnu.org>
* langhooks-def.h (LANG_HOOKS_CLEAR_BINDING_STACK): Delete.
* langhooks.h (struct lang_hooks): Delete clear_binding_stack member.
* toplev.c (compile_file): Don't call it.
* langhooks-def.h (LANG_HOOKS_CLEAR_BINDING_STACK): Delete.
* langhooks.h (struct lang_hooks): Delete clear_binding_stack member.
* toplev.c (compile_file): Don't call it.
2008-03-11 Uros Bizjak <ubizjak@gmail.com>

View File

@ -1662,7 +1662,8 @@ use_return_insn (int iscond, rtx sibling)
|| current_function_calls_alloca
/* Or if there is a stack adjustment. However, if the stack pointer
is saved on the stack, we can use a pre-incrementing stack load. */
|| !(stack_adjust == 0 || (frame_pointer_needed && stack_adjust == 4)))
|| !(stack_adjust == 0 || (TARGET_APCS_FRAME && frame_pointer_needed
&& stack_adjust == 4)))
return 0;
saved_int_regs = arm_compute_save_reg_mask ();
@ -10706,25 +10707,14 @@ arm_compute_save_reg0_reg12_mask (void)
}
else
{
/* In arm mode we handle r11 (FP) as a special case. */
unsigned last_reg = TARGET_ARM ? 10 : 11;
/* In the normal case we only need to save those registers
which are call saved and which are used by this function. */
for (reg = 0; reg <= last_reg; reg++)
for (reg = 0; reg <= 11; reg++)
if (df_regs_ever_live_p (reg) && ! call_used_regs[reg])
save_reg_mask |= (1 << reg);
/* Handle the frame pointer as a special case. */
if (! TARGET_APCS_FRAME
&& ! frame_pointer_needed
&& df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM)
&& ! call_used_regs[HARD_FRAME_POINTER_REGNUM])
save_reg_mask |= 1 << HARD_FRAME_POINTER_REGNUM;
else if (! TARGET_APCS_FRAME
&& ! frame_pointer_needed
&& df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM)
&& ! call_used_regs[HARD_FRAME_POINTER_REGNUM])
if (frame_pointer_needed)
save_reg_mask |= 1 << HARD_FRAME_POINTER_REGNUM;
/* If we aren't loading the PIC register,
@ -10775,7 +10765,7 @@ arm_compute_save_reg_mask (void)
/* If we are creating a stack frame, then we must save the frame pointer,
IP (which will hold the old stack pointer), LR and the PC. */
if (frame_pointer_needed && TARGET_ARM)
if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
save_reg_mask |=
(1 << ARM_HARD_FRAME_POINTER_REGNUM)
| (1 << IP_REGNUM)
@ -11306,7 +11296,7 @@ arm_output_epilogue (rtx sibling)
if (saved_regs_mask & (1 << reg))
floats_offset += 4;
if (frame_pointer_needed && TARGET_ARM)
if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
{
/* This variable is for the Virtual Frame Pointer, not VFP regs. */
int vfp_offset = offsets->frame;
@ -11452,33 +11442,61 @@ arm_output_epilogue (rtx sibling)
}
else
{
/* This branch is executed for ARM mode (non-apcs frames) and
Thumb-2 mode. Frame layout is essentially the same for those
cases, except that in ARM mode frame pointer points to the
first saved register, while in Thumb-2 mode the frame pointer points
to the last saved register.
It is possible to make frame pointer point to last saved
register in both cases, and remove some conditionals below.
That means that fp setup in prologue would be just "mov fp, sp"
and sp restore in epilogue would be just "mov sp, fp", whereas
now we have to use add/sub in those cases. However, the value
of that would be marginal, as both mov and add/sub are 32-bit
in ARM mode, and it would require extra conditionals
in arm_expand_prologue to distingish ARM-apcs-frame case
(where frame pointer is required to point at first register)
and ARM-non-apcs-frame. Therefore, such change is postponed
until real need arise. */
HOST_WIDE_INT amount;
int rfe;
/* Restore stack pointer if necessary. */
if (frame_pointer_needed)
if (TARGET_ARM && frame_pointer_needed)
{
/* For Thumb-2 restore sp from the frame pointer.
Operand restrictions mean we have to increment FP, then copy
to SP. */
amount = offsets->locals_base - offsets->saved_regs;
operands[0] = hard_frame_pointer_rtx;
operands[0] = stack_pointer_rtx;
operands[1] = hard_frame_pointer_rtx;
operands[2] = GEN_INT (offsets->frame - offsets->saved_regs);
output_add_immediate (operands);
}
else
{
operands[0] = stack_pointer_rtx;
amount = offsets->outgoing_args - offsets->saved_regs;
if (frame_pointer_needed)
{
/* For Thumb-2 restore sp from the frame pointer.
Operand restrictions mean we have to incrememnt FP, then copy
to SP. */
amount = offsets->locals_base - offsets->saved_regs;
operands[0] = hard_frame_pointer_rtx;
}
else
{
operands[0] = stack_pointer_rtx;
amount = offsets->outgoing_args - offsets->saved_regs;
}
if (amount)
{
operands[1] = operands[0];
operands[2] = GEN_INT (amount);
output_add_immediate (operands);
}
if (frame_pointer_needed)
asm_fprintf (f, "\tmov\t%r, %r\n",
SP_REGNUM, HARD_FRAME_POINTER_REGNUM);
}
if (amount)
{
operands[1] = operands[0];
operands[2] = GEN_INT (amount);
output_add_immediate (operands);
}
if (frame_pointer_needed)
asm_fprintf (f, "\tmov\t%r, %r\n",
SP_REGNUM, HARD_FRAME_POINTER_REGNUM);
if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
{
for (reg = FIRST_FPA_REGNUM; reg <= LAST_FPA_REGNUM; reg++)
@ -12320,7 +12338,10 @@ arm_expand_prologue (void)
emit_insn (gen_movsi (stack_pointer_rtx, r1));
}
if (frame_pointer_needed && TARGET_ARM)
/* For APCS frames, if IP register is clobbered
when creating frame, save that register in a special
way. */
if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
{
if (IS_INTERRUPT (func_type))
{
@ -12419,13 +12440,13 @@ arm_expand_prologue (void)
}
/* If this is an interrupt service routine, and the link register
is going to be pushed, and we are not creating a stack frame,
(which would involve an extra push of IP and a pop in the epilogue)
is going to be pushed, and we're not generating extra
push of IP (needed when frame is needed and frame layout if apcs),
subtracting four from LR now will mean that the function return
can be done with a single instruction. */
if ((func_type == ARM_FT_ISR || func_type == ARM_FT_FIQ)
&& (live_regs_mask & (1 << LR_REGNUM)) != 0
&& ! frame_pointer_needed
&& !(frame_pointer_needed && TARGET_APCS_FRAME)
&& TARGET_ARM)
{
rtx lr = gen_rtx_REG (SImode, LR_REGNUM);
@ -12446,6 +12467,7 @@ arm_expand_prologue (void)
if (frame_pointer_needed && TARGET_ARM)
{
/* Create the new frame pointer. */
if (TARGET_APCS_FRAME)
{
insn = GEN_INT (-(4 + args_to_push + fp_offset));
insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, ip_rtx, insn));
@ -12467,6 +12489,13 @@ arm_expand_prologue (void)
emit_insn (gen_prologue_use (ip_rtx));
}
}
else
{
insn = GEN_INT (saved_regs - 4);
insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
stack_pointer_rtx, insn));
RTX_FRAME_RELATED_P (insn) = 1;
}
}
offsets = arm_get_frame_offsets ();