This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] fix wrong code for push of long double
- From: Mikulas Patocka <mikulas at artax dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 4 Aug 2009 15:18:37 +0200 (CEST)
- Subject: [PATCH] fix wrong code for push of long double
Hi
This patch fixes incorrect code being generated for push long double.
Tested on i686. I compiled and ran succesfully mpfr testsuite where the
bug originally showed up.
The patch should be applied to 4.4 branch and likely to trunk as well (I
checked it only on 4.4.1 release).
2009-08-04 Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>
PR target/40906
* config/i386/i386.c (ix86_split_long_move): Fix push of long
double
* testsuite/gcc.dg/pr40906-m128bit-long-double.c: New test
* testsuite/gcc.dg/pr40906.c: New test
diff -urpN gcc-4.4.1/gcc/config/i386/i386.c gcc-4.4.1-fix-push/gcc/config/i386/i386.c
--- gcc-4.4.1/gcc/config/i386/i386.c 2009-07-21 09:22:51.000000000 +0200
+++ gcc-4.4.1-fix-push/gcc/config/i386/i386.c 2009-07-29 03:10:26.000000000 +0200
@@ -16307,10 +16307,18 @@ ix86_split_long_move (rtx operands[])
/* When emitting push, take care for source operands on the stack. */
if (push && MEM_P (operands[1])
&& reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
- for (i = 0; i < nparts - 1; i++)
- part[1][i] = change_address (part[1][i],
- GET_MODE (part[1][i]),
- XEXP (part[1][i + 1], 0));
+ {
+ if (!TARGET_64BIT && TARGET_128BIT_LONG_DOUBLE && mode == XFmode)
+ {
+ /* Compensate for the stack decrement by 4 */
+ for (i = 0; i < nparts; i++)
+ part[1][i] = change_address (part[1][i], GET_MODE (part[1][i]), plus_constant(XEXP (part[1][i], 0), 4));
+ }
+ for (i = nparts - 2; i >= 0; i--)
+ part[1][i] = change_address (part[1][i],
+ GET_MODE (part[1][i]),
+ XEXP (part[1][i + 1], 0));
+ }
/* We need to do copy in the right order in case an address register
of the source overlaps the destination. */
diff -urpN gcc-4.4.1/gcc/testsuite/gcc.dg/pr40906-m128bit-long-double.c gcc-4.4.1-fix-push/gcc/testsuite/gcc.dg/pr40906-m128bit-long-double.c
--- gcc-4.4.1/gcc/testsuite/gcc.dg/pr40906-m128bit-long-double.c 1970-01-01 01:00:00.000000000 +0100
+++ gcc-4.4.1-fix-push/gcc/testsuite/gcc.dg/pr40906-m128bit-long-double.c 2009-08-04 14:19:09.000000000 +0200
@@ -0,0 +1,24 @@
+/* PR target/40906 */
+/* Test for push of long double */
+
+/* { dg-do run { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+/* { dg-options "-O2 -fomit-frame-pointer -fno-inline -mpush-args -mno-accumulate-outgoing-args -m128bit-long-double" } */
+
+extern void abort (void);
+
+void f(long double a)
+{
+ if (a != 1.0) abort();
+}
+
+int g(long double b)
+{
+ f(b);
+ return 0;
+}
+
+int main(void)
+{
+ g(1.0);
+ return 0;
+}
diff -urpN gcc-4.4.1/gcc/testsuite/gcc.dg/pr40906.c gcc-4.4.1-fix-push/gcc/testsuite/gcc.dg/pr40906.c
--- gcc-4.4.1/gcc/testsuite/gcc.dg/pr40906.c 1970-01-01 01:00:00.000000000 +0100
+++ gcc-4.4.1-fix-push/gcc/testsuite/gcc.dg/pr40906.c 2009-08-04 15:06:42.000000000 +0200
@@ -0,0 +1,25 @@
+/* PR target/40906 */
+/* Test for push of long double */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fomit-frame-pointer -fno-inline" } */
+/* { dg-options "-O2 -fomit-frame-pointer -fno-inline -mpush-args -mno-accumulate-outgoing-args" { target { i?86-*-* x86_64-*-* } } } */
+
+extern void abort (void);
+
+void f(long double a)
+{
+ if (a != 1.0) abort();
+}
+
+int g(long double b)
+{
+ f(b);
+ return 0;
+}
+
+int main(void)
+{
+ g(1.0);
+ return 0;
+}