diff options
author | Richard Biener <rguenther@suse.de> | 2016-02-24 14:54:01 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2016-02-24 14:54:01 +0000 |
commit | f802a42401e16c7b918cee539e3c38f4d6f7a336 (patch) | |
tree | 2abaef0504af1d06e7a5df00c463d575dd11e6a7 /gcc | |
parent | 525f795f86f448a6cedb6b35317ae28de64d23e0 (diff) | |
download | gcc-f802a42401e16c7b918cee539e3c38f4d6f7a336.zip gcc-f802a42401e16c7b918cee539e3c38f4d6f7a336.tar.gz gcc-f802a42401e16c7b918cee539e3c38f4d6f7a336.tar.bz2 |
re PR tree-optimization/69760 (Wrong 64-bit memory address caused by an unneeded overflowing 32-bit integer multiplication on x86_64 under -O2 and -O3 code optimization)
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.
Co-Authored-By: Jakub Jelinek <jakub@redhat.com>
From-SVN: r233669
Diffstat (limited to 'gcc')
-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 53376ae..0c2c960 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 d956d00..2e41588 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 0000000..8f24608 --- /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 c36a039..fdd5da0 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: |