As a result of the previous changes, epilogue_insns pattern can only be
authorgretay <gretay@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 18 Jun 2012 18:06:54 +0000 (18:06 +0000)
committergretay <gretay@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 18 Jun 2012 18:06:54 +0000 (18:06 +0000)
generated in Thumb1. After removing other cases in define_insn for
epilogue_insns, the function arm_output_epilogue becomes dead code and can
be eliminated, along with all its helper functions.

gcc/

2012-06-18  Ian Bolton  <ian.bolton@arm.com>
            Sameera Deshpande  <sameera.deshpande@arm.com>
            Greta Yorsh  <greta.yorsh@arm.com>

        * config/arm/arm-protos.h (arm_output_epilogue): Remove.
        * config/arm/arm.c (print_multi_reg): Remove.
        (vfp_output_fldmd): Likewise.
        (arm_output_epilogue): Likewise.
        * config/arm/arm.md (epilogue_insns): Update condition and code.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@188745 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arm/arm-protos.h
gcc/config/arm/arm.c
gcc/config/arm/arm.md

index cc72e97..97659f8 100644 (file)
@@ -2,6 +2,16 @@
             Sameera Deshpande  <sameera.deshpande@arm.com>
             Greta Yorsh  <greta.yorsh@arm.com>
 
+        * config/arm/arm-protos.h (arm_output_epilogue): Remove.
+        * config/arm/arm.c (print_multi_reg): Remove.
+        (vfp_output_fldmd): Likewise.
+        (arm_output_epilogue): Likewise.
+        * config/arm/arm.md (epilogue_insns): Update condition and code.
+
+2012-06-18  Ian Bolton  <ian.bolton@arm.com>
+            Sameera Deshpande  <sameera.deshpande@arm.com>
+            Greta Yorsh  <greta.yorsh@arm.com>
+
         * config/arm/arm-protos.h (thumb2_expand_return): New declaration.
         * config/arm/arm.c (thumb2_expand_return): New function.
         * config/arm/arm.md (return): Update condition and code.
index 5a9940e..76e1abd 100644 (file)
@@ -28,7 +28,6 @@ extern int use_return_insn (int, rtx);
 extern enum reg_class arm_regno_class (int);
 extern void arm_load_pic_register (unsigned long);
 extern int arm_volatile_func (void);
-extern const char *arm_output_epilogue (rtx);
 extern void arm_expand_prologue (void);
 extern void arm_expand_epilogue (bool);
 extern void thumb2_expand_return (void);
index 3f5b500..627b436 100644 (file)
@@ -13659,86 +13659,6 @@ fp_const_from_val (REAL_VALUE_TYPE *r)
   return "0";
 }
 
-/* Output the operands of a LDM/STM instruction to STREAM.
-   MASK is the ARM register set mask of which only bits 0-15 are important.
-   REG is the base register, either the frame pointer or the stack pointer,
-   INSTR is the possibly suffixed load or store instruction.
-   RFE is nonzero if the instruction should also copy spsr to cpsr.  */
-
-static void
-print_multi_reg (FILE *stream, const char *instr, unsigned reg,
-                unsigned long mask, int rfe)
-{
-  unsigned i;
-  bool not_first = FALSE;
-
-  gcc_assert (!rfe || (mask & (1 << PC_REGNUM)));
-  fputc ('\t', stream);
-  asm_fprintf (stream, instr, reg);
-  fputc ('{', stream);
-
-  for (i = 0; i <= LAST_ARM_REGNUM; i++)
-    if (mask & (1 << i))
-      {
-       if (not_first)
-         fprintf (stream, ", ");
-
-       asm_fprintf (stream, "%r", i);
-       not_first = TRUE;
-      }
-
-  if (rfe)
-    fprintf (stream, "}^\n");
-  else
-    fprintf (stream, "}\n");
-}
-
-
-/* Output a FLDMD instruction to STREAM.
-   BASE if the register containing the address.
-   REG and COUNT specify the register range.
-   Extra registers may be added to avoid hardware bugs.
-
-   We output FLDMD even for ARMv5 VFP implementations.  Although
-   FLDMD is technically not supported until ARMv6, it is believed
-   that all VFP implementations support its use in this context.  */
-
-static void
-vfp_output_fldmd (FILE * stream, unsigned int base, int reg, int count)
-{
-  int i;
-
-  /* Workaround ARM10 VFPr1 bug.  */
-  if (count == 2 && !arm_arch6)
-    {
-      if (reg == 15)
-       reg--;
-      count++;
-    }
-
-  /* FLDMD may not load more than 16 doubleword registers at a time. Split the
-     load into multiple parts if we have to handle more than 16 registers.  */
-  if (count > 16)
-    {
-      vfp_output_fldmd (stream, base, reg, 16);
-      vfp_output_fldmd (stream, base, reg + 16, count - 16);
-      return;
-    }
-
-  fputc ('\t', stream);
-  asm_fprintf (stream, "fldmfdd\t%r!, {", base);
-
-  for (i = reg; i < reg + count; i++)
-    {
-      if (i > reg)
-       fputs (", ", stream);
-      asm_fprintf (stream, "d%d", i);
-    }
-  fputs ("}\n", stream);
-
-}
-
-
 /* OPERANDS[0] is the entire list of insns that constitute pop,
    OPERANDS[1] is the base register, RETURN_PC is true iff return insn
    is in the list, UPDATE is true iff the list contains explicit
@@ -15833,451 +15753,6 @@ arm_output_function_prologue (FILE *f, HOST_WIDE_INT frame_size)
 
 }
 
-const char *
-arm_output_epilogue (rtx sibling)
-{
-  int reg;
-  unsigned long saved_regs_mask;
-  unsigned long func_type;
-  /* Floats_offset is the offset from the "virtual" frame.  In an APCS
-     frame that is $fp + 4 for a non-variadic function.  */
-  int floats_offset = 0;
-  rtx operands[3];
-  FILE * f = asm_out_file;
-  unsigned int lrm_count = 0;
-  int really_return = (sibling == NULL);
-  int start_reg;
-  arm_stack_offsets *offsets;
-
-  /* If we have already generated the return instruction
-     then it is futile to generate anything else.  */
-  if (use_return_insn (FALSE, sibling) &&
-      (cfun->machine->return_used_this_function != 0))
-    return "";
-
-  func_type = arm_current_func_type ();
-
-  if (IS_NAKED (func_type))
-    /* Naked functions don't have epilogues.  */
-    return "";
-
-  if (IS_VOLATILE (func_type) && TARGET_ABORT_NORETURN)
-    {
-      rtx op;
-
-      /* A volatile function should never return.  Call abort.  */
-      op = gen_rtx_SYMBOL_REF (Pmode, NEED_PLT_RELOC ? "abort(PLT)" : "abort");
-      assemble_external_libcall (op);
-      output_asm_insn ("bl\t%a0", &op);
-
-      return "";
-    }
-
-  /* If we are throwing an exception, then we really must be doing a
-     return, so we can't tail-call.  */
-  gcc_assert (!crtl->calls_eh_return || really_return);
-
-  offsets = arm_get_frame_offsets ();
-  saved_regs_mask = offsets->saved_regs_mask;
-
-  if (TARGET_IWMMXT)
-    lrm_count = bit_count (saved_regs_mask);
-
-  floats_offset = offsets->saved_args;
-  /* Compute how far away the floats will be.  */
-  for (reg = 0; reg <= LAST_ARM_REGNUM; reg++)
-    if (saved_regs_mask & (1 << reg))
-      floats_offset += 4;
-
-  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;
-
-      if (TARGET_FPA_EMU2)
-       {
-         for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--)
-           if (df_regs_ever_live_p (reg) && !call_used_regs[reg])
-             {
-               floats_offset += 12;
-               asm_fprintf (f, "\tldfe\t%r, [%r, #-%d]\n",
-                            reg, FP_REGNUM, floats_offset - vfp_offset);
-             }
-       }
-      else
-       {
-         start_reg = LAST_FPA_REGNUM;
-
-         for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--)
-           {
-             if (df_regs_ever_live_p (reg) && !call_used_regs[reg])
-               {
-                 floats_offset += 12;
-
-                 /* We can't unstack more than four registers at once.  */
-                 if (start_reg - reg == 3)
-                   {
-                     asm_fprintf (f, "\tlfm\t%r, 4, [%r, #-%d]\n",
-                                  reg, FP_REGNUM, floats_offset - vfp_offset);
-                     start_reg = reg - 1;
-                   }
-               }
-             else
-               {
-                 if (reg != start_reg)
-                   asm_fprintf (f, "\tlfm\t%r, %d, [%r, #-%d]\n",
-                                reg + 1, start_reg - reg,
-                                FP_REGNUM, floats_offset - vfp_offset);
-                 start_reg = reg - 1;
-               }
-           }
-
-         /* Just in case the last register checked also needs unstacking.  */
-         if (reg != start_reg)
-           asm_fprintf (f, "\tlfm\t%r, %d, [%r, #-%d]\n",
-                        reg + 1, start_reg - reg,
-                        FP_REGNUM, floats_offset - vfp_offset);
-       }
-
-      if (TARGET_HARD_FLOAT && TARGET_VFP)
-       {
-         int saved_size;
-
-         /* The fldmd insns do not have base+offset addressing
-             modes, so we use IP to hold the address.  */
-         saved_size = arm_get_vfp_saved_size ();
-
-         if (saved_size > 0)
-           {
-             floats_offset += saved_size;
-             asm_fprintf (f, "\tsub\t%r, %r, #%d\n", IP_REGNUM,
-                          FP_REGNUM, floats_offset - vfp_offset);
-           }
-         start_reg = FIRST_VFP_REGNUM;
-         for (reg = FIRST_VFP_REGNUM; reg < LAST_VFP_REGNUM; reg += 2)
-           {
-             if ((!df_regs_ever_live_p (reg) || call_used_regs[reg])
-                 && (!df_regs_ever_live_p (reg + 1) || call_used_regs[reg + 1]))
-               {
-                 if (start_reg != reg)
-                   vfp_output_fldmd (f, IP_REGNUM,
-                                     (start_reg - FIRST_VFP_REGNUM) / 2,
-                                     (reg - start_reg) / 2);
-                 start_reg = reg + 2;
-               }
-           }
-         if (start_reg != reg)
-           vfp_output_fldmd (f, IP_REGNUM,
-                             (start_reg - FIRST_VFP_REGNUM) / 2,
-                             (reg - start_reg) / 2);
-       }
-
-      if (TARGET_IWMMXT)
-       {
-         /* The frame pointer is guaranteed to be non-double-word aligned.
-            This is because it is set to (old_stack_pointer - 4) and the
-            old_stack_pointer was double word aligned.  Thus the offset to
-            the iWMMXt registers to be loaded must also be non-double-word
-            sized, so that the resultant address *is* double-word aligned.
-            We can ignore floats_offset since that was already included in
-            the live_regs_mask.  */
-         lrm_count += (lrm_count % 2 ? 2 : 1);
-
-         for (reg = LAST_IWMMXT_REGNUM; reg >= FIRST_IWMMXT_REGNUM; reg--)
-           if (df_regs_ever_live_p (reg) && !call_used_regs[reg])
-             {
-               asm_fprintf (f, "\twldrd\t%r, [%r, #-%d]\n",
-                            reg, FP_REGNUM, lrm_count * 4);
-               lrm_count += 2;
-             }
-       }
-
-      /* saved_regs_mask should contain the IP, which at the time of stack
-        frame generation actually contains the old stack pointer.  So a
-        quick way to unwind the stack is just pop the IP register directly
-        into the stack pointer.  */
-      gcc_assert (saved_regs_mask & (1 << IP_REGNUM));
-      saved_regs_mask &= ~ (1 << IP_REGNUM);
-      saved_regs_mask |=   (1 << SP_REGNUM);
-
-      /* There are two registers left in saved_regs_mask - LR and PC.  We
-        only need to restore the LR register (the return address), but to
-        save time we can load it directly into the PC, unless we need a
-        special function exit sequence, or we are not really returning.  */
-      if (really_return
-         && ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL
-         && !crtl->calls_eh_return)
-       /* Delete the LR from the register mask, so that the LR on
-          the stack is loaded into the PC in the register mask.  */
-       saved_regs_mask &= ~ (1 << LR_REGNUM);
-      else
-       saved_regs_mask &= ~ (1 << PC_REGNUM);
-
-      /* We must use SP as the base register, because SP is one of the
-         registers being restored.  If an interrupt or page fault
-         happens in the ldm instruction, the SP might or might not
-         have been restored.  That would be bad, as then SP will no
-         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.  If the stack pointer already points at the right
-         place, then omit the subtraction.  */
-      if (offsets->outgoing_args != (1 + (int) bit_count (saved_regs_mask))
-         || cfun->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, 0);
-
-      if (IS_INTERRUPT (func_type))
-       /* Interrupt handlers will have pushed the
-          IP onto the stack, so restore it now.  */
-       print_multi_reg (f, "ldmfd\t%r!, ", SP_REGNUM, 1 << IP_REGNUM, 0);
-    }
-  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 distinguish 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.  */
-      unsigned HOST_WIDE_INT amount;
-      int rfe;
-      /* Restore stack pointer if necessary.  */
-      if (TARGET_ARM && frame_pointer_needed)
-       {
-         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
-       {
-         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
-           {
-             unsigned long count;
-             operands[0] = stack_pointer_rtx;
-             amount = offsets->outgoing_args - offsets->saved_regs;
-             /* pop call clobbered registers if it avoids a
-                separate stack adjustment.  */
-             count = offsets->saved_regs - offsets->saved_args;
-             if (optimize_size
-                 && count != 0
-                 && !crtl->calls_eh_return
-                 && bit_count(saved_regs_mask) * 4 == count
-                 && !IS_INTERRUPT (func_type)
-                 && !IS_STACKALIGN (func_type)
-                 && !crtl->tail_call_emit)
-               {
-                 unsigned long mask;
-                  /* Preserve return values, of any size.  */
-                 mask = (1 << ((arm_size_return_regs() + 3) / 4)) - 1;
-                 mask ^= 0xf;
-                 mask &= ~saved_regs_mask;
-                 reg = 0;
-                 while (bit_count (mask) * 4 > amount)
-                   {
-                     while ((mask & (1 << reg)) == 0)
-                       reg++;
-                     mask &= ~(1 << reg);
-                   }
-                 if (bit_count (mask) * 4 == amount) {
-                     amount = 0;
-                     saved_regs_mask |= mask;
-                 }
-               }
-           }
-
-         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 (TARGET_FPA_EMU2)
-       {
-         for (reg = FIRST_FPA_REGNUM; reg <= LAST_FPA_REGNUM; reg++)
-           if (df_regs_ever_live_p (reg) && !call_used_regs[reg])
-             asm_fprintf (f, "\tldfe\t%r, [%r], #12\n",
-                          reg, SP_REGNUM);
-       }
-      else
-       {
-         start_reg = FIRST_FPA_REGNUM;
-
-         for (reg = FIRST_FPA_REGNUM; reg <= LAST_FPA_REGNUM; reg++)
-           {
-             if (df_regs_ever_live_p (reg) && !call_used_regs[reg])
-               {
-                 if (reg - start_reg == 3)
-                   {
-                     asm_fprintf (f, "\tlfmfd\t%r, 4, [%r]!\n",
-                                  start_reg, SP_REGNUM);
-                     start_reg = reg + 1;
-                   }
-               }
-             else
-               {
-                 if (reg != start_reg)
-                   asm_fprintf (f, "\tlfmfd\t%r, %d, [%r]!\n",
-                                start_reg, reg - start_reg,
-                                SP_REGNUM);
-
-                 start_reg = reg + 1;
-               }
-           }
-
-         /* Just in case the last register checked also needs unstacking.  */
-         if (reg != start_reg)
-           asm_fprintf (f, "\tlfmfd\t%r, %d, [%r]!\n",
-                        start_reg, reg - start_reg, SP_REGNUM);
-       }
-
-      if (TARGET_HARD_FLOAT && TARGET_VFP)
-       {
-         int end_reg = LAST_VFP_REGNUM + 1;
-
-         /* Scan the registers in reverse order.  We need to match
-            any groupings made in the prologue and generate matching
-            pop operations.  */
-         for (reg = LAST_VFP_REGNUM - 1; reg >= FIRST_VFP_REGNUM; reg -= 2)
-           {
-             if ((!df_regs_ever_live_p (reg) || call_used_regs[reg])
-                 && (!df_regs_ever_live_p (reg + 1)
-                     || call_used_regs[reg + 1]))
-               {
-                 if (end_reg > reg + 2)
-                   vfp_output_fldmd (f, SP_REGNUM,
-                                     (reg + 2 - FIRST_VFP_REGNUM) / 2,
-                                     (end_reg - (reg + 2)) / 2);
-                 end_reg = reg;
-               }
-           }
-         if (end_reg > reg + 2)
-           vfp_output_fldmd (f, SP_REGNUM, 0,
-                             (end_reg - (reg + 2)) / 2);
-       }
-
-      if (TARGET_IWMMXT)
-       for (reg = FIRST_IWMMXT_REGNUM; reg <= LAST_IWMMXT_REGNUM; reg++)
-         if (df_regs_ever_live_p (reg) && !call_used_regs[reg])
-           asm_fprintf (f, "\twldrd\t%r, [%r], #8\n", reg, SP_REGNUM);
-
-      /* If we can, restore the LR into the PC.  */
-      if (ARM_FUNC_TYPE (func_type) != ARM_FT_INTERWORKED
-         && (TARGET_ARM || ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL)
-         && !IS_STACKALIGN (func_type)
-         && really_return
-         && crtl->args.pretend_args_size == 0
-         && saved_regs_mask & (1 << LR_REGNUM)
-         && !crtl->calls_eh_return)
-       {
-         saved_regs_mask &= ~ (1 << LR_REGNUM);
-         saved_regs_mask |=   (1 << PC_REGNUM);
-         rfe = IS_INTERRUPT (func_type);
-       }
-      else
-       rfe = 0;
-
-      /* Load the registers off the stack.  If we only have one register
-        to load use the LDR instruction - it is faster.  For Thumb-2
-        always use pop and the assembler will pick the best instruction.*/
-      if (TARGET_ARM && saved_regs_mask == (1 << LR_REGNUM)
-         && !IS_INTERRUPT(func_type))
-       {
-         asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
-       }
-      else if (saved_regs_mask)
-       {
-         if (saved_regs_mask & (1 << SP_REGNUM))
-           /* Note - write back to the stack register is not enabled
-              (i.e. "ldmfd sp!...").  We know that the stack pointer is
-              in the list of registers and if we add writeback the
-              instruction becomes UNPREDICTABLE.  */
-           print_multi_reg (f, "ldmfd\t%r, ", SP_REGNUM, saved_regs_mask,
-                            rfe);
-         else if (TARGET_ARM)
-           print_multi_reg (f, "ldmfd\t%r!, ", SP_REGNUM, saved_regs_mask,
-                            rfe);
-         else
-           print_multi_reg (f, "pop\t", SP_REGNUM, saved_regs_mask, 0);
-       }
-
-      if (crtl->args.pretend_args_size)
-       {
-         /* Unwind the pre-pushed regs.  */
-         operands[0] = operands[1] = stack_pointer_rtx;
-         operands[2] = GEN_INT (crtl->args.pretend_args_size);
-         output_add_immediate (operands);
-       }
-    }
-
-  /* We may have already restored PC directly from the stack.  */
-  if (!really_return || saved_regs_mask & (1 << PC_REGNUM))
-    return "";
-
-  /* Stack adjustment for exception handler.  */
-  if (crtl->calls_eh_return)
-    asm_fprintf (f, "\tadd\t%r, %r, %r\n", SP_REGNUM, SP_REGNUM,
-                ARM_EH_STACKADJ_REGNUM);
-
-  /* Generate the return instruction.  */
-  switch ((int) ARM_FUNC_TYPE (func_type))
-    {
-    case ARM_FT_ISR:
-    case ARM_FT_FIQ:
-      asm_fprintf (f, "\tsubs\t%r, %r, #4\n", PC_REGNUM, LR_REGNUM);
-      break;
-
-    case ARM_FT_EXCEPTION:
-      asm_fprintf (f, "\tmovs\t%r, %r\n", PC_REGNUM, LR_REGNUM);
-      break;
-
-    case ARM_FT_INTERWORKED:
-      asm_fprintf (f, "\tbx\t%r\n", LR_REGNUM);
-      break;
-
-    default:
-      if (IS_STACKALIGN (func_type))
-       {
-         /* See comment in arm_expand_prologue.  */
-         asm_fprintf (f, "\tmov\t%r, %r\n", SP_REGNUM, 0);
-       }
-      if (arm_arch5 || arm_arch4t)
-       asm_fprintf (f, "\tbx\t%r\n", LR_REGNUM);
-      else
-       asm_fprintf (f, "\tmov\t%r, %r\n", PC_REGNUM, LR_REGNUM);
-      break;
-    }
-
-  return "";
-}
-
 static void
 arm_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
                              HOST_WIDE_INT frame_size ATTRIBUTE_UNUSED)
index eb99488..f4ced7b 100644 (file)
 
 (define_insn "*epilogue_insns"
   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
-  "TARGET_EITHER"
+  "TARGET_THUMB1"
   "*
-  if (TARGET_32BIT)
-    return arm_output_epilogue (NULL);
-  else /* TARGET_THUMB1 */
     return thumb1_unexpanded_epilogue ();
   "
   ; Length is absolute worst case