re PR middle-end/47893 (4.6 miscompiles mesa on i686)
authorJakub Jelinek <jakub@gcc.gnu.org>
Mon, 28 Feb 2011 17:05:07 +0000 (18:05 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 28 Feb 2011 17:05:07 +0000 (18:05 +0100)
PR middle-end/47893
* rtl.h (ASLK_REDUCE_ALIGN, ASLK_RECORD_PAD): Define.
(assign_stack_local_1): Change last argument type to int.
* function.c (assign_stack_local_1): Replace reduce_alignment_ok
argument with kind.  If bit ASLK_RECORD_PAD is not set in it,
don't record padding space into frame_space_list nor
use those areas.
(assign_stack_local): Adjust caller.
(assign_stack_temp_for_type): Call assign_stack_local_1 instead
of assign_stack_local, pass 0 as last argument.
* caller-save.c (setup_save_areas): Adjust assign_stack_local_1
callers.

* gcc.dg/pr47893.c: New test.

From-SVN: r170568

gcc/ChangeLog
gcc/caller-save.c
gcc/function.c
gcc/rtl.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr47893.c [new file with mode: 0644]

index b01637c3d7b11f193522995ab1ebc7e3fa61991b..c4c7a13052c4473f5ea8d9476fdc2cdba487eb45 100644 (file)
@@ -1,3 +1,19 @@
+2011-02-28  Bernd Schmidt  <bernds@codesourcery.com>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/47893
+       * rtl.h (ASLK_REDUCE_ALIGN, ASLK_RECORD_PAD): Define.
+       (assign_stack_local_1): Change last argument type to int.
+       * function.c (assign_stack_local_1): Replace reduce_alignment_ok
+       argument with kind.  If bit ASLK_RECORD_PAD is not set in it,
+       don't record padding space into frame_space_list nor
+       use those areas.
+       (assign_stack_local): Adjust caller.
+       (assign_stack_temp_for_type): Call assign_stack_local_1 instead
+       of assign_stack_local, pass 0 as last argument.
+       * caller-save.c (setup_save_areas): Adjust assign_stack_local_1
+       callers.
+
 2011-02-28  Jakub Jelinek  <jakub@redhat.com>
 
        PR debug/47283
index 7f7e222b4302fd33d65ae80b0a057f8ed1397a39..160d2e9117d19f694c7a992fbe0535a017496698 100644 (file)
@@ -647,7 +647,8 @@ setup_save_areas (void)
                  saved_reg->slot
                    = assign_stack_local_1
                      (regno_save_mode[regno][1],
-                      GET_MODE_SIZE (regno_save_mode[regno][1]), 0, true);
+                      GET_MODE_SIZE (regno_save_mode[regno][1]), 0,
+                      ASLK_REDUCE_ALIGN);
                  if (dump_file != NULL)
                    fprintf (dump_file, "%d uses a new slot\n", regno);
                }
@@ -705,7 +706,7 @@ setup_save_areas (void)
            regno_save_mem[i][j]
              = assign_stack_local_1 (regno_save_mode[i][j],
                                      GET_MODE_SIZE (regno_save_mode[i][j]),
-                                     0, true);
+                                     0, ASLK_REDUCE_ALIGN);
 
            /* Setup single word save area just in case...  */
            for (k = 0; k < j; k++)
index 3f721fb1a2f2fe7ade1230391c9633c2e91155fc..8b80485860c1e8d5da6bc36db10e8c3f75b19c77 100644 (file)
@@ -1,7 +1,7 @@
 /* Expands front end tree to back end RTL for GCC.
    Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
    1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010  Free Software Foundation, Inc.
+   2010, 2011  Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -355,14 +355,17 @@ add_frame_space (HOST_WIDE_INT start, HOST_WIDE_INT end)
    -2 means use BITS_PER_UNIT,
    positive specifies alignment boundary in bits.
 
-   If REDUCE_ALIGNMENT_OK is true, it is OK to reduce alignment.
+   KIND has ASLK_REDUCE_ALIGN bit set if it is OK to reduce
+   alignment and ASLK_RECORD_PAD bit set if we should remember
+   extra space we allocated for alignment purposes.  When we are
+   called from assign_stack_temp_for_type, it is not set so we don't
+   track the same stack slot in two independent lists.
 
    We do not round to stack_boundary here.  */
 
 rtx
 assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size,
-                     int align,
-                     bool reduce_alignment_ok ATTRIBUTE_UNUSED)
+                     int align, int kind)
 {
   rtx x, addr;
   int bigend_correction = 0;
@@ -412,7 +415,7 @@ assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size,
                  /* It is OK to reduce the alignment as long as the
                     requested size is 0 or the estimated stack
                     alignment >= mode alignment.  */
-                 gcc_assert (reduce_alignment_ok
+                 gcc_assert ((kind & ASLK_REDUCE_ALIGN)
                              || size == 0
                              || (crtl->stack_alignment_estimated
                                  >= GET_MODE_ALIGNMENT (mode)));
@@ -430,21 +433,24 @@ assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size,
 
   if (mode != BLKmode || size != 0)
     {
-      struct frame_space **psp;
-
-      for (psp = &crtl->frame_space_list; *psp; psp = &(*psp)->next)
+      if (kind & ASLK_RECORD_PAD)
        {
-         struct frame_space *space = *psp;
-         if (!try_fit_stack_local (space->start, space->length, size,
-                                   alignment, &slot_offset))
-           continue;
-         *psp = space->next;
-         if (slot_offset > space->start)
-           add_frame_space (space->start, slot_offset);
-         if (slot_offset + size < space->start + space->length)
-           add_frame_space (slot_offset + size,
-                            space->start + space->length);
-         goto found_space;
+         struct frame_space **psp;
+
+         for (psp = &crtl->frame_space_list; *psp; psp = &(*psp)->next)
+           {
+             struct frame_space *space = *psp;
+             if (!try_fit_stack_local (space->start, space->length, size,
+                                       alignment, &slot_offset))
+               continue;
+             *psp = space->next;
+             if (slot_offset > space->start)
+               add_frame_space (space->start, slot_offset);
+             if (slot_offset + size < space->start + space->length)
+               add_frame_space (slot_offset + size,
+                                space->start + space->length);
+             goto found_space;
+           }
        }
     }
   else if (!STACK_ALIGNMENT_NEEDED)
@@ -460,20 +466,26 @@ assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size,
       frame_offset -= size;
       try_fit_stack_local (frame_offset, size, size, alignment, &slot_offset);
 
-      if (slot_offset > frame_offset)
-       add_frame_space (frame_offset, slot_offset);
-      if (slot_offset + size < old_frame_offset)
-       add_frame_space (slot_offset + size, old_frame_offset);
+      if (kind & ASLK_RECORD_PAD)
+       {
+         if (slot_offset > frame_offset)
+           add_frame_space (frame_offset, slot_offset);
+         if (slot_offset + size < old_frame_offset)
+           add_frame_space (slot_offset + size, old_frame_offset);
+       }
     }
   else
     {
       frame_offset += size;
       try_fit_stack_local (old_frame_offset, size, size, alignment, &slot_offset);
 
-      if (slot_offset > old_frame_offset)
-       add_frame_space (old_frame_offset, slot_offset);
-      if (slot_offset + size < frame_offset)
-       add_frame_space (slot_offset + size, frame_offset);
+      if (kind & ASLK_RECORD_PAD)
+       {
+         if (slot_offset > old_frame_offset)
+           add_frame_space (old_frame_offset, slot_offset);
+         if (slot_offset + size < frame_offset)
+           add_frame_space (slot_offset + size, frame_offset);
+       }
     }
 
  found_space:
@@ -513,7 +525,7 @@ assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size,
 rtx
 assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align)
 {
-  return assign_stack_local_1 (mode, size, align, false);
+  return assign_stack_local_1 (mode, size, align, ASLK_RECORD_PAD);
 }
 \f
 \f
@@ -868,11 +880,13 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
         and round it now.  We also make sure ALIGNMENT is at least
         BIGGEST_ALIGNMENT.  */
       gcc_assert (mode != BLKmode || align == BIGGEST_ALIGNMENT);
-      p->slot = assign_stack_local (mode,
-                                   (mode == BLKmode
-                                    ? CEIL_ROUND (size, (int) align / BITS_PER_UNIT)
-                                    : size),
-                                   align);
+      p->slot = assign_stack_local_1 (mode,
+                                     (mode == BLKmode
+                                      ? CEIL_ROUND (size,
+                                                    (int) align
+                                                    / BITS_PER_UNIT)
+                                      : size),
+                                     align, 0);
 
       p->align = align;
 
index e5c6e38302055b7fb4096ba2c5d3cba6d78b00bb..0552156d64808a830a22dce932cd230b7d9c0dfa 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1,6 +1,6 @@
 /* Register Transfer Language (RTL) definitions for GCC
    Copyright (C) 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -1685,7 +1685,9 @@ extern rtx simplify_subtraction (rtx);
 
 /* In function.c  */
 extern rtx assign_stack_local (enum machine_mode, HOST_WIDE_INT, int);
-extern rtx assign_stack_local_1 (enum machine_mode, HOST_WIDE_INT, int, bool);
+#define ASLK_REDUCE_ALIGN 1
+#define ASLK_RECORD_PAD 2
+extern rtx assign_stack_local_1 (enum machine_mode, HOST_WIDE_INT, int, int);
 extern rtx assign_stack_temp (enum machine_mode, HOST_WIDE_INT, int);
 extern rtx assign_stack_temp_for_type (enum machine_mode,
                                       HOST_WIDE_INT, int, tree);
index fe2cedddfc6c3d804f92f3f083d8f0718f2f2164..10c430a3c886c520eda4b5534c1af064dcf61fd5 100644 (file)
@@ -1,3 +1,8 @@
+2011-02-28  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/47893
+       * gcc.dg/pr47893.c: New test.
+
 2011-02-28  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * objc.dg/gnu-api-2-sel.m: Test that sel_getTypedSelector return
diff --git a/gcc/testsuite/gcc.dg/pr47893.c b/gcc/testsuite/gcc.dg/pr47893.c
new file mode 100644 (file)
index 0000000..317d95d
--- /dev/null
@@ -0,0 +1,187 @@
+/* PR middle-end/47893 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-options "-O2 -mtune=atom -fno-omit-frame-pointer -fno-strict-aliasing" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+
+extern void abort (void);
+
+struct S
+{
+  unsigned s1:4, s2:2, s3:2, s4:2, s5:2, s6:1, s7:1, s8:1, s9:1, s10:1;
+  int s11:16; unsigned s12:4; int s13:16; unsigned s14:2;
+  int s15:16; unsigned s16:4; int s17:16; unsigned s18:2;
+};
+
+struct T
+{
+  unsigned t[3];
+};
+
+struct U
+{
+  unsigned u1, u2;
+};
+
+struct V;
+
+struct W
+{
+  char w1[24]; struct V *w2; unsigned w3; char w4[28912];
+  unsigned int w5; char w6[60];
+};
+
+struct X
+{
+  unsigned int x[2];
+};
+
+struct V
+{
+  int v1;
+  struct X v2[3];
+  char v3[28];
+};
+
+struct Y
+{
+  void *y1;
+  char y2[3076];
+  struct T y3[32];
+  char y4[1052];
+};
+
+volatile struct S v1 = { .s15 = -1, .s16 = 15, .s17 = -1, .s18 = 3 };
+
+__attribute__ ((noinline, noclone))
+int
+fn1 (int x)
+{
+  int r;
+  __asm__ volatile ("" : "=r" (r) : "0" (1), "r" (x) : "memory");
+  return r;
+}
+
+volatile int cnt;
+
+__attribute__ ((noinline, noclone))
+#ifdef __i386__
+__attribute__ ((regparm (2)))
+#endif
+struct S
+fn2 (struct Y *x, const struct X *y)
+{
+  if (++cnt > 1)
+    abort ();
+  __asm__ volatile ("" : : "r" (x), "r" (y) : "memory");
+  return v1;
+}
+
+__attribute__ ((noinline, noclone))
+void fn3 (void *x, unsigned y, const struct S *z, unsigned w)
+{
+  __asm__ volatile ("" : : "r" (x), "r" (y), "r" (z), "r" (w) : "memory");
+}
+
+volatile struct U v2;
+
+__attribute__ ((noinline, noclone))
+struct U
+fn4 (void *x, unsigned y)
+{
+  __asm__ volatile ("" : : "r" (x), "r" (y) : "memory");
+  return v2;
+}
+
+__attribute__ ((noinline, noclone))
+struct S
+fn5 (void *x)
+{
+  __asm__ volatile ("" : : "r" (x) : "memory");
+  return v1;
+}
+
+volatile struct T v3;
+
+__attribute__ ((noinline, noclone))
+struct T fn6 (void *x)
+{
+  __asm__ volatile ("" : : "r" (x) : "memory");
+  return v3;
+}
+
+__attribute__ ((noinline, noclone))
+struct T fn7 (void *x, unsigned y, unsigned z)
+{
+  __asm__ volatile ("" : : "r" (x), "r" (y), "r" (z) : "memory");
+  return v3;
+}
+
+static void
+fn8 (struct Y *x, const struct V *y)
+{
+  void *a = x->y1;
+  struct S b[4];
+  unsigned i, c;
+  c = fn1 (y->v1);
+  for (i = 0; i < c; i++)
+    b[i] = fn2 (x, &y->v2[i]);
+  fn3 (a, y->v1, b, c);
+}
+
+static inline void
+fn9 (void *x, struct S y __attribute__((unused)))
+{
+  fn4 (x, 8);
+}
+
+static void
+fn10 (struct Y *x)
+{
+  void *a = x->y1;
+  struct T b __attribute__((unused)) = fn6 (a);
+  fn9 (a, fn5 (a));
+}
+
+__attribute__((noinline, noclone))
+int
+fn11 (unsigned int x, void *y, const struct W *z,
+      unsigned int w, const char *v, const char *u)
+{
+  struct Y a, *t;
+  unsigned i;
+  t = &a;
+  __builtin_memset (t, 0, sizeof *t);
+  t->y1 = y;
+  if (x == 0)
+    {
+      if (z->w3 & 1)
+       fn10 (t);
+      for (i = 0; i < w; i++)
+       {
+         if (v[i] == 0)
+           t->y3[i] = fn7 (y, 0, u[i]);
+         else
+           return 0;
+       }
+    }
+  else
+    for (i = 0; i < w; i++)
+      t->y3[i] = fn7 (y, v[i], u[i]);
+  for (i = 0; i < z->w5; i++)
+    fn8 (t, &z->w2[i]);
+  return 0;
+}
+
+volatile int i;
+const char *volatile p = "";
+
+int
+main ()
+{
+  struct V v = { .v1 = 0 };
+  struct W w = { .w5 = 1, .w2 = &v };
+  fn11 (i + 1, (void *) p, &w, i, (const char *) p, (const char *) p);
+  if (cnt != 1)
+    abort ();
+  return 0;
+}