]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
arm.c (output_return_instruction): Only restore IP into SP if frame_pointer_needed.
authorIan Lance Taylor <ian@wasabisystems.com>
Tue, 27 Jan 2004 14:48:02 +0000 (14:48 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 27 Jan 2004 14:48:02 +0000 (14:48 +0000)
* config/arm/arm.c (output_return_instruction): Only restore IP
into SP if frame_pointer_needed.

* gcc.dg/arm-mmx-1.c: New test.

From-SVN: r76710

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/arm-mmx-1.c [new file with mode: 0644]

index 58a742c0c28c11c99164e1924fd8b8351022dbd2..119c20ab6496dc4fe3cbf49c58d10cabae315cc9 100644 (file)
@@ -1,3 +1,8 @@
+2004-01-27  Ian Lance Taylor  <ian@wasabisystems.com>
+
+       * config/arm/arm.c (output_return_instruction): Only restore IP
+       into SP if frame_pointer_needed.
+
 2004-01-27  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        * config/sparc/sparc.c (function_arg_pass_by_reference): Return 1
index 768678d1b51b6982af251c403a5e4c2b96a2b58a..b70e68b1e1822f57bc69f5471710a909f55913e0 100644 (file)
@@ -8260,15 +8260,25 @@ output_return_instruction (rtx operand, int really_return, int reverse)
        return_reg = reg_names[LR_REGNUM];
 
       if ((live_regs_mask & (1 << IP_REGNUM)) == (1 << IP_REGNUM))
-       /* There are two possible reasons for the IP register being saved.
-          Either a stack frame was created, in which case IP contains the
-          old stack pointer, or an ISR routine corrupted it.  If this in an
-          ISR routine then just restore IP, otherwise restore IP into SP.  */
-       if (! IS_INTERRUPT (func_type))
-         {
-           live_regs_mask &= ~ (1 << IP_REGNUM);
-           live_regs_mask |=   (1 << SP_REGNUM);
-         }
+       {
+         /* There are three possible reasons for the IP register
+            being saved.  1) a stack frame was created, in which case
+            IP contains the old stack pointer, or 2) an ISR routine
+            corrupted it, or 3) it was saved to align the stack on
+            iWMMXt.  In case 1, restore IP into SP, otherwise just
+            restore IP.  */
+         if (frame_pointer_needed)
+           {
+             live_regs_mask &= ~ (1 << IP_REGNUM);
+             live_regs_mask |=   (1 << SP_REGNUM);
+           }
+         else
+           {
+             if (! IS_INTERRUPT (func_type)
+                 && ! TARGET_REALLY_IWMMXT)
+               abort ();
+           }
+       }
 
       /* On some ARM architectures it is faster to use LDR rather than
         LDM to load a single register.  On other architectures, the
index 330d38a3c8cfac4ff015136264f2682acb4890ae..a89844292bde5531214ea9a33e3e5320e1365cd4 100644 (file)
@@ -1,3 +1,7 @@
+2004-01-27  Ian Lance Taylor  <ian@wasabisystems.com>
+
+       * gcc.dg/arm-mmx-1.c: New test.
+
 2004-01-27  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        * gcc.dg/20040127-1.c: New test.
diff --git a/gcc/testsuite/gcc.dg/arm-mmx-1.c b/gcc/testsuite/gcc.dg/arm-mmx-1.c
new file mode 100644 (file)
index 0000000..4f95d8d
--- /dev/null
@@ -0,0 +1,26 @@
+/* Verify that if IP is saved to ensure stack alignment, we don't load
+   it into sp.  */
+/* { dg-do compile { target arm*-*-* strongarm*-*-* xscale*-*-*} } */
+/* { dg-options "-O -mno-apcs-frame -mcpu=iwmmxt" } */
+/* { dg-final { scan-assembler "ldmfd\[        ]sp!.*ip,\[ ]*pc" } } */
+
+/* This function uses all the call-saved registers, namely r4, r5, r6,
+   r7, r8, r9, sl, fp.  Since we also save pc, that leaves an odd
+   number of registers, and the compiler will push ip to align the
+   stack.  Make sure that we restore ip into ip, not into sp as is
+   done when using a frame pointer.  The -mno-apcs-frame option
+   permits the frame pointer to be used as an ordinary register.  */
+int
+foo(int *a, int *b, int *c, int *d, int *tot)
+{
+  int i, j, k, l, m, n, o;
+
+  *tot = 0;
+  for (i = *a; i < *b; i += *c)
+    for (j = *a; j < *b; j += *d)
+      for (k = *a; k < *c; k += *d)
+       for (l = *b; k < *c; k += *d)
+         for (m = *d; k < *c; k += *b)
+           *tot += i + j + k + l + m;
+  return *tot;
+}