diff options
author | Richard Biener <rguenther@suse.de> | 2012-12-11 10:06:15 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2012-12-11 10:06:15 +0000 |
commit | 83ede847e82db63f9d56c98aa7830f0d4f0e76e1 (patch) | |
tree | 7cbb63bd058c4cb36880da81ecd6d37b2c1e99a6 /gcc | |
parent | c401fb6f18ed51467bc84311bdc1d9f64b57309a (diff) | |
download | gcc-83ede847e82db63f9d56c98aa7830f0d4f0e76e1.zip gcc-83ede847e82db63f9d56c98aa7830f0d4f0e76e1.tar.gz gcc-83ede847e82db63f9d56c98aa7830f0d4f0e76e1.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Warray-bounds-10.c | 25 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Warray-bounds-9.c | 19 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 111 |
5 files changed, 162 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eef5504..fc1a827 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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> * tree-ssa-loop-ivopts.c (prepare_decl_rtl) <ADDR_EXPR>: Generate RTL diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 481bbaa..3e81e76 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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> PR fortran/52909 diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-10.c b/gcc/testsuite/gcc.dg/Warray-bounds-10.c new file mode 100644 index 0000000..5fd6e6f --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-10.c @@ -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; +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-9.c b/gcc/testsuite/gcc.dg/Warray-bounds-9.c new file mode 100644 index 0000000..92bcd4e --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-9.c @@ -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--); + } +} diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index dc03db5..4319c60 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -2349,6 +2349,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr, && code != EXACT_DIV_EXPR && code != ROUND_DIV_EXPR && code != TRUNC_MOD_EXPR + && code != MIN_EXPR + && code != MAX_EXPR && (vr0.type == VR_VARYING || vr1.type == VR_VARYING || vr0.type != vr1.type @@ -2602,21 +2604,49 @@ extract_range_from_binary_expr_1 (value_range_t *vr, else if (code == MIN_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, - the resulting VR_ANTI_RANGE is the same - intersection - of the two ranges. */ - min = vrp_int_const_binop (MAX_EXPR, vr0.min, vr1.min); - max = vrp_int_const_binop (MIN_EXPR, vr0.max, vr1.max); + 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 { - /* 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); + set_value_range_to_varying (vr); + return; } } 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 && 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_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, "array subscript is above array bounds"); 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 && 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, "array subscript is below array bounds"); 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); 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, "array subscript is below array bounds"); TREE_NO_WARNING (t) = 1; @@ -6026,6 +6110,11 @@ search_for_addr_array (tree t, location_t location) - tree_to_double_int (low_bound) + 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, "array subscript is above array bounds"); TREE_NO_WARNING (t) = 1; |