This is another -Warray-bounds false-positive triggered by more aggressive loop unrolling. Fortunately VRP has everything available to compute correct bounds - if it were not for VRP itself pessimizing itself (it runs twice after all) by folding predicates from a < C to a != C (and similar transforms). While the folded variant is better for code-gen it's worse for analysis. Thus the following patch defers that to the 2nd run of VRP.
Bootstrapped and tested on x86_64-unknown-linux-gnu, testing in progress. Richard. 2013-02-11 Richard Biener <rguent...@suse.de> PR tree-optimization/56273 * tree-vrp.c (simplify_cond_using_ranges): Disable for the first VRP run. (check_array_ref): Fix missing newline in dumps. (search_for_addr_array): Likewise. * g++.dg/warn/Warray-bounds-6.C: New testcase. * gcc.dg/tree-ssa/pr21559.c: Adjust. * gcc.dg/tree-ssa/vrp17.c: Likewise. * gcc.dg/tree-ssa/vrp18.c: Likewise. * gcc.dg/tree-ssa/vrp23.c: Likewise. * gcc.dg/tree-ssa/vrp24.c: Likewise. Index: gcc/tree-vrp.c =================================================================== *** gcc/tree-vrp.c (revision 195938) --- gcc/tree-vrp.c (working copy) *************** check_array_ref (location_t location, tr *** 6027,6032 **** --- 6022,6028 ---- { fprintf (dump_file, "Array bound warning for "); dump_generic_expr (MSG_NOTE, TDF_SLIM, ref); + fprintf (dump_file, "\n"); } warning_at (location, OPT_Warray_bounds, "array subscript is above array bounds"); *************** check_array_ref (location_t location, tr *** 6039,6044 **** --- 6035,6041 ---- { fprintf (dump_file, "Array bound warning for "); dump_generic_expr (MSG_NOTE, TDF_SLIM, ref); + fprintf (dump_file, "\n"); } warning_at (location, OPT_Warray_bounds, "array subscript is below array bounds"); *************** search_for_addr_array (tree t, location_ *** 6112,6117 **** --- 6109,6115 ---- { fprintf (dump_file, "Array bound warning for "); dump_generic_expr (MSG_NOTE, TDF_SLIM, t); + fprintf (dump_file, "\n"); } warning_at (location, OPT_Warray_bounds, "array subscript is below array bounds"); *************** search_for_addr_array (tree t, location_ *** 6125,6130 **** --- 6123,6129 ---- { fprintf (dump_file, "Array bound warning for "); dump_generic_expr (MSG_NOTE, TDF_SLIM, t); + fprintf (dump_file, "\n"); } warning_at (location, OPT_Warray_bounds, "array subscript is above array bounds"); *************** test_for_singularity (enum tree_code con *** 8499,8507 **** return NULL; } ! /* Simplify a conditional using a relational operator to an equality ! test if the range information indicates only one value can satisfy ! the original conditional. */ static bool simplify_cond_using_ranges (gimple stmt) --- 8498,8505 ---- return NULL; } ! /* Simplify the conditional stmt STMT using final range information. ! Return true if we simplified the statement. */ static bool simplify_cond_using_ranges (gimple stmt) *************** simplify_cond_using_ranges (gimple stmt) *** 8510,8516 **** tree op1 = gimple_cond_rhs (stmt); enum tree_code cond_code = gimple_cond_code (stmt); ! if (cond_code != NE_EXPR && cond_code != EQ_EXPR && TREE_CODE (op0) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (op0)) --- 8508,8520 ---- tree op1 = gimple_cond_rhs (stmt); enum tree_code cond_code = gimple_cond_code (stmt); ! /* Simplify a conditional using a relational operator to an equality ! test if the range information indicates only one value can satisfy ! the original conditional. ! Do that only in the second VRP pass as otherwise assertions derived ! from this predicate are weakened. */ ! if (!first_pass_instance ! && cond_code != NE_EXPR && cond_code != EQ_EXPR && TREE_CODE (op0) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (op0)) Index: gcc/testsuite/g++.dg/warn/Warray-bounds-6.C =================================================================== *** gcc/testsuite/g++.dg/warn/Warray-bounds-6.C (revision 0) --- gcc/testsuite/g++.dg/warn/Warray-bounds-6.C (working copy) *************** *** 0 **** --- 1,30 ---- + // { dg-do compile } + // { dg-options "-O3 -Warray-bounds" } + + struct type { + bool a, b; + bool get_b() { return b; } + }; + + type stuff[9u]; + + void bar(); + + void foo() { + + for(unsigned i = 0u; i < 9u; i++) { + + if(!stuff[i].a) { + continue; + } + + bar(); + + for(unsigned j = i + 1u; j < 9u; j++) { + if(stuff[j].a && stuff[j].get_b()) { // { dg-bogus "array bounds" } + return; + } + } + + } + } Index: gcc/testsuite/gcc.dg/tree-ssa/pr21559.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/pr21559.c (revision 195938) --- gcc/testsuite/gcc.dg/tree-ssa/pr21559.c (working copy) *************** *** 1,5 **** /* { dg-do compile } */ ! /* { dg-options "-O2 -fdump-tree-vrp1-details" } */ static int blocksize = 4096; --- 1,5 ---- /* { dg-do compile } */ ! /* { dg-options "-O2 -fdump-tree-vrp-details" } */ static int blocksize = 4096; *************** void foo (void) *** 32,38 **** /* First, we should simplify the bits < 0 test within the loop. */ ! /* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */ /* Second, we should thread the edge out of the loop via the break statement. We also realize that the final bytes == 0 test is useless, --- 32,38 ---- /* First, we should simplify the bits < 0 test within the loop. */ ! /* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp2" } } */ /* Second, we should thread the edge out of the loop via the break statement. We also realize that the final bytes == 0 test is useless, *************** void foo (void) *** 40,43 **** /* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp1" } } */ /* { dg-final { cleanup-tree-dump "vrp1" } } */ ! --- 40,43 ---- /* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp1" } } */ /* { dg-final { cleanup-tree-dump "vrp1" } } */ ! /* { dg-final { cleanup-tree-dump "vrp2" } } */ Index: gcc/testsuite/gcc.dg/tree-ssa/vrp17.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/vrp17.c (revision 195938) --- gcc/testsuite/gcc.dg/tree-ssa/vrp17.c (working copy) *************** *** 1,5 **** /* { dg-do compile } */ ! /* { dg-options "-O2 -fdump-tree-vrp1" } */ extern void abort (void) __attribute__ ((__noreturn__)); union tree_node; --- 1,5 ---- /* { dg-do compile } */ ! /* { dg-options "-O2 -fdump-tree-vrp2" } */ extern void abort (void) __attribute__ ((__noreturn__)); union tree_node; *************** gimplify_for_stmt (tree stmt) *** 27,32 **** abort (); } ! /* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */ ! /* { dg-final { cleanup-tree-dump "vrp1" } } */ --- 27,32 ---- abort (); } ! /* { dg-final { scan-tree-dump-times "Simplified relational" 2 "vrp1" } } */ ! /* { dg-final { cleanup-tree-dump "vrp2" } } */ Index: gcc/testsuite/gcc.dg/tree-ssa/vrp18.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/vrp18.c (revision 195938) --- gcc/testsuite/gcc.dg/tree-ssa/vrp18.c (working copy) *************** *** 1,5 **** /* { dg-do compile } */ ! /* { dg-options "-O2 -fdump-tree-vrp1" } */ static int blocksize = 4096; --- 1,5 ---- /* { dg-do compile } */ ! /* { dg-options "-O2 -fdump-tree-vrp2" } */ static int blocksize = 4096; *************** void foo (void) *** 30,34 **** eof_reached = 1; } ! /* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */ ! /* { dg-final { cleanup-tree-dump "vrp1" } } */ --- 30,34 ---- eof_reached = 1; } ! /* { dg-final { scan-tree-dump-times "Simplified relational" 2 "vrp1" } } */ ! /* { dg-final { cleanup-tree-dump "vrp2" } } */ Index: gcc/testsuite/gcc.dg/tree-ssa/vrp23.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/vrp23.c (revision 195938) --- gcc/testsuite/gcc.dg/tree-ssa/vrp23.c (working copy) *************** *** 1,5 **** /* { dg-do compile } */ ! /* { dg-options "-O2 -fdump-tree-vrp1-details" } */ blah (int code1, int code2) { --- 1,5 ---- /* { dg-do compile } */ ! /* { dg-options "-O2 -fdump-tree-vrp2-details" } */ blah (int code1, int code2) { *************** L8: *** 40,45 **** /* The n_sets > 0 test can be simplified into n_sets == 1 since the only way to reach the test is when n_sets <= 1, and the only value which satisfies both conditions is n_sets == 1. */ ! /* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */ ! /* { dg-final { cleanup-tree-dump "vrp1" } } */ ! --- 40,44 ---- /* The n_sets > 0 test can be simplified into n_sets == 1 since the only way to reach the test is when n_sets <= 1, and the only value which satisfies both conditions is n_sets == 1. */ ! /* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp2" } } */ ! /* { dg-final { cleanup-tree-dump "vrp2" } } */ Index: gcc/testsuite/gcc.dg/tree-ssa/vrp24.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/vrp24.c (revision 195938) --- gcc/testsuite/gcc.dg/tree-ssa/vrp24.c (working copy) *************** *** 1,6 **** /* { dg-do compile } */ ! /* { dg-options "-O2 -fdump-tree-vrp1-details" } */ ! struct rtx_def; typedef struct rtx_def *rtx; --- 1,5 ---- /* { dg-do compile } */ ! /* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp2-details" } */ struct rtx_def; typedef struct rtx_def *rtx; *************** L7: *** 86,91 **** The second n_sets > 0 test can also be simplified into n_sets == 1 as the only way to reach the tests is when n_sets <= 1 and the only value which satisfies both conditions is n_sets == 1. */ ! /* { dg-final { scan-tree-dump-times "Simplified relational" 2 "vrp1" } } */ ! /* { dg-final { cleanup-tree-dump "vrp1" } } */ ! --- 85,89 ---- The second n_sets > 0 test can also be simplified into n_sets == 1 as the only way to reach the tests is when n_sets <= 1 and the only value which satisfies both conditions is n_sets == 1. */ ! /* { dg-final { scan-tree-dump-times "Simplified relational" 2 "vrp2" } } */ ! /* { dg-final { cleanup-tree-dump "vrp2" } } */