arm.c (arm_output_epilogue): When using a frame pointer...
authorRichard Earnshaw <rearnsha@arm.com>
Tue, 28 Oct 2003 09:47:45 +0000 (09:47 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Tue, 28 Oct 2003 09:47:45 +0000 (09:47 +0000)
* 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

gcc/ChangeLog
gcc/config/arm/arm.c

index 197630452768603ac9a9942da3b2f04d9d761cbd..a9f43073fc4661b8136d5086078be3d7e811e45e 100644 (file)
@@ -1,3 +1,12 @@
+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>
 
        * ggc-zone.c (check_cookies): Add missing variable.
index f127b1d2904e5a9f4a883522fecddc3f31d02f32..cab1d96fd4f5e13b2580f7345cec8c4d219f0fee 100644 (file)
@@ -1015,10 +1015,6 @@ use_return_insn (int iscond)
   if (!reload_completed)
     return 0;
 
-  /* We need two instructions when there's a frame pointer. */
-  if (frame_pointer_needed)
-    return 0;
-  
   func_type = arm_current_func_type ();
 
   /* Naked functions and volatile functions need special
@@ -1033,11 +1029,12 @@ use_return_insn (int iscond)
   /* As do variadic functions.  */
   if (current_function_pretend_args_size
       || 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
-      /* Or if there is no frame pointer and there is a stack adjustment.  */
-      || ((arm_get_frame_size () + current_function_outgoing_args_size != 0)
-         && !frame_pointer_needed))
+      /* Or if the function calls alloca */
+      || current_function_calls_alloca
+      /* Or if there is a stack adjustment.  */
+      || (arm_get_frame_size () + current_function_outgoing_args_size != 0))
     return 0;
 
   saved_int_regs = arm_compute_save_reg_mask ();
@@ -8098,7 +8095,7 @@ arm_compute_save_reg_mask (void)
   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.  */
 const char *
 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 this function was declared non-returning, and we have found a tail 
-        call, then we have to trust that the called function won't return.  */
+      /* If this function was declared non-returning, and we have
+        found a tail call, then we have to trust that the called
+        function won't return.  */
       if (really_return)
        {
          rtx ops[2];
@@ -8189,10 +8187,11 @@ output_return_instruction (rtx operand, int really_return, int reverse)
          char *p;
          int first = 1;
 
-         /* Generate the load multiple instruction to restore the registers.  */
-         if (frame_pointer_needed)
-           sprintf (instr, "ldm%sea\t%%|fp, {", conditional);
-         else if (live_regs_mask & (1 << SP_REGNUM))
+         /* Generate the load multiple instruction to restore the
+            registers.  Note we can get here, even if
+            frame_pointer_needed is true, but only if sp already
+            points to the base of the saved core registers.  */
+         if (live_regs_mask & (1 << SP_REGNUM))
            sprintf (instr, "ldm%sfd\t%%|sp, {", conditional);
          else
            sprintf (instr, "ldm%sfd\t%%|sp!, {", conditional);
@@ -8552,9 +8551,13 @@ arm_output_epilogue (int really_return)
          longer indicate the safe area of stack, and we can get stack
          corruption.  Using SP as the base register means that it will
          be reset correctly to the original value, should an interrupt
-         occur.  */
-      asm_fprintf (f, "\tsub\t%r,%r,#%d\n", SP_REGNUM, FP_REGNUM,
-                  4 * bit_count (saved_regs_mask));
+         occur.  If the stack pointer already points at the right
+         place, then omit the subtraction.  */
+      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);
 
       if (IS_INTERRUPT (func_type))