From 0425d6f563d8b76eb4fcf2bf3ebb64cee85f6eca Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 31 Jan 2011 17:52:22 +0100 Subject: [PATCH] re PR tree-optimization/47538 (GNU Scientific Library miscompiled by gcc 4.6) 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 From-SVN: r169441 --- gcc/ChangeLog | 9 ++++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.c-torture/execute/pr47538.c | 73 +++++++++++++++++++++++++++ gcc/tree-ssa-ccp.c | 19 ++++++- 4 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr47538.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cdc402e..f575543 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2011-01-31 Jakub Jelinek + Richard Guenther + + 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 * doc/sourcebuild.texi (Effective-Target Keywords): Document diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d12d612..9f8550e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-01-31 Jakub Jelinek + + PR tree-optimization/47538 + * gcc.c-torture/execute/pr47538.c: New test. + 2011-01-31 Rainer Orth 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 index 0000000..99dea08 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr47538.c @@ -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; +} diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 57fc56d..8b8d996 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -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. */ -- 2.7.4