At some point we decided to not simply intersect all ranges we get via register_edge_assert_for. Instead we simply register them in-order. That causes things like replacing [64, +INF] with ~[0, 0].
The following patch avoids replacing a range with a larger one as obvious improvement. Compared to assert_expr based VRP we lack the ability to put down actual assert_exprs and thus multiple SSA names with ranges we could link via equivalences. In the end we need sth similar, for example by keeping a stack of active ranges for each SSA name. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2018-10-18 Richard Biener <rguent...@suse.de> * gimple-ssa-evrp-analyze.c (evrp_range_analyzer::record_ranges_from_incoming_edge): Be smarter about what ranges to use. * tree-vrp.c (add_assert_info): Dump here. (register_edge_assert_for_2): Instead of here at multiple but not all places. * gcc.dg/tree-ssa/evrp12.c: New testcase. * gcc.dg/predict-6.c: Adjust. * gcc.dg/tree-ssa/vrp33.c: Disable EVRP. * gcc.dg/tree-ssa/vrp02.c: Likewise. * gcc.dg/tree-ssa/cunroll-9.c: Likewise. diff --git a/gcc/gimple-ssa-evrp-analyze.c b/gcc/gimple-ssa-evrp-analyze.c index e9afa80e191..0748a53cdb8 100644 --- a/gcc/gimple-ssa-evrp-analyze.c +++ b/gcc/gimple-ssa-evrp-analyze.c @@ -206,6 +206,17 @@ evrp_range_analyzer::record_ranges_from_incoming_edge (basic_block bb) ordering issues that can lead to worse ranges. */ for (unsigned i = 0; i < vrs.length (); ++i) { + /* But make sure we do not weaken ranges like when + getting first [64, +INF] and then ~[0, 0] from + conditions like (s & 0x3cc0) == 0). */ + value_range *old_vr = get_value_range (vrs[i].first); + value_range tem = *old_vr; + tem.equiv = NULL; + vrp_intersect_ranges (&tem, vrs[i].second); + if (tem.type == old_vr->type + && tem.min == old_vr->min + && tem.max == old_vr->max) + continue; push_value_range (vrs[i].first, vrs[i].second); if (is_fallthru && all_uses_feed_or_dominated_by_stmt (vrs[i].first, stmt)) diff --git a/gcc/testsuite/gcc.dg/predict-6.c b/gcc/testsuite/gcc.dg/predict-6.c index 5d6fbf158f2..08ce5cdb81d 100644 --- a/gcc/testsuite/gcc.dg/predict-6.c +++ b/gcc/testsuite/gcc.dg/predict-6.c @@ -10,9 +10,9 @@ void foo (int base, int bound) int i, ret = 0; for (i = base; i <= bound; i++) { - if (i < base) + if (i <= base) global += bar (i); - if (i < base + 1) + if (i < base + 2) global += bar (i); if (i <= base + 3) global += bar (i); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cunroll-9.c b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-9.c index 0e4407dcbd7..886dc147ad1 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/cunroll-9.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-9.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-cunrolli-details" } */ +/* { dg-options "-O2 -fdump-tree-cunrolli-details -fdisable-tree-evrp" } */ void abort (void); int q (void); int a[10]; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp12.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp12.c new file mode 100644 index 00000000000..b3906c23465 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp12.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +extern void link_error (); + +void +f3 (unsigned int s) +{ + if ((s & 0x3cc0) == 0) + { + if (s >= -15552U) + link_error (); + } + else + { + if (s <= 0x3f) + link_error (); + } +} + +/* { dg-final { scan-tree-dump-not "link_error" "evrp" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp02.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp02.c index 8d14feadb6a..4be538f5944 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp02.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp02.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp1 -fdelete-null-pointer-checks" } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fdelete-null-pointer-checks -fdisable-tree-evrp" } */ struct A { diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp33.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp33.c index 75fefa49925..f1d3863943e 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp33.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp33.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp1 -fno-tree-fre" } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fno-tree-fre -fdisable-tree-evrp" } */ /* This is from PR14052. */ diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index cbc2ea2f26b..6f5ec43670e 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -2133,6 +2133,17 @@ add_assert_info (vec<assert_info> &asserts, info.val = val; info.expr = expr; asserts.safe_push (info); + + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Adding assert for "); + print_generic_expr (dump_file, name); + fprintf (dump_file, " from "); + print_generic_expr (dump_file, expr); + fprintf (dump_file, " %s ", op_symbol_code (comp_code)); + print_generic_expr (dump_file, val); + fprintf (dump_file, "\n"); + } } /* If NAME doesn't have an ASSERT_EXPR registered for asserting @@ -2532,16 +2543,6 @@ register_edge_assert_for_2 (tree name, edge e, tmp = build1 (NOP_EXPR, TREE_TYPE (name), name3); if (cst2 != NULL_TREE) tmp = build2 (PLUS_EXPR, TREE_TYPE (name), tmp, cst2); - - if (dump_file) - { - fprintf (dump_file, "Adding assert for "); - print_generic_expr (dump_file, name3); - fprintf (dump_file, " from "); - print_generic_expr (dump_file, tmp); - fprintf (dump_file, "\n"); - } - add_assert_info (asserts, name3, tmp, comp_code, val); } @@ -2559,16 +2560,6 @@ register_edge_assert_for_2 (tree name, edge e, tmp = build1 (NOP_EXPR, TREE_TYPE (name), tmp); if (cst2 != NULL_TREE) tmp = build2 (PLUS_EXPR, TREE_TYPE (name), tmp, cst2); - - if (dump_file) - { - fprintf (dump_file, "Adding assert for "); - print_generic_expr (dump_file, name2); - fprintf (dump_file, " from "); - print_generic_expr (dump_file, tmp); - fprintf (dump_file, "\n"); - } - add_assert_info (asserts, name2, tmp, comp_code, val); } } @@ -2691,16 +2682,6 @@ register_edge_assert_for_2 (tree name, edge e, cst = fold_build2 (MINUS_EXPR, TREE_TYPE (name2), cst, build_int_cst (TREE_TYPE (name2), 1)); } - - if (dump_file) - { - fprintf (dump_file, "Adding assert for "); - print_generic_expr (dump_file, name2); - fprintf (dump_file, " from "); - print_generic_expr (dump_file, tmp); - fprintf (dump_file, "\n"); - } - add_assert_info (asserts, name2, tmp, new_comp_code, cst); } } @@ -2765,18 +2746,7 @@ register_edge_assert_for_2 (tree name, edge e, } if (new_val) - { - if (dump_file) - { - fprintf (dump_file, "Adding assert for "); - print_generic_expr (dump_file, name2); - fprintf (dump_file, " from "); - print_generic_expr (dump_file, tmp); - fprintf (dump_file, "\n"); - } - - add_assert_info (asserts, name2, tmp, new_comp_code, new_val); - } + add_assert_info (asserts, name2, tmp, new_comp_code, new_val); } /* Add asserts for NAME cmp CST and NAME being defined as @@ -3004,16 +2974,6 @@ register_edge_assert_for_2 (tree name, edge e, maxv2 = maxv - minv; } new_val = wide_int_to_tree (type, maxv2); - - if (dump_file) - { - fprintf (dump_file, "Adding assert for "); - print_generic_expr (dump_file, names[i]); - fprintf (dump_file, " from "); - print_generic_expr (dump_file, tmp); - fprintf (dump_file, "\n"); - } - add_assert_info (asserts, names[i], tmp, LE_EXPR, new_val); } }