Commit 699a4925 by Richard Earnshaw Committed by Richard Earnshaw

arm.c (arm_output_epilogue): When using a frame pointer...

* arm.c (arm_output_epilogue): When using a frame pointer, don't emit
an extra stack adjustment insn if the stack pointer is already
pointing at the right place.
(use_return_insn): Allow a return insn to be used when we have a
frame pointer if the stack pointer is in the right place.
(output_return_instruction): Handle it.

From-SVN: r73003
parent 578e8170
2003-10-28 Richard Earnshaw <rearnsha@arm.com>
* arm.c (arm_output_epilogue): When using a frame pointer, don't emit
an extra stack adjustment insn if the stack pointer is already
pointing at the right place.
(use_return_insn): Allow a return insn to be used when we have a
frame pointer if the stack pointer is in the right place.
(output_return_instruction): Handle it.
2003-10-28 Andreas Jaeger <aj@suse.de> 2003-10-28 Andreas Jaeger <aj@suse.de>
* ggc-zone.c (check_cookies): Add missing variable. * ggc-zone.c (check_cookies): Add missing variable.
......
...@@ -1015,10 +1015,6 @@ use_return_insn (int iscond) ...@@ -1015,10 +1015,6 @@ use_return_insn (int iscond)
if (!reload_completed) if (!reload_completed)
return 0; return 0;
/* We need two instructions when there's a frame pointer. */
if (frame_pointer_needed)
return 0;
func_type = arm_current_func_type (); func_type = arm_current_func_type ();
/* Naked functions and volatile functions need special /* Naked functions and volatile functions need special
...@@ -1033,11 +1029,12 @@ use_return_insn (int iscond) ...@@ -1033,11 +1029,12 @@ use_return_insn (int iscond)
/* As do variadic functions. */ /* As do variadic functions. */
if (current_function_pretend_args_size if (current_function_pretend_args_size
|| cfun->machine->uses_anonymous_args || cfun->machine->uses_anonymous_args
/* Of if the function calls __builtin_eh_return () */ /* Or if the function calls __builtin_eh_return () */
|| ARM_FUNC_TYPE (func_type) == ARM_FT_EXCEPTION_HANDLER || ARM_FUNC_TYPE (func_type) == ARM_FT_EXCEPTION_HANDLER
/* Or if there is no frame pointer and there is a stack adjustment. */ /* Or if the function calls alloca */
|| ((arm_get_frame_size () + current_function_outgoing_args_size != 0) || current_function_calls_alloca
&& !frame_pointer_needed)) /* Or if there is a stack adjustment. */
|| (arm_get_frame_size () + current_function_outgoing_args_size != 0))
return 0; return 0;
saved_int_regs = arm_compute_save_reg_mask (); saved_int_regs = arm_compute_save_reg_mask ();
...@@ -8098,7 +8095,7 @@ arm_compute_save_reg_mask (void) ...@@ -8098,7 +8095,7 @@ arm_compute_save_reg_mask (void)
return save_reg_mask; return save_reg_mask;
} }
/* Generate a function exit sequence. If REALLY_RETURN is true, then do /* Generate a function exit sequence. If REALLY_RETURN is false, then do
everything bar the final return instruction. */ everything bar the final return instruction. */
const char * const char *
output_return_instruction (rtx operand, int really_return, int reverse) output_return_instruction (rtx operand, int really_return, int reverse)
...@@ -8116,8 +8113,9 @@ output_return_instruction (rtx operand, int really_return, int reverse) ...@@ -8116,8 +8113,9 @@ output_return_instruction (rtx operand, int really_return, int reverse)
if (IS_VOLATILE (func_type) && TARGET_ABORT_NORETURN) if (IS_VOLATILE (func_type) && TARGET_ABORT_NORETURN)
{ {
/* If this function was declared non-returning, and we have found a tail /* If this function was declared non-returning, and we have
call, then we have to trust that the called function won't return. */ found a tail call, then we have to trust that the called
function won't return. */
if (really_return) if (really_return)
{ {
rtx ops[2]; rtx ops[2];
...@@ -8189,10 +8187,11 @@ output_return_instruction (rtx operand, int really_return, int reverse) ...@@ -8189,10 +8187,11 @@ output_return_instruction (rtx operand, int really_return, int reverse)
char *p; char *p;
int first = 1; int first = 1;
/* Generate the load multiple instruction to restore the registers. */ /* Generate the load multiple instruction to restore the
if (frame_pointer_needed) registers. Note we can get here, even if
sprintf (instr, "ldm%sea\t%%|fp, {", conditional); frame_pointer_needed is true, but only if sp already
else if (live_regs_mask & (1 << SP_REGNUM)) points to the base of the saved core registers. */
if (live_regs_mask & (1 << SP_REGNUM))
sprintf (instr, "ldm%sfd\t%%|sp, {", conditional); sprintf (instr, "ldm%sfd\t%%|sp, {", conditional);
else else
sprintf (instr, "ldm%sfd\t%%|sp!, {", conditional); sprintf (instr, "ldm%sfd\t%%|sp!, {", conditional);
...@@ -8552,9 +8551,13 @@ arm_output_epilogue (int really_return) ...@@ -8552,9 +8551,13 @@ arm_output_epilogue (int really_return)
longer indicate the safe area of stack, and we can get stack longer indicate the safe area of stack, and we can get stack
corruption. Using SP as the base register means that it will corruption. Using SP as the base register means that it will
be reset correctly to the original value, should an interrupt be reset correctly to the original value, should an interrupt
occur. */ occur. If the stack pointer already points at the right
asm_fprintf (f, "\tsub\t%r,%r,#%d\n", SP_REGNUM, FP_REGNUM, place, then omit the subtraction. */
4 * bit_count (saved_regs_mask)); if (((frame_size + current_function_outgoing_args_size + floats_offset)
!= 4 * (1 + (int) bit_count (saved_regs_mask)))
|| current_function_calls_alloca)
asm_fprintf (f, "\tsub\t%r, %r, #%d\n", SP_REGNUM, FP_REGNUM,
4 * bit_count (saved_regs_mask));
print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask); print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
if (IS_INTERRUPT (func_type)) if (IS_INTERRUPT (func_type))
......
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