diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-24 14:54:01 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-24 14:54:01 +0000 |
commit | 596070e8e2337a520117c088138354b7a1ff9c76 (patch) | |
tree | 2abaef0504af1d06e7a5df00c463d575dd11e6a7 | |
parent | d6b92d9f1fea6d58c9b8f87b4014bb6bc6b11c6d (diff) | |
download | gcc-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/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr69760.c | 50 | ||||
-rw-r--r-- | gcc/tree-scalar-evolution.c | 70 |
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: |