re PR tree-optimization/47538 (GNU Scientific Library miscompiled by gcc 4.6)
authorJakub Jelinek <jakub@redhat.com>
Mon, 31 Jan 2011 16:52:22 +0000 (17:52 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 31 Jan 2011 16:52:22 +0000 (17:52 +0100)
PR tree-optimization/47538
* tree-ssa-ccp.c (bit_value_binop_1): For uns computation use
type instead of r1type, except for comparisons.  For right
shifts and comparisons punt if there are mismatches in
sizetype vs. non-sizetype types.

* gcc.c-torture/execute/pr47538.c: New test.

Co-Authored-By: Richard Guenther <rguenther@suse.de>
From-SVN: r169441

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr47538.c [new file with mode: 0644]
gcc/tree-ssa-ccp.c

index cdc402e..f575543 100644 (file)
@@ -1,3 +1,12 @@
+2011-01-31  Jakub Jelinek  <jakub@redhat.com>
+           Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/47538
+       * tree-ssa-ccp.c (bit_value_binop_1): For uns computation use
+       type instead of r1type, except for comparisons.  For right
+       shifts and comparisons punt if there are mismatches in
+       sizetype vs. non-sizetype types.
+
 2011-01-31  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * doc/sourcebuild.texi (Effective-Target Keywords): Document
index d12d612..9f8550e 100644 (file)
@@ -1,3 +1,8 @@
+2011-01-31  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/47538
+       * gcc.c-torture/execute/pr47538.c: New test.
+
 2011-01-31  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        PR target/45325
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr47538.c b/gcc/testsuite/gcc.c-torture/execute/pr47538.c
new file mode 100644 (file)
index 0000000..99dea08
--- /dev/null
@@ -0,0 +1,73 @@
+/* PR tree-optimization/47538 */
+
+struct S
+{
+  double a, b, *c;
+  unsigned long d;
+};
+
+__attribute__((noinline, noclone)) void
+foo (struct S *x, const struct S *y)
+{
+  const unsigned long n = y->d + 1;
+  const double m = 0.25 * (y->b - y->a);
+  x->a = y->a;
+  x->b = y->b;
+  if (n == 1)
+    {
+      x->c[0] = 0.;
+    }
+  else if (n == 2)
+    {
+      x->c[1] = m * y->c[0];
+      x->c[0] = 2.0 * x->c[1];
+    }
+  else
+    {
+      double o = 0.0, p = 1.0;
+      unsigned long i;
+
+      for (i = 1; i <= n - 2; i++)
+       {
+         x->c[i] = m * (y->c[i - 1] - y->c[i + 1]) / (double) i;
+         o += p * x->c[i];
+         p = -p;
+       }
+      x->c[n - 1] = m * y->c[n - 2] / (n - 1.0);
+      o += p * x->c[n - 1];
+      x->c[0] = 2.0 * o;
+    }
+}
+
+int
+main (void)
+{
+  struct S x, y;
+  double c[4] = { 10, 20, 30, 40 }, d[4], e[4] = { 118, 118, 118, 118 };
+
+  y.a = 10;
+  y.b = 6;
+  y.c = c;
+  x.c = d;
+  y.d = 3;
+  __builtin_memcpy (d, e, sizeof d);
+  foo (&x, &y);
+  if (d[0] != 0 || d[1] != 20 || d[2] != 10 || d[3] != -10)
+    __builtin_abort ();
+  y.d = 2;
+  __builtin_memcpy (d, e, sizeof d);
+  foo (&x, &y);
+  if (d[0] != 60 || d[1] != 20 || d[2] != -10 || d[3] != 118)
+    __builtin_abort ();
+  y.d = 1;
+  __builtin_memcpy (d, e, sizeof d);
+  foo (&x, &y);
+  if (d[0] != -20 || d[1] != -10 || d[2] != 118 || d[3] != 118)
+    __builtin_abort ();
+  y.d = 0;
+  __builtin_memcpy (d, e, sizeof d);
+  foo (&x, &y);
+  if (d[0] != 0 || d[1] != 118 || d[2] != 118 || d[3] != 118)
+    __builtin_abort ();
+  return 0;
+}
index 57fc56d..8b8d996 100644 (file)
@@ -1768,8 +1768,8 @@ bit_value_binop_1 (enum tree_code code, tree type,
                   tree r1type, double_int r1val, double_int r1mask,
                   tree r2type, double_int r2val, double_int r2mask)
 {
-  bool uns = (TREE_CODE (r1type) == INTEGER_TYPE
-             && TYPE_IS_SIZETYPE (r1type) ? 0 : TYPE_UNSIGNED (r1type));
+  bool uns = (TREE_CODE (type) == INTEGER_TYPE
+             && TYPE_IS_SIZETYPE (type) ? 0 : TYPE_UNSIGNED (type));
   /* Assume we'll get a constant result.  Use an initial varying value,
      we fall back to varying in the end if necessary.  */
   *mask = double_int_minus_one;
@@ -1836,6 +1836,13 @@ bit_value_binop_1 (enum tree_code code, tree type,
            }
          else if (shift < 0)
            {
+             /* ???  We can have sizetype related inconsistencies in
+                the IL.  */
+             if ((TREE_CODE (r1type) == INTEGER_TYPE
+                  && (TYPE_IS_SIZETYPE (r1type)
+                      ? 0 : TYPE_UNSIGNED (r1type))) != uns)
+               break;
+
              shift = -shift;
              *mask = double_int_rshift (r1mask, shift,
                                         TYPE_PRECISION (type), !uns);
@@ -1946,6 +1953,14 @@ bit_value_binop_1 (enum tree_code code, tree type,
        if (double_int_negative_p (r1mask) || double_int_negative_p (r2mask))
          break;
 
+       /* For comparisons the signedness is in the comparison operands.  */
+       uns = (TREE_CODE (r1type) == INTEGER_TYPE
+              && TYPE_IS_SIZETYPE (r1type) ? 0 : TYPE_UNSIGNED (r1type));
+       /* ???  We can have sizetype related inconsistencies in the IL.  */
+       if ((TREE_CODE (r2type) == INTEGER_TYPE
+            && TYPE_IS_SIZETYPE (r2type) ? 0 : TYPE_UNSIGNED (r2type)) != uns)
+         break;
+
        /* If we know the most significant bits we know the values
           value ranges by means of treating varying bits as zero
           or one.  Do a cross comparison of the max/min pairs.  */