Commit 83ede847 by Richard Biener Committed by Richard Biener

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
parent c401fb6f
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
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
......
/* { 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;
}
/* { 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--);
}
}
...@@ -2349,6 +2349,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr, ...@@ -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, ...@@ -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))
{
type = VR_RANGE;
if (vr1.type == VR_RANGE
&& !symbolic_range_p (&vr1))
{
/* 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))
{ {
/* For MIN_EXPR and MAX_EXPR with two VR_ANTI_RANGEs, type = VR_RANGE;
the resulting VR_ANTI_RANGE is the same - intersection if (code == MIN_EXPR)
of the two ranges. */ {
min = vrp_int_const_binop (MAX_EXPR, vr0.min, vr1.min); min = vrp_val_min (expr_type);
max = vrp_int_const_binop (MIN_EXPR, vr0.max, vr1.max); 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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment