summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2010-04-27 09:34:08 +0000
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2010-04-27 09:34:08 +0000
commitf2df60270980b4c0cb98a64b4bfbc36eb3358c79 (patch)
tree590b6fcd87fdd36bc035f67a23648f0756834d8a
parent86689d78bf39258773f86b15937a1d294e1b65ee (diff)
downloadgcc-f2df60270980b4c0cb98a64b4bfbc36eb3358c79.tar.gz
PR target/40657
* config/arm/arm.c (thumb1_extra_regs_pushed): New function. (thumb1_expand_prologue, thumb1_output_function_prologue): Call it here to determine which regs to push and how much stack to reserve. PR target/40657 * gcc.target/arm/thumb-stackframe.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158771 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/arm/arm.c52
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/arm/thumb-stackframe.c13
4 files changed, 76 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4f0e2591bb9..95444f19038 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2010-04-27 Bernd Schmidt <bernds@codesourcery.com>
+
+ PR target/40657
+ * config/arm/arm.c (thumb1_extra_regs_pushed): New function.
+ (thumb1_expand_prologue, thumb1_output_function_prologue): Call it
+ here to determine which regs to push and how much stack to reserve.
+
2010-04-27 Jie Zhang <jie@codesourcery.com>
* doc/gimple.texi (gimple_statement_with_ops): Remove
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 8d21b8782f0..72d54736f05 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -19402,6 +19402,51 @@ thumb_compute_initial_elimination_offset (unsigned int from, unsigned int to)
}
}
+/* Given the stack offsets and register mask in OFFSETS, decide
+ how many additional registers to push instead of subtracting
+ a constant from SP. */
+static int
+thumb1_extra_regs_pushed (arm_stack_offsets *offsets)
+{
+ HOST_WIDE_INT amount = offsets->outgoing_args - offsets->saved_regs;
+ unsigned long live_regs_mask = offsets->saved_regs_mask;
+ /* Extract a mask of the ones we can give to the Thumb's push instruction. */
+ unsigned long l_mask = live_regs_mask & 0x40ff;
+ /* Then count how many other high registers will need to be pushed. */
+ unsigned long high_regs_pushed = bit_count (live_regs_mask & 0x0f00);
+ int n_free;
+
+ /* If the stack frame size is 512 exactly, we can save one load
+ instruction, which should make this a win even when optimizing
+ for speed. */
+ if (!optimize_size && amount != 512)
+ return 0;
+
+ /* Can't do this if there are high registers to push, or if we
+ are not going to do a push at all. */
+ if (high_regs_pushed != 0 || l_mask == 0)
+ return 0;
+
+ /* Don't do this if thumb1_expand_prologue wants to emit instructions
+ between the push and the stack frame allocation. */
+ if ((flag_pic && arm_pic_register != INVALID_REGNUM)
+ || (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0))
+ return 0;
+
+ for (n_free = 0; n_free < 8 && !(live_regs_mask & 1); live_regs_mask >>= 1)
+ n_free++;
+
+ if (n_free == 0)
+ return 0;
+ gcc_assert (amount / 4 * 4 == amount);
+
+ if (amount >= 512 && (amount - n_free * 4) < 512)
+ return (amount - 508) / 4;
+ if (amount <= n_free * 4)
+ return amount / 4;
+ return 0;
+}
+
/* Generate the rest of a function's prologue. */
void
thumb1_expand_prologue (void)
@@ -19438,6 +19483,7 @@ thumb1_expand_prologue (void)
stack_pointer_rtx);
amount = offsets->outgoing_args - offsets->saved_regs;
+ amount -= 4 * thumb1_extra_regs_pushed (offsets);
if (amount)
{
if (amount < 512)
@@ -19742,7 +19788,11 @@ thumb1_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
register. */
else if ((l_mask & 0xff) != 0
|| (high_regs_pushed == 0 && l_mask))
- thumb_pushpop (f, l_mask, 1, &cfa_offset, l_mask);
+ {
+ unsigned long mask = l_mask;
+ mask |= (1 << thumb1_extra_regs_pushed (offsets)) - 1;
+ thumb_pushpop (f, mask, 1, &cfa_offset, mask);
+ }
if (high_regs_pushed)
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 21640d68b03..e3b7527bec8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-04-27 Bernd Schmidt <bernds@codesourcery.com>
+
+ PR target/40657
+ * gcc.target/arm/thumb-stackframe.c: New test.
+
2010-04-27 Shujing Zhao <pearly.zhao@oracle.com>
* gcc.dg/pr32207.c: Fix typo in expected warning messages.
diff --git a/gcc/testsuite/gcc.target/arm/thumb-stackframe.c b/gcc/testsuite/gcc.target/arm/thumb-stackframe.c
new file mode 100644
index 00000000000..f6c78804e91
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb-stackframe.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-mthumb -Os" } */
+/* { dg-require-effective-target arm_thumb1_ok } */
+
+extern void bar(int*);
+int foo()
+{
+ int x;
+ bar(&x);
+ return x;
+}
+
+/* { dg-final { scan-assembler-not "sub\[\\t \]*sp,\[\\t \]*sp," } } */