summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2016-02-24 14:54:01 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2016-02-24 14:54:01 +0000
commit596070e8e2337a520117c088138354b7a1ff9c76 (patch)
tree2abaef0504af1d06e7a5df00c463d575dd11e6a7
parentd6b92d9f1fea6d58c9b8f87b4014bb6bc6b11c6d (diff)
downloadgcc-596070e8e2337a520117c088138354b7a1ff9c76.tar.gz
2016-02-24 Richard Biener <rguenther@suse.de>
Jakub Jelinek <jakub@redhat.com> PR middle-end/69760 * tree-scalar-evolution.c (interpret_rhs_expr): Re-write conditionally executed ops to well-defined overflow behavior. * gcc.dg/torture/pr69760.c: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233669 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr69760.c50
-rw-r--r--gcc/tree-scalar-evolution.c70
4 files changed, 120 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 53376ae27bb..0c2c960612c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2016-02-24 Richard Biener <rguenther@suse.de>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/69760
+ * tree-scalar-evolution.c (interpret_rhs_expr): Re-write
+ conditionally executed ops to well-defined overflow behavior.
+
2016-02-24 Jakub Jelinek <jakub@redhat.com>
PR middle-end/69915
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d956d00569f..2e4158839c9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2016-02-24 Richard Biener <rguenther@suse.de>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/69760
+ * gcc.dg/torture/pr69760.c: New testcase.
+
2016-02-24 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* gcc.dg/debug/dwarf2/prod-options.c: Use different DW_AT_producer
diff --git a/gcc/testsuite/gcc.dg/torture/pr69760.c b/gcc/testsuite/gcc.dg/torture/pr69760.c
new file mode 100644
index 00000000000..8f24608d232
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr69760.c
@@ -0,0 +1,50 @@
+/* PR tree-optimization/69760 */
+/* { dg-do run { target { { *-*-linux* *-*-gnu* } && mmap } } } */
+/* { dg-options "-O2" } */
+
+#include <unistd.h>
+#include <sys/mman.h>
+
+__attribute__((noinline, noclone)) void
+test_func (double *a, int L, int m, int n, int N)
+{
+ int i, k;
+ for (i = 0; i < N; i++)
+ {
+ k = i - m;
+ if (k >= 0 && k < n)
+ a[L * k] = 0.0;
+ }
+}
+
+int
+main ()
+{
+ char *p;
+ int L, m, n, N;
+ long l;
+ L = 10000000;
+ n = 4;
+ N = 100 * n;
+ long pgsz = sysconf(_SC_PAGESIZE);
+ if (pgsz < sizeof (double) || pgsz > L * sizeof (double))
+ return 0;
+ p = mmap ((void *) 0, L * n * sizeof (double), PROT_NONE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (p == MAP_FAILED)
+ return 0;
+ if (mprotect (p, pgsz, PROT_READ | PROT_WRITE))
+ return 0;
+ l = (L * sizeof (double)) / pgsz * pgsz;
+ if (mprotect (p + l, pgsz, PROT_READ | PROT_WRITE))
+ return 0;
+ l = (2 * L * sizeof (double)) / pgsz * pgsz;
+ if (mprotect (p + l, pgsz, PROT_READ | PROT_WRITE))
+ return 0;
+ l = (3 * L * sizeof (double)) / pgsz * pgsz;
+ if (mprotect (p + l, pgsz, PROT_READ | PROT_WRITE))
+ return 0;
+ for (m = 0; m < N; m += n)
+ test_func ((double *) p, L, m, n, N);
+ return 0;
+}
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index c36a0398db6..fdd5da0589a 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -1703,7 +1703,7 @@ static tree
interpret_rhs_expr (struct loop *loop, gimple *at_stmt,
tree type, tree rhs1, enum tree_code code, tree rhs2)
{
- tree res, chrec1, chrec2;
+ tree res, chrec1, chrec2, ctype;
gimple *def;
if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS)
@@ -1798,30 +1798,63 @@ interpret_rhs_expr (struct loop *loop, gimple *at_stmt,
case PLUS_EXPR:
chrec1 = analyze_scalar_evolution (loop, rhs1);
chrec2 = analyze_scalar_evolution (loop, rhs2);
- chrec1 = chrec_convert (type, chrec1, at_stmt);
- chrec2 = chrec_convert (type, chrec2, at_stmt);
+ ctype = type;
+ /* When the stmt is conditionally executed re-write the CHREC
+ into a form that has well-defined behavior on overflow. */
+ if (at_stmt
+ && INTEGRAL_TYPE_P (type)
+ && ! TYPE_OVERFLOW_WRAPS (type)
+ && ! dominated_by_p (CDI_DOMINATORS, loop->latch,
+ gimple_bb (at_stmt)))
+ ctype = unsigned_type_for (type);
+ chrec1 = chrec_convert (ctype, chrec1, at_stmt);
+ chrec2 = chrec_convert (ctype, chrec2, at_stmt);
chrec1 = instantiate_parameters (loop, chrec1);
chrec2 = instantiate_parameters (loop, chrec2);
- res = chrec_fold_plus (type, chrec1, chrec2);
+ res = chrec_fold_plus (ctype, chrec1, chrec2);
+ if (type != ctype)
+ res = chrec_convert (type, res, at_stmt);
break;
case MINUS_EXPR:
chrec1 = analyze_scalar_evolution (loop, rhs1);
chrec2 = analyze_scalar_evolution (loop, rhs2);
- chrec1 = chrec_convert (type, chrec1, at_stmt);
- chrec2 = chrec_convert (type, chrec2, at_stmt);
+ ctype = type;
+ /* When the stmt is conditionally executed re-write the CHREC
+ into a form that has well-defined behavior on overflow. */
+ if (at_stmt
+ && INTEGRAL_TYPE_P (type)
+ && ! TYPE_OVERFLOW_WRAPS (type)
+ && ! dominated_by_p (CDI_DOMINATORS,
+ loop->latch, gimple_bb (at_stmt)))
+ ctype = unsigned_type_for (type);
+ chrec1 = chrec_convert (ctype, chrec1, at_stmt);
+ chrec2 = chrec_convert (ctype, chrec2, at_stmt);
chrec1 = instantiate_parameters (loop, chrec1);
chrec2 = instantiate_parameters (loop, chrec2);
- res = chrec_fold_minus (type, chrec1, chrec2);
+ res = chrec_fold_minus (ctype, chrec1, chrec2);
+ if (type != ctype)
+ res = chrec_convert (type, res, at_stmt);
break;
case NEGATE_EXPR:
chrec1 = analyze_scalar_evolution (loop, rhs1);
- chrec1 = chrec_convert (type, chrec1, at_stmt);
+ ctype = type;
+ /* When the stmt is conditionally executed re-write the CHREC
+ into a form that has well-defined behavior on overflow. */
+ if (at_stmt
+ && INTEGRAL_TYPE_P (type)
+ && ! TYPE_OVERFLOW_WRAPS (type)
+ && ! dominated_by_p (CDI_DOMINATORS,
+ loop->latch, gimple_bb (at_stmt)))
+ ctype = unsigned_type_for (type);
+ chrec1 = chrec_convert (ctype, chrec1, at_stmt);
/* TYPE may be integer, real or complex, so use fold_convert. */
chrec1 = instantiate_parameters (loop, chrec1);
- res = chrec_fold_multiply (type, chrec1,
- fold_convert (type, integer_minus_one_node));
+ res = chrec_fold_multiply (ctype, chrec1,
+ fold_convert (ctype, integer_minus_one_node));
+ if (type != ctype)
+ res = chrec_convert (type, res, at_stmt);
break;
case BIT_NOT_EXPR:
@@ -1837,11 +1870,22 @@ interpret_rhs_expr (struct loop *loop, gimple *at_stmt,
case MULT_EXPR:
chrec1 = analyze_scalar_evolution (loop, rhs1);
chrec2 = analyze_scalar_evolution (loop, rhs2);
- chrec1 = chrec_convert (type, chrec1, at_stmt);
- chrec2 = chrec_convert (type, chrec2, at_stmt);
+ ctype = type;
+ /* When the stmt is conditionally executed re-write the CHREC
+ into a form that has well-defined behavior on overflow. */
+ if (at_stmt
+ && INTEGRAL_TYPE_P (type)
+ && ! TYPE_OVERFLOW_WRAPS (type)
+ && ! dominated_by_p (CDI_DOMINATORS,
+ loop->latch, gimple_bb (at_stmt)))
+ ctype = unsigned_type_for (type);
+ chrec1 = chrec_convert (ctype, chrec1, at_stmt);
+ chrec2 = chrec_convert (ctype, chrec2, at_stmt);
chrec1 = instantiate_parameters (loop, chrec1);
chrec2 = instantiate_parameters (loop, chrec2);
- res = chrec_fold_multiply (type, chrec1, chrec2);
+ res = chrec_fold_multiply (ctype, chrec1, chrec2);
+ if (type != ctype)
+ res = chrec_convert (type, res, at_stmt);
break;
case LSHIFT_EXPR: