re PR tree-optimization/55079 (false positive -Warray-bounds (also seen at -O3 bootstrap))

2012-12-11  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/55079
	* tree-vrp.c (extract_range_from_binary_expr_1): Handle MAX/MIN_EXPR
	for more cases.
	(register_edge_assert_for_2): Register asserts for post-in/decrement
	tests.
	(check_array_ref): Dump what expression we emit array bound
	warnings for.
	(search_for_addr_array): Likewise.

	* gcc.dg/Warray-bounds-9.c: New testcase.
	* gcc.dg/Warray-bounds-10.c: Likewise.
	* gcc.dg/tree-ssa/ssa-pre-1.c: Adjust.

From-SVN: r194388
This commit is contained in:
Richard Biener 2012-12-11 10:06:15 +00:00 committed by Richard Biener
parent c401fb6f18
commit 83ede847e8
5 changed files with 162 additions and 11 deletions

View File

@ -1,3 +1,14 @@
2012-12-11 Richard Biener <rguenther@suse.de>
PR tree-optimization/55079
* tree-vrp.c (extract_range_from_binary_expr_1): Handle MAX/MIN_EXPR
for more cases.
(register_edge_assert_for_2): Register asserts for post-in/decrement
tests.
(check_array_ref): Dump what expression we emit array bound
warnings for.
(search_for_addr_array): Likewise.
2012-12-11 Eric Botcazou <ebotcazou@adacore.com> 2012-12-11 Eric Botcazou <ebotcazou@adacore.com>
* tree-ssa-loop-ivopts.c (prepare_decl_rtl) <ADDR_EXPR>: Generate RTL * tree-ssa-loop-ivopts.c (prepare_decl_rtl) <ADDR_EXPR>: Generate RTL

View File

@ -1,3 +1,10 @@
2012-12-11 Richard Biener <rguenther@suse.de>
PR tree-optimization/55079
* gcc.dg/Warray-bounds-9.c: New testcase.
* gcc.dg/Warray-bounds-10.c: Likewise.
* gcc.dg/tree-ssa/ssa-pre-1.c: Adjust.
2012-12-10 Janus Weil <janus@gcc.gnu.org> 2012-12-10 Janus Weil <janus@gcc.gnu.org>
PR fortran/52909 PR fortran/52909

View File

@ -0,0 +1,25 @@
/* { dg-do compile } */
/* { dg-options "-O3 -Warray-bounds" } */
int f(unsigned len, int buflen)
{
unsigned taillen;
unsigned slen;
unsigned i;
int b[17]; /* needed <= 17 to trigger Warning */
int j = 0; /* needed to trigger Warning */
b[0] = 0;
taillen= buflen & 7; /* taillen [0..7] */
if(taillen) { /* taillen [1..7] */
slen= 8 - taillen; /* slen [7..1] */
if (len<slen) /* needed to trigger Warning */
slen=len; /* slen' < slen */
for(i=0; i<slen; i++) {
j = b[taillen]; /* taillen + slen = [1..7] + [7..1] = 8 */
taillen++;
}
}
return j;
}

View File

@ -0,0 +1,19 @@
/* { dg-do compile } */
/* { dg-options "-O3 -Warray-bounds" } */
int a[8];
void
test(unsigned int n)
{
unsigned int i;
unsigned int j;
if (n<8)
for (j=0;j<n;j++)
{
i = j;
do
a[i+1]=a[i];
while (i--);
}
}

View File

@ -2349,6 +2349,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
&& code != EXACT_DIV_EXPR && code != EXACT_DIV_EXPR
&& code != ROUND_DIV_EXPR && code != ROUND_DIV_EXPR
&& code != TRUNC_MOD_EXPR && code != TRUNC_MOD_EXPR
&& code != MIN_EXPR
&& code != MAX_EXPR
&& (vr0.type == VR_VARYING && (vr0.type == VR_VARYING
|| vr1.type == VR_VARYING || vr1.type == VR_VARYING
|| vr0.type != vr1.type || vr0.type != vr1.type
@ -2602,21 +2604,49 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
else if (code == MIN_EXPR else if (code == MIN_EXPR
|| code == MAX_EXPR) || code == MAX_EXPR)
{ {
if (vr0.type == VR_ANTI_RANGE) if (vr0.type == VR_RANGE
&& !symbolic_range_p (&vr0))
{ {
/* For MIN_EXPR and MAX_EXPR with two VR_ANTI_RANGEs, type = VR_RANGE;
the resulting VR_ANTI_RANGE is the same - intersection if (vr1.type == VR_RANGE
of the two ranges. */ && !symbolic_range_p (&vr1))
min = vrp_int_const_binop (MAX_EXPR, vr0.min, vr1.min); {
max = vrp_int_const_binop (MIN_EXPR, vr0.max, vr1.max); /* For operations that make the resulting range directly
proportional to the original ranges, apply the operation to
the same end of each range. */
min = vrp_int_const_binop (code, vr0.min, vr1.min);
max = vrp_int_const_binop (code, vr0.max, vr1.max);
}
else if (code == MIN_EXPR)
{
min = vrp_val_min (expr_type);
max = vr0.max;
}
else if (code == MAX_EXPR)
{
min = vr0.min;
max = vrp_val_max (expr_type);
}
}
else if (vr1.type == VR_RANGE
&& !symbolic_range_p (&vr1))
{
type = VR_RANGE;
if (code == MIN_EXPR)
{
min = vrp_val_min (expr_type);
max = vr1.max;
}
else if (code == MAX_EXPR)
{
min = vr1.min;
max = vrp_val_max (expr_type);
}
} }
else else
{ {
/* For operations that make the resulting range directly set_value_range_to_varying (vr);
proportional to the original ranges, apply the operation to return;
the same end of each range. */
min = vrp_int_const_binop (code, vr0.min, vr1.min);
max = vrp_int_const_binop (code, vr0.max, vr1.max);
} }
} }
else if (code == MULT_EXPR) else if (code == MULT_EXPR)
@ -4707,6 +4737,45 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
} }
} }
/* In the case of post-in/decrement tests like if (i++) ... and uses
of the in/decremented value on the edge the extra name we want to
assert for is not on the def chain of the name compared. Instead
it is in the set of use stmts. */
if ((comp_code == NE_EXPR
|| comp_code == EQ_EXPR)
&& TREE_CODE (val) == INTEGER_CST)
{
imm_use_iterator ui;
gimple use_stmt;
FOR_EACH_IMM_USE_STMT (use_stmt, ui, name)
{
/* Cut off to use-stmts that are in the predecessor. */
if (gimple_bb (use_stmt) != e->src)
continue;
if (!is_gimple_assign (use_stmt))
continue;
enum tree_code code = gimple_assign_rhs_code (use_stmt);
if (code != PLUS_EXPR
&& code != MINUS_EXPR)
continue;
tree cst = gimple_assign_rhs2 (use_stmt);
if (TREE_CODE (cst) != INTEGER_CST)
continue;
tree name2 = gimple_assign_lhs (use_stmt);
if (live_on_edge (e, name2))
{
cst = int_const_binop (code, val, cst);
register_new_assert_for (name2, name2, comp_code, cst,
NULL, e, bsi);
retval = true;
}
}
}
if (TREE_CODE_CLASS (comp_code) == tcc_comparison if (TREE_CODE_CLASS (comp_code) == tcc_comparison
&& TREE_CODE (val) == INTEGER_CST) && TREE_CODE (val) == INTEGER_CST)
{ {
@ -5943,6 +6012,11 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
: (tree_int_cst_lt (up_bound, up_sub) : (tree_int_cst_lt (up_bound, up_sub)
|| tree_int_cst_equal (up_bound_p1, up_sub)))) || tree_int_cst_equal (up_bound_p1, up_sub))))
{ {
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Array bound warning for ");
dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
}
warning_at (location, OPT_Warray_bounds, warning_at (location, OPT_Warray_bounds,
"array subscript is above array bounds"); "array subscript is above array bounds");
TREE_NO_WARNING (ref) = 1; TREE_NO_WARNING (ref) = 1;
@ -5950,6 +6024,11 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
else if (TREE_CODE (low_sub) == INTEGER_CST else if (TREE_CODE (low_sub) == INTEGER_CST
&& tree_int_cst_lt (low_sub, low_bound)) && tree_int_cst_lt (low_sub, low_bound))
{ {
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Array bound warning for ");
dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
}
warning_at (location, OPT_Warray_bounds, warning_at (location, OPT_Warray_bounds,
"array subscript is below array bounds"); "array subscript is below array bounds");
TREE_NO_WARNING (ref) = 1; TREE_NO_WARNING (ref) = 1;
@ -6018,6 +6097,11 @@ search_for_addr_array (tree t, location_t location)
idx = idx.sdiv (tree_to_double_int (el_sz), TRUNC_DIV_EXPR); idx = idx.sdiv (tree_to_double_int (el_sz), TRUNC_DIV_EXPR);
if (idx.slt (double_int_zero)) if (idx.slt (double_int_zero))
{ {
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Array bound warning for ");
dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
}
warning_at (location, OPT_Warray_bounds, warning_at (location, OPT_Warray_bounds,
"array subscript is below array bounds"); "array subscript is below array bounds");
TREE_NO_WARNING (t) = 1; TREE_NO_WARNING (t) = 1;
@ -6026,6 +6110,11 @@ search_for_addr_array (tree t, location_t location)
- tree_to_double_int (low_bound) - tree_to_double_int (low_bound)
+ double_int_one)) + double_int_one))
{ {
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Array bound warning for ");
dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
}
warning_at (location, OPT_Warray_bounds, warning_at (location, OPT_Warray_bounds,
"array subscript is above array bounds"); "array subscript is above array bounds");
TREE_NO_WARNING (t) = 1; TREE_NO_WARNING (t) = 1;