This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix another problem with RTX_UNCHANGING_P
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Tue, 2 Dec 2003 16:45:57 +0100
- Subject: [PATCH] Fix another problem with RTX_UNCHANGING_P
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
The following testcase is miscompiled on both gcc-3_3-branch,
gcc-3_3-rhl-branch and TRUNK (for trunk with the obvious s/cpu/tune/
change). The problem is that GCC initializes the constructor with:
(insn 12 10 13 0 (parallel [
(set (reg/f:SI 60)
(plus:SI (reg/f:SI %eframe)
(const_int -32 [0xffffffe0])))
(clobber (reg:CC %eflags))
]) 138 {*addsi_1} (nil)
(nil))
(insn 13 12 14 0 (set (reg:SI %edirflag)
(const_int 0 [0x0])) 440 {cld} (nil)
(nil))
...
(insn 17 15 18 0 (parallel [
(set (reg:SI 63)
(const_int 0 [0x0]))
(set (reg/f:SI 60)
(plus:SI (ashift:SI (reg:SI 62)
(const_int 2 [0x2]))
(reg/f:SI 60)))
(set (mem:BLK (reg/f:SI 60) [0 A8])
(const_int 0 [0x0]))
(use (reg:SI 61))
(use (reg:SI 62))
(use (reg:SI %edirflag))
]) 449 {rep_stossi} (nil)
(nil))
(insn 18 17 29 0 (set (mem/s/u:SI (plus:SI (reg/f:SI %eframe)
(const_int -24 [0xffffffe8])) [6 y+8 S4 A64])
(reg/v/f:SI 59 [ x ])) 36 {*movsi_1} (nil)
(nil))
(note /u in the last insn). This violates RTX_UNCHANGING_P, since
the memory at eframe-24 is written more than once and sched2 happily
moves insn 18 before insn 17.
Ok to commit (TRUNK, gcc-3_3-branch)?
2003-12-02 Jakub Jelinek <jakub@redhat.com>
* expr.c (store_constructor): Only set RTX_UNCHANGING_P for
read-only field if cleared is 0.
* gcc.dg/20031202-1.c: New test.
--- gcc/expr.c.jj 2003-12-02 17:51:57.000000000 +0100
+++ gcc/expr.c 2003-12-02 18:09:59.000000000 +0100
@@ -4936,7 +4936,10 @@ store_constructor (exp, target, cleared,
highest_pow2_factor (offset));
}
- if (TREE_READONLY (field))
+ /* If the constructor has been cleared, setting RTX_UNCHANGING_P
+ on the MEM might lead to scheduling the clearing after the
+ store. */
+ if (TREE_READONLY (field) && !cleared)
{
if (GET_CODE (to_rtx) == MEM)
to_rtx = copy_rtx (to_rtx);
--- gcc/testsuite/gcc.dg/20031202-1.c.jj 2003-12-02 18:35:45.000000000 +0100
+++ gcc/testsuite/gcc.dg/20031202-1.c 2003-12-02 18:32:08.000000000 +0100
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-options "-O2 -mcpu=i686" { target i?86-*-* } } */
+
+extern void abort (void);
+extern void exit (int);
+
+struct A { char p[6]; } __attribute__((packed));
+struct B {
+ struct A a;
+ void * const b;
+ struct A const * const c;
+ struct A const *d;
+};
+
+char v;
+
+int __attribute__((noinline))
+foo (struct B *b)
+{
+ int i;
+ for (i = 0; i < 6; ++i)
+ if (b->a.p[i])
+ abort ();
+ if (b->b != &v || b->c || b->d)
+ abort ();
+ return 12;
+}
+
+int __attribute__((noinline))
+bar (void *x)
+{
+ __asm __volatile ("" : "=r" (x) : "0" (x));
+ struct B y = { .b = x, .c = (void *) 0 };
+ return foo (&y) + 1;
+}
+
+int
+main (void)
+{
+ if (bar (&v) != 13)
+ abort ();
+ exit (0);
+}
Jakub