arm.c (use_return_insn): Check TARGET_APCS_FRAME.
authorPaul Brook <pbrook@gcc.gnu.org>
Tue, 11 Mar 2008 17:43:22 +0000 (17:43 +0000)
committerPaul Brook <pbrook@gcc.gnu.org>
Tue, 11 Mar 2008 17:43:22 +0000 (17:43 +0000)
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

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

index 7b7f9d7f735c8cfb71065ced4187de049ed4c644..c3fb00aabe64e5809b90500fab81e23a2af3c199 100644 (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>
 
index bddb0e2771ad3e3ebb9674fc82071c2be5642706..531dd1fe3eb0d1dc971df20bdd3037fe6f0baa02 100644 (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,32 +11442,60 @@ 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)
-       {
-         /* 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;
-       }
-      else
+      if (TARGET_ARM && frame_pointer_needed)
        {
          operands[0] = stack_pointer_rtx;
-         amount = offsets->outgoing_args - offsets->saved_regs;
+         operands[1] = hard_frame_pointer_rtx;
+         
+         operands[2] = GEN_INT (offsets->frame - offsets->saved_regs);
+         output_add_immediate (operands);
        }
-
-      if (amount)
+      else
        {
-         operands[1] = operands[0];
-         operands[2] = GEN_INT (amount);
-         output_add_immediate (operands);
+         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 (frame_pointer_needed)
-       asm_fprintf (f, "\tmov\t%r, %r\n",
-                    SP_REGNUM, HARD_FRAME_POINTER_REGNUM);
 
       if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
        {
@@ -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 ();