This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] fix PR39429 arm wrong-code error for 4.4 and 4.3
- From: Mikael Pettersson <mikpe at it dot uu dot se>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 20 Jul 2009 12:00:22 +0200 (MEST)
- Subject: [PATCH] fix PR39429 arm wrong-code error for 4.4 and 4.3
This patch fixes PR target/39429, an ARM wrong-code error.
In some cases the back-end will try to load two adjacent memory
operands for an arithmetic operation using an LDM instruction.
There is a check to avoid doing this when the offset from the base
register is too large for LDM, but it mistakenly used the PLUS
opcode as offset, causing large offsets to not be rejected. If a
large offset does occur and registers are allocated in a particular
way, the pattern in arm.md will emit incorrect code.
The test case was fixed "accidentally" for 4.5 in revision 146451,
when Ian Lance Taylor fixed a number of enum conversions which are
invalid in C++. That uncovered the real source of the bug, namely
swapped parameters in two const_ok_for_op calls. This patch backports
that fix to 4.4 and 4.3.
Bootstrapped and regtested on armv5tel-unknown-linux-gnueabi.
Ok for 4.4 and 4.3?
(I don't have write access.)
2009-07-20 Mikael Pettersson <mikpe@it.uu.se>
gcc/
Backport from mainline:
2009-04-20 Ian Lance Taylor <ian@gcc.gnu.org>
Fix enum conversions which are invalid in C++.
PR target/39429
* config/arm/arm.c (adjacent_mem_locations): Fix swapped
parameters in const_ok_for_op calls.
gcc/testsuite/
PR target/39429
* gcc.target/arm/pr39429.c: New test case.
diff -rupN gcc-4.4.1-RC-20090715/gcc/config/arm/arm.c gcc-4.4.1-RC-20090715.pr39429/gcc/config/arm/arm.c
--- gcc-4.4.1-RC-20090715/gcc/config/arm/arm.c 2009-06-02 09:18:16.000000000 +0200
+++ gcc-4.4.1-RC-20090715.pr39429/gcc/config/arm/arm.c 2009-07-18 20:14:45.000000000 +0200
@@ -7401,7 +7401,7 @@ adjacent_mem_locations (rtx a, rtx b)
/* Don't accept any offset that will require multiple
instructions to handle, since this would cause the
arith_adjacentmem pattern to output an overlong sequence. */
- if (!const_ok_for_op (PLUS, val0) || !const_ok_for_op (PLUS, val1))
+ if (!const_ok_for_op (val0, PLUS) || !const_ok_for_op (val1, PLUS))
return 0;
/* Don't allow an eliminable register: register elimination can make
diff -rupN gcc-4.4.1-RC-20090715/gcc/testsuite/gcc.target/arm/pr39429.c gcc-4.4.1-RC-20090715.pr39429/gcc/testsuite/gcc.target/arm/pr39429.c
--- gcc-4.4.1-RC-20090715/gcc/testsuite/gcc.target/arm/pr39429.c 1970-01-01 01:00:00.000000000 +0100
+++ gcc-4.4.1-RC-20090715.pr39429/gcc/testsuite/gcc.target/arm/pr39429.c 2009-07-14 01:21:46.000000000 +0200
@@ -0,0 +1,28 @@
+/* PR target/39429 */
+/* { dg-do run } */
+/* { dg-options "-O2 -mtune=arm740t" } */
+
+struct obj {
+ unsigned int _filler[270];
+ unsigned int mapsize;
+ unsigned int size;
+};
+
+int __attribute__((noinline)) useOffScreen(struct obj *obj)
+{
+ unsigned int size = obj->size;
+ unsigned int mapsize = obj->mapsize;
+
+ return (mapsize - size) < 16*1024 ? 0 : 1;
+}
+
+int main(void)
+{
+ struct obj obj;
+
+ obj.mapsize = 0;
+ obj.size = 0;
+ if (useOffScreen(&obj) != 0)
+ __builtin_abort();
+ return 0;
+}