mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-11 08:54:35 +08:00
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:
parent
2f6025a15b
commit
ec6237e440
@ -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>
|
||||
|
||||
|
@ -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 ();
|
||||
|
Loading…
Reference in New Issue
Block a user