This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR55079
- From: Richard Biener <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 10 Dec 2012 16:11:10 +0100 (CET)
- Subject: [PATCH] Fix PR55079
This improves VRP so that two of the three (the remaining one invalid
IMHO) spurious array-bound warnings in PR55079 no longer appear.
With the patch we now properly handle
MIN_EXPR <[1, 6], VARYING>
and register asserts for i_2 in
i_2 = i_1 + 1;
if (i_1 != 0)
which is a common pattern from tests of post-modify expressions.
For gcc.dg/tree-ssa/ssa-pre-1.c this is too fancy and thus I needed
to adjust the testcase to avoid VRP being too clever.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
Richard.
2012-12-10 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.
Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c (revision 194358)
--- gcc/tree-vrp.c (working copy)
*************** extract_range_from_binary_expr_1 (value_
*** 2349,2354 ****
--- 2349,2356 ----
&& 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
*************** extract_range_from_binary_expr_1 (value_
*** 2602,2622 ****
else if (code == MIN_EXPR
|| code == MAX_EXPR)
{
! if (vr0.type == VR_ANTI_RANGE)
{
! /* 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);
}
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);
}
}
else if (code == MULT_EXPR)
--- 2604,2652 ----
else if (code == MIN_EXPR
|| code == MAX_EXPR)
{
! 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))
! {
! 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
{
! set_value_range_to_varying (vr);
! return;
}
}
else if (code == MULT_EXPR)
*************** register_edge_assert_for_2 (tree name, e
*** 4707,4712 ****
--- 4737,4781 ----
}
}
+ /* 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)
{
*************** check_array_ref (location_t location, tr
*** 5943,5948 ****
--- 6012,6022 ----
: (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;
*************** check_array_ref (location_t location, tr
*** 5950,5955 ****
--- 6024,6034 ----
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;
*************** search_for_addr_array (tree t, location_
*** 6018,6023 ****
--- 6097,6107 ----
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;
*************** search_for_addr_array (tree t, location_
*** 6026,6031 ****
--- 6110,6120 ----
- 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;
Index: gcc/testsuite/gcc.dg/Warray-bounds-9.c
===================================================================
*** gcc/testsuite/gcc.dg/Warray-bounds-9.c (revision 0)
--- gcc/testsuite/gcc.dg/Warray-bounds-9.c (working copy)
***************
*** 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--);
+ }
+ }
Index: gcc/testsuite/gcc.dg/Warray-bounds-10.c
===================================================================
*** gcc/testsuite/gcc.dg/Warray-bounds-10.c (revision 0)
--- gcc/testsuite/gcc.dg/Warray-bounds-10.c (working copy)
***************
*** 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;
+ }
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c (revision 194358)
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c (working copy)
*************** int foo(int argc, char **argv)
*** 9,15 ****
b = argc + 1;
c = argc + 2;
a = b + c;
! if (argc * 2)
{
c = argc + 3;
}
--- 9,15 ----
b = argc + 1;
c = argc + 2;
a = b + c;
! if (argc > 2)
{
c = argc + 3;
}