This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH: PR target/38570] remove redundant push {lr} for -mthumb


This patch is to fix the bug PR target/38570. In thumb mode if the lr register
is not clobbered, we can skip the push {lr} prologue. But if there is a jump
in the function, the reload pass can't decide if it is a far jump (lr is used
in a far jump), so it always treats the jump as far jump and prevent this
optimization.

The fix first compute the maximum possible function length, if the length is
not large enough far jump is not necessary, and we can do this optimization
safely.

ChangeLog:
2009-05-04  Carrot Wei  <carrot@google.com>

        PR target/38570
        * config/arm/arm.c: There is no far jump if a function is not large
        enough.

Test:
This patch was applied to trunk GCC and tested on the arm emulator with newlib.
No new failures.

thanks
Carrot


Index: arm.c
===================================================================
--- arm.c       (revision 146995)
+++ arm.c       (working copy)
@@ -398,6 +398,8 @@ static bool arm_allocate_stack_slots_for
 #define TARGET_ASM_OUTPUT_DWARF_DTPREL arm_output_dwarf_dtprel
 #endif

+#define SHORTEST_FAR_JUMP_LENGTH 2040
+
 struct gcc_target targetm = TARGET_INITIALIZER;

 /* Obstack for minipool constant handling.  */
@@ -17212,6 +17214,17 @@ thumb_shiftable_const (unsigned HOST_WID
   return 0;
 }

+/* Computes the maximum possible function length. */
+static int
+estimate_function_length (void)
+{
+  rtx insn;
+  int length = 0;
+  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+    length += get_attr_length(insn);
+  return length;
+}
+
 /* Returns nonzero if the current function contains,
    or might contain a far jump.  */
 static int
@@ -17230,6 +17243,16 @@ thumb_far_jump_used_p (void)
   if (cfun->machine->far_jump_used)
     return 1;

+  /* In reload pass we haven't got the exact jump instruction length,
+     but we can get a reasonable estimation based on the maximum
+     possible function length. */
+  if (!reload_completed)
+    {
+      int function_length = estimate_function_length();
+      if (function_length < SHORTEST_FAR_JUMP_LENGTH)
+        return 0;
+    }
+
   /* If this function is not being called from the prologue/epilogue
      generation code then it must be being called from the
      INITIAL_ELIMINATION_OFFSET macro.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]