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:
parent
525f795f86
commit
f802a42401
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue