summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr47538.c73
-rw-r--r--gcc/tree-ssa-ccp.c19
4 files changed, 104 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index cdc402e6e47..f575543585c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d12d6125529..9f8550e03b5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..99dea084310
--- /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 57fc56d8ba7..8b8d996f508 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. */