]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR rtl-optimization/40924 (miscompiles with -O3 (seemingly related to attribute...
authorJakub Jelinek <jakub@redhat.com>
Wed, 5 Aug 2009 12:36:34 +0000 (14:36 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 5 Aug 2009 12:36:34 +0000 (14:36 +0200)
PR rtl-optimization/40924
* dse.c (canon_address): Before calling cselib_expand_value_rtx
make sure canon_rtx (mem_address) isn't simpler than
canon_rtx (expanded_mem_address).

* g++.dg/torture/pr40924.C: New test.

From-SVN: r150483

gcc/ChangeLog
gcc/dse.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr40924.C [new file with mode: 0644]

index 075b612954e4f9d9b683ea6955073e0447ede182..7fec75887b5ab11800df6f1b2c24eb980e6d6be7 100644 (file)
@@ -1,3 +1,10 @@
+2009-08-05  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/40924
+       * dse.c (canon_address): Before calling cselib_expand_value_rtx
+       make sure canon_rtx (mem_address) isn't simpler than
+       canon_rtx (expanded_mem_address).
+
 2009-08-05  Li Feng  <nemokingdom@gmail.com>
 
        * graphite-sese-to-poly.c (build_pbb_drs): Remove build alias set
index 0fc2aa9c1bf3e3341f7109e4ccd1597612155f6e..2338d3240ba93481c853d62ec7924353acb80fc1 100644 (file)
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -1070,6 +1070,8 @@ canon_address (rtx mem,
 {
   rtx mem_address = XEXP (mem, 0);
   rtx expanded_address, address;
+  int expanded;
+
   /* Make sure that cselib is has initialized all of the operands of
      the address before asking it to do the subst.  */
 
@@ -1114,72 +1116,88 @@ canon_address (rtx mem,
       fprintf (dump_file, "\n");
     }
 
-  /* Use cselib to replace all of the reg references with the full
-     expression.  This will take care of the case where we have 
+  /* First see if just canon_rtx (mem_address) is const or frame,
+     if not, try cselib_expand_value_rtx and call canon_rtx on that.  */
+  address = NULL_RTX;
+  for (expanded = 0; expanded < 2; expanded++)
+    {
+      if (expanded)
+       {
+         /* Use cselib to replace all of the reg references with the full
+            expression.  This will take care of the case where we have 
 
-     r_x = base + offset;
-     val = *r_x;
+            r_x = base + offset;
+            val = *r_x;
    
-     by making it into 
-
-     val = *(base + offset);  
-  */
-
-  expanded_address = cselib_expand_value_rtx (mem_address, scratch, 5);
+            by making it into 
 
-  /* If this fails, just go with the mem_address.  */
-  if (!expanded_address)
-    expanded_address = mem_address;
+            val = *(base + offset);  */
 
-  /* Split the address into canonical BASE + OFFSET terms.  */
-  address = canon_rtx (expanded_address);
+         expanded_address = cselib_expand_value_rtx (mem_address,
+                                                     scratch, 5);
 
-  *offset = 0;
+         /* If this fails, just go with the address from first
+            iteration.  */
+         if (!expanded_address)
+           break;
+       }
+      else
+       expanded_address = mem_address;
 
-  if (dump_file)
-    {
-      fprintf (dump_file, "\n   after cselib_expand address: ");
-      print_inline_rtx (dump_file, expanded_address, 0);
-      fprintf (dump_file, "\n");
+      /* Split the address into canonical BASE + OFFSET terms.  */
+      address = canon_rtx (expanded_address);
 
-      fprintf (dump_file, "\n   after canon_rtx address: ");
-      print_inline_rtx (dump_file, address, 0);
-      fprintf (dump_file, "\n");
-    }
+      *offset = 0;
 
-  if (GET_CODE (address) == CONST)
-    address = XEXP (address, 0);
+      if (dump_file)
+       {
+         if (expanded)
+           {
+             fprintf (dump_file, "\n   after cselib_expand address: ");
+             print_inline_rtx (dump_file, expanded_address, 0);
+             fprintf (dump_file, "\n");
+           }
 
-  if (GET_CODE (address) == PLUS && CONST_INT_P (XEXP (address, 1)))
-    {
-      *offset = INTVAL (XEXP (address, 1));
-      address = XEXP (address, 0);
-    }
+         fprintf (dump_file, "\n   after canon_rtx address: ");
+         print_inline_rtx (dump_file, address, 0);
+         fprintf (dump_file, "\n");
+       }
 
-  if (const_or_frame_p (address))
-    {
-      group_info_t group = get_group_info (address);
+      if (GET_CODE (address) == CONST)
+       address = XEXP (address, 0);
 
-      if (dump_file)
-       fprintf (dump_file, "  gid=%d offset=%d \n", group->id, (int)*offset);
-      *base = NULL;
-      *group_id = group->id;
-    }
-  else
-    {
-      *base = cselib_lookup (address, Pmode, true);
-      *group_id = -1;
+      if (GET_CODE (address) == PLUS
+         && CONST_INT_P (XEXP (address, 1)))
+       {
+         *offset = INTVAL (XEXP (address, 1));
+         address = XEXP (address, 0);
+       }
 
-      if (*base == NULL)
+      if (const_or_frame_p (address))
        {
+         group_info_t group = get_group_info (address);
+
          if (dump_file)
-           fprintf (dump_file, " no cselib val - should be a wild read.\n");
-         return false;
+           fprintf (dump_file, "  gid=%d offset=%d \n",
+                    group->id, (int)*offset);
+         *base = NULL;
+         *group_id = group->id;
+         return true;
        }
+    }
+
+  *base = cselib_lookup (address, Pmode, true);
+  *group_id = -1;
+
+  if (*base == NULL)
+    {
       if (dump_file)
-       fprintf (dump_file, "  varying cselib base=%d offset = %d\n", 
-                (*base)->value, (int)*offset);
+       fprintf (dump_file, " no cselib val - should be a wild read.\n");
+      return false;
     }
+  if (dump_file)
+    fprintf (dump_file, "  varying cselib base=%d offset = %d\n", 
+            (*base)->value, (int)*offset);
   return true;
 }
 
index 77238de44b5be8f9392b30ed727d163e3bb14b66..e34aa8d8b2e91c2408107d07ab3e3f0198cfe254 100644 (file)
@@ -1,3 +1,8 @@
+2009-08-05  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/40924
+       * g++.dg/torture/pr40924.C: New test.
+
 2009-08-05  Manuel López-Ibáñez  <manu@gcc.gnu.org>
 
        PR c++/36069
diff --git a/gcc/testsuite/g++.dg/torture/pr40924.C b/gcc/testsuite/g++.dg/torture/pr40924.C
new file mode 100644 (file)
index 0000000..9140da3
--- /dev/null
@@ -0,0 +1,111 @@
+// PR rtl-optimization/40924
+// { dg-do run }
+
+extern "C" void abort (void);
+
+#define MAY_ALIAS __attribute__((__may_alias__))
+
+typedef struct { float v[2]; } floata;
+typedef struct { int v[2]; } inta;
+
+typedef unsigned int uint MAY_ALIAS;
+typedef signed int sint MAY_ALIAS;
+typedef float flt MAY_ALIAS;
+
+static inline unsigned short
+less_than (inta a, inta b)
+{
+  unsigned short r = 0;
+  const uint *p1 = (const uint *) &a;
+  const uint *p2 = (const uint *) &b;
+  for (int i=0; i < 2; i++)
+    if (p1[i] < p2[i]) r |= (1 << i);
+  return r;
+}
+
+static inline inta
+multiply (inta b, inta c)
+{
+  inta r;
+  sint *p3 = (sint *) &c;
+  for (int i=0; i < 2; i++)
+    r.v[i] = (int) (b.v[i] * p3[i] & 0xFFFFFFFF);
+  return r;
+}
+
+static inline floata
+gather (inta indexes, const void *baseAddr)
+{
+  floata r;
+
+  sint *idx = (sint *) &indexes;
+  flt *src = (flt *) baseAddr;
+  for (int i=0; i < 2; i++)
+    r.v[i] = *(src + idx[i]);
+  return r;
+}
+
+static inline inta
+add (const inta &b, const inta &c)
+{
+  inta result;
+  sint *r = (sint *) &result;
+
+  for (int i=0; i < 2; i++)
+    r[i] = b.v[i] + c.v[i];
+  return result;
+}
+
+struct uintv
+{
+  inta data;
+  inline uintv () { data.v[0] = 0; data.v[1] = 1; }
+  inline uintv (unsigned int a)
+  {
+    for (int i=0; i < 2; i++)
+      *(uint *) &data.v[i] = a;
+  }
+  inline uintv (inta x) : data (x) {}
+  inline uintv operator* (const uintv &x) const
+  { return multiply (data, x.data); }
+  inline uintv operator+ (const uintv &x) const
+  { return uintv (add (data, x.data)); }
+  inline unsigned short operator< (const uintv &x) const
+  { return less_than (data, x.data); }
+};
+
+struct floatv
+{
+  floata data;
+  explicit inline floatv (const uintv &x)
+  {
+    uint *p2 = (uint *) &x.data;
+    for (int i=0; i < 2; i++)
+      data.v[i] = p2[i];
+  }
+  inline floatv (const float *array, const uintv &indexes)
+  {
+    const uintv &offsets = indexes * uintv (1);
+    data = gather (offsets.data, array);
+  }
+  unsigned short operator== (const floatv &x) const
+  {
+    unsigned short r = 0;
+    for (int i=0; i < 2; i++)
+      if (data.v[i] == x.data.v[i]) r |= (1 << i);
+    return r;
+  }
+};
+
+int
+main ()
+{
+  const float array[2] = { 2, 3 };
+  for (uintv i; (i < 2) == 3; i = i + 2)
+    {
+      const floatv ii (i + 2);
+      floatv a (array, i);
+      if ((a == ii) != 3)
+       abort ();
+    }
+}