This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH: PR target/38570] remove redundant push {lr} for -mthumb
- From: Carrot Wei <carrot at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 4 May 2009 11:03:11 +0800
- Subject: [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. */