mirror of git://gcc.gnu.org/git/gcc.git
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>
|
2016-02-24 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR middle-end/69915
|
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>
|
2016-02-24 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
|
||||||
|
|
||||||
* gcc.dg/debug/dwarf2/prod-options.c: Use different DW_AT_producer
|
* 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,
|
interpret_rhs_expr (struct loop *loop, gimple *at_stmt,
|
||||||
tree type, tree rhs1, enum tree_code code, tree rhs2)
|
tree type, tree rhs1, enum tree_code code, tree rhs2)
|
||||||
{
|
{
|
||||||
tree res, chrec1, chrec2;
|
tree res, chrec1, chrec2, ctype;
|
||||||
gimple *def;
|
gimple *def;
|
||||||
|
|
||||||
if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS)
|
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:
|
case PLUS_EXPR:
|
||||||
chrec1 = analyze_scalar_evolution (loop, rhs1);
|
chrec1 = analyze_scalar_evolution (loop, rhs1);
|
||||||
chrec2 = analyze_scalar_evolution (loop, rhs2);
|
chrec2 = analyze_scalar_evolution (loop, rhs2);
|
||||||
chrec1 = chrec_convert (type, chrec1, at_stmt);
|
ctype = type;
|
||||||
chrec2 = chrec_convert (type, chrec2, at_stmt);
|
/* 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);
|
chrec1 = instantiate_parameters (loop, chrec1);
|
||||||
chrec2 = instantiate_parameters (loop, chrec2);
|
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;
|
break;
|
||||||
|
|
||||||
case MINUS_EXPR:
|
case MINUS_EXPR:
|
||||||
chrec1 = analyze_scalar_evolution (loop, rhs1);
|
chrec1 = analyze_scalar_evolution (loop, rhs1);
|
||||||
chrec2 = analyze_scalar_evolution (loop, rhs2);
|
chrec2 = analyze_scalar_evolution (loop, rhs2);
|
||||||
chrec1 = chrec_convert (type, chrec1, at_stmt);
|
ctype = type;
|
||||||
chrec2 = chrec_convert (type, chrec2, at_stmt);
|
/* 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);
|
chrec1 = instantiate_parameters (loop, chrec1);
|
||||||
chrec2 = instantiate_parameters (loop, chrec2);
|
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;
|
break;
|
||||||
|
|
||||||
case NEGATE_EXPR:
|
case NEGATE_EXPR:
|
||||||
chrec1 = analyze_scalar_evolution (loop, rhs1);
|
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. */
|
/* TYPE may be integer, real or complex, so use fold_convert. */
|
||||||
chrec1 = instantiate_parameters (loop, chrec1);
|
chrec1 = instantiate_parameters (loop, chrec1);
|
||||||
res = chrec_fold_multiply (type, chrec1,
|
res = chrec_fold_multiply (ctype, chrec1,
|
||||||
fold_convert (type, integer_minus_one_node));
|
fold_convert (ctype, integer_minus_one_node));
|
||||||
|
if (type != ctype)
|
||||||
|
res = chrec_convert (type, res, at_stmt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BIT_NOT_EXPR:
|
case BIT_NOT_EXPR:
|
||||||
|
|
@ -1837,11 +1870,22 @@ interpret_rhs_expr (struct loop *loop, gimple *at_stmt,
|
||||||
case MULT_EXPR:
|
case MULT_EXPR:
|
||||||
chrec1 = analyze_scalar_evolution (loop, rhs1);
|
chrec1 = analyze_scalar_evolution (loop, rhs1);
|
||||||
chrec2 = analyze_scalar_evolution (loop, rhs2);
|
chrec2 = analyze_scalar_evolution (loop, rhs2);
|
||||||
chrec1 = chrec_convert (type, chrec1, at_stmt);
|
ctype = type;
|
||||||
chrec2 = chrec_convert (type, chrec2, at_stmt);
|
/* 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);
|
chrec1 = instantiate_parameters (loop, chrec1);
|
||||||
chrec2 = instantiate_parameters (loop, chrec2);
|
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;
|
break;
|
||||||
|
|
||||||
case LSHIFT_EXPR:
|
case LSHIFT_EXPR:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue