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
This commit is contained in:
Richard Biener 2016-02-24 14:54:01 +00:00 committed by Richard Biener
parent 525f795f86
commit f802a42401
4 changed files with 120 additions and 13 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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: