On Thu, 18 Oct 2018, Richard Biener wrote: > > 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.
Actually not. Needed to update to the new value_range class and after that (and its introduction of ->check()) we now ICE during bootstrap with during GIMPLE pass: evrp /space/rguenther/src/svn/trunk/libgcc/config/libbid/bid128_div.c: In function ‘get_BID128’: /space/rguenther/src/svn/trunk/libgcc/config/libbid/bid128_div.c:1851:1: internal compiler error: in check, at tree-vrp.c:155 1851 | } | ^ 0xf3a8b5 value_range::check() /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:155 0xf42424 value_range::value_range(value_range_kind, tree_node*, tree_node*, bitmap_head*) /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:110 0xf42424 set_value_range_with_overflow /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:1422 0xf42424 extract_range_from_binary_expr_1(value_range*, tree_code, tree_node*, value_range const*, value_range const*) /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:1679 for a PLUS_EXPR of [12254, expon_43] and [-1, -1] yielding (temporarily!) [12254, -1] before supposed to be adjusted by the symbolic bound: /* Adjust the range for possible overflow. */ set_value_range_with_overflow (*vr, expr_type, wmin, wmax, min_ovf, max_ovf); ^^^ ICE if (vr->varying_p ()) return; /* Build the symbolic bounds if needed. */ min = vr->min (); max = vr->max (); adjust_symbolic_bound (min, code, expr_type, sym_min_op0, sym_min_op1, neg_min_op0, neg_min_op1); adjust_symbolic_bound (max, code, expr_type, sym_max_op0, sym_max_op1, neg_max_op0, neg_max_op1); type = vr->kind (); I think the refactoring that was applied here is simply not suitable because *vr is _not_ necessarily a valid range before the symbolic bounds have been adjusted. A fix would be sth like the following which I am going to test now. Richard. diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 40d40e5e2fe..c5748a43246 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -1328,7 +1328,7 @@ combine_bound (enum tree_code code, wide_int &wi, wi::overflow_type &ovf, underflow. +1 indicates overflow. 0 indicates neither. */ static void -set_value_range_with_overflow (value_range &vr, +set_value_range_with_overflow (value_range_kind &kind, tree &min, tree &max, tree type, const wide_int &wmin, const wide_int &wmax, wi::overflow_type min_ovf, @@ -1341,7 +1341,7 @@ set_value_range_with_overflow (value_range &vr, range covers all values. */ if (prec == 1 && wi::lt_p (wmax, wmin, sgn)) { - set_value_range_to_varying (&vr); + kind = VR_VARYING; return; } @@ -1357,13 +1357,15 @@ set_value_range_with_overflow (value_range &vr, the entire range. We have a similar check at the end of extract_range_from_binary_expr_1. */ if (wi::gt_p (tmin, tmax, sgn)) - vr.set_varying (); + kind = VR_VARYING; else - /* No overflow or both overflow or underflow. The - range kind stays VR_RANGE. */ - vr = value_range (VR_RANGE, - wide_int_to_tree (type, tmin), - wide_int_to_tree (type, tmax)); + { + kind = VR_RANGE; + /* No overflow or both overflow or underflow. The + range kind stays VR_RANGE. */ + min = wide_int_to_tree (type, tmin); + max = wide_int_to_tree (type, tmax); + } return; } else if ((min_ovf == wi::OVF_UNDERFLOW && max_ovf == wi::OVF_NONE) @@ -1384,18 +1386,18 @@ set_value_range_with_overflow (value_range &vr, types values. */ if (covers || wi::cmp (tmin, tmax, sgn) > 0) { - set_value_range_to_varying (&vr); + kind = VR_VARYING; return; } - vr = value_range (VR_ANTI_RANGE, - wide_int_to_tree (type, tmin), - wide_int_to_tree (type, tmax)); + kind = VR_ANTI_RANGE; + min = wide_int_to_tree (type, tmin); + max = wide_int_to_tree (type, tmax); return; } else { /* Other underflow and/or overflow, drop to VR_VARYING. */ - set_value_range_to_varying (&vr); + kind = VR_VARYING; return; } } @@ -1405,7 +1407,7 @@ set_value_range_with_overflow (value_range &vr, value. */ wide_int type_min = wi::min_value (prec, sgn); wide_int type_max = wi::max_value (prec, sgn); - tree min, max; + kind = VR_RANGE; if (min_ovf == wi::OVF_UNDERFLOW) min = wide_int_to_tree (type, type_min); else if (min_ovf == wi::OVF_OVERFLOW) @@ -1419,7 +1421,6 @@ set_value_range_with_overflow (value_range &vr, max = wide_int_to_tree (type, type_max); else max = wide_int_to_tree (type, wmax); - vr = value_range (VR_RANGE, min, max); } } @@ -1676,21 +1677,20 @@ extract_range_from_binary_expr_1 (value_range *vr, } /* Adjust the range for possible overflow. */ - set_value_range_with_overflow (*vr, expr_type, + min = NULL_TREE; + max = NULL_TREE; + set_value_range_with_overflow (type, min, max, expr_type, wmin, wmax, min_ovf, max_ovf); - if (vr->varying_p ()) + if (type == VR_VARYING) return; /* Build the symbolic bounds if needed. */ - min = vr->min (); - max = vr->max (); adjust_symbolic_bound (min, code, expr_type, sym_min_op0, sym_min_op1, neg_min_op0, neg_min_op1); adjust_symbolic_bound (max, code, expr_type, sym_max_op0, sym_max_op1, neg_max_op0, neg_max_op1); - type = vr->kind (); } else { > 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); > } > } > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)