From f802a42401e16c7b918cee539e3c38f4d6f7a336 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 24 Feb 2016 14:54:01 +0000 Subject: [PATCH] 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 Jakub Jelinek 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 From-SVN: r233669 --- gcc/ChangeLog | 7 +++ gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/gcc.dg/torture/pr69760.c | 50 ++++++++++++++++++ gcc/tree-scalar-evolution.c | 70 +++++++++++++++++++++----- 4 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr69760.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 53376ae27bb4..0c2c960612c9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2016-02-24 Richard Biener + Jakub Jelinek + + 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 PR middle-end/69915 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d956d00569fa..2e4158839c9d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-02-24 Richard Biener + Jakub Jelinek + + PR middle-end/69760 + * gcc.dg/torture/pr69760.c: New testcase. + 2016-02-24 Rainer Orth * 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 000000000000..8f24608d232f --- /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 +#include + +__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 c36a0398db62..fdd5da0589a8 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: -- 2.47.2