This patch adapts the strlen pass to use the irange API. I wasn't able to remove the one annoying use of VR_ANTI_RANGE, because I'm not sure what to do. Perhaps Martin can shed some light. The current code has:
else if (rng == VR_ANTI_RANGE) { wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node)); if (wi::ltu_p (cntrange[1], maxobjsize)) { cntrange[0] = cntrange[1] + 1; cntrange[1] = maxobjsize; Suppose we have ~[10,20], won't the above set cntrange[] to [21,MAX]? Won't this ignore the 0..9 that is part of the range? What should we do here? Anyways, I've left the anti-range in place, but the rest of the patch still stands. OK? gcc/ChangeLog: * tree-ssa-strlen.c (get_range): Adjust for irange API. (compare_nonzero_chars): Same. (dump_strlen_info): Same. (get_range_strlen_dynamic): Same. (set_strlen_range): Same. (maybe_diag_stxncpy_trunc): Same. (get_len_or_size): Same. (count_nonzero_bytes_addr): Same. (handle_integral_assign): Same. --- gcc/tree-ssa-strlen.c | 122 ++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 65 deletions(-) diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index fbaee745f7d..e6009874ee5 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -220,21 +220,25 @@ get_range (tree val, wide_int minmax[2], const vr_values *rvals /* = NULL */) GCC 11). */ const value_range *vr = (CONST_CAST (class vr_values *, rvals)->get_value_range (val)); - value_range_kind rng = vr->kind (); - if (rng != VR_RANGE || !range_int_cst_p (vr)) + if (vr->undefined_p () || vr->varying_p ()) return NULL_TREE; - minmax[0] = wi::to_wide (vr->min ()); - minmax[1] = wi::to_wide (vr->max ()); + minmax[0] = vr->lower_bound (); + minmax[1] = vr->upper_bound (); return val; } - value_range_kind rng = get_range_info (val, minmax, minmax + 1); - if (rng == VR_RANGE) - return val; + value_range vr; + get_range_info (val, vr); + if (!vr.undefined_p () && !vr.varying_p ()) + { + minmax[0] = vr.lower_bound (); + minmax[1] = vr.upper_bound (); + return val; + } - /* Do not handle anti-ranges and instead make use of the on-demand - VRP if/when it becomes available (hopefully in GCC 11). */ + /* We should adjust for the on-demand VRP if/when it becomes + available (hopefully in GCC 11). */ return NULL_TREE; } @@ -278,16 +282,18 @@ compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off, = (CONST_CAST (class vr_values *, rvals) ->get_value_range (si->nonzero_chars)); - value_range_kind rng = vr->kind (); - if (rng != VR_RANGE || !range_int_cst_p (vr)) + if (vr->undefined_p () || vr->varying_p ()) return -1; /* If the offset is less than the minimum length or if the bounds of the length range are equal return the result of the comparison same as in the constant case. Otherwise return a conservative result. */ - int cmpmin = compare_tree_int (vr->min (), off); - if (cmpmin > 0 || tree_int_cst_equal (vr->min (), vr->max ())) + tree type = TREE_TYPE (si->nonzero_chars); + tree tmin = wide_int_to_tree (type, vr->lower_bound ()); + tree tmax = wide_int_to_tree (type, vr->upper_bound ()); + int cmpmin = compare_tree_int (tmin, off); + if (cmpmin > 0 || tree_int_cst_equal (tmin, tmax)) return cmpmin; return -1; @@ -905,32 +911,14 @@ dump_strlen_info (FILE *fp, gimple *stmt, const vr_values *rvals) print_generic_expr (fp, si->nonzero_chars); if (TREE_CODE (si->nonzero_chars) == SSA_NAME) { - value_range_kind rng = VR_UNDEFINED; - wide_int min, max; + value_range vr; if (rvals) - { - const value_range *vr - = CONST_CAST (class vr_values *, rvals) - ->get_value_range (si->nonzero_chars); - rng = vr->kind (); - if (range_int_cst_p (vr)) - { - min = wi::to_wide (vr->min ()); - max = wi::to_wide (vr->max ()); - } - else - rng = VR_UNDEFINED; - } + vr = *(CONST_CAST (class vr_values *, rvals) + ->get_value_range (si->nonzero_chars)); else - rng = get_range_info (si->nonzero_chars, &min, &max); - - if (rng == VR_RANGE || rng == VR_ANTI_RANGE) - { - fprintf (fp, " %s[%llu, %llu]", - rng == VR_RANGE ? "" : "~", - (long long) min.to_uhwi (), - (long long) max.to_uhwi ()); - } + get_range_info (si->nonzero_chars, vr); + vr.normalize_symbolics (); + vr.dump (fp); } } @@ -1113,11 +1101,13 @@ get_range_strlen_dynamic (tree src, c_strlen_data *pdata, bitmap *visited, const value_range_equiv *vr = CONST_CAST (class vr_values *, rvals) ->get_value_range (si->nonzero_chars); - if (vr->kind () == VR_RANGE - && range_int_cst_p (vr)) + if (!vr->undefined_p () && !vr->varying_p ()) { - pdata->minlen = vr->min (); - pdata->maxlen = vr->max (); + tree type = TREE_TYPE (si->nonzero_chars); + tree tmin = wide_int_to_tree (type, vr->lower_bound ()); + tree tmax = wide_int_to_tree (type, vr->upper_bound ()); + pdata->minlen = tmin; + pdata->maxlen = tmax; } else pdata->minlen = build_zero_cst (size_type_node); @@ -1159,11 +1149,11 @@ get_range_strlen_dynamic (tree src, c_strlen_data *pdata, bitmap *visited, const value_range_equiv *vr = CONST_CAST (class vr_values *, rvals) ->get_value_range (si->nonzero_chars); - if (vr->kind () == VR_RANGE - && range_int_cst_p (vr)) + if (!vr->undefined_p () && !vr->varying_p ()) { - pdata->minlen = vr->min (); - pdata->maxlen = vr->max (); + tree type = TREE_TYPE (si->nonzero_chars); + pdata->minlen = wide_int_to_tree (type, vr->lower_bound ()); + pdata->maxlen = wide_int_to_tree (type, vr->upper_bound ()); pdata->maxbound = pdata->maxlen; } else @@ -1803,12 +1793,14 @@ set_strlen_range (tree lhs, wide_int min, wide_int max, else if (TREE_CODE (bound) == SSA_NAME) { wide_int minbound, maxbound; - value_range_kind rng = get_range_info (bound, &minbound, &maxbound); - if (rng == VR_RANGE) + value_range vr; + get_range_info (bound, vr); + if (!vr.undefined_p () && !vr.varying_p ()) { + wide_int minbound = vr.lower_bound (); + wide_int maxbound = vr.upper_bound (); /* For a bound in a known range, adjust the range determined - above as necessary. For a bound in some anti-range or - in an unknown range, use the range determined by callers. */ + above as necessary. */ if (wi::ltu_p (minbound, min)) min = minbound; if (wi::ltu_p (maxbound, max)) @@ -3045,6 +3037,8 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt) if (wi::ltu_p (cntrange[1], maxobjsize)) { + /* FIXME: Imagine ~[10,20]. The code here will set + cntrange[] to [21,MAX]. Why are we ignoring [0,9] ?? */ cntrange[0] = cntrange[1] + 1; cntrange[1] = maxobjsize; } @@ -4139,10 +4133,12 @@ get_len_or_size (tree arg, int idx, unsigned HOST_WIDE_INT lenrng[2], } else if (TREE_CODE (si->nonzero_chars) == SSA_NAME) { - wide_int min, max; - value_range_kind rng = get_range_info (si->nonzero_chars, &min, &max); - if (rng == VR_RANGE) + value_range vr; + get_range_info (si->nonzero_chars, vr); + if (!vr.undefined_p () && !vr.varying_p ()) { + wide_int min = vr.lower_bound (); + wide_int max = vr.upper_bound (); lenrng[0] = min.to_uhwi (); lenrng[1] = max.to_uhwi (); *nulterm = si->full_string_p; @@ -4847,11 +4843,11 @@ count_nonzero_bytes_addr (tree exp, unsigned HOST_WIDE_INT offset, { vr_values *v = CONST_CAST (vr_values *, rvals); const value_range_equiv *vr = v->get_value_range (si->nonzero_chars); - if (vr->kind () != VR_RANGE || !range_int_cst_p (vr)) + if (vr->undefined_p () || vr->varying_p ()) return false; - - minlen = tree_to_uhwi (vr->min ()); - maxlen = tree_to_uhwi (vr->max ()); + tree type = TREE_TYPE (si->nonzero_chars); + minlen = tree_to_uhwi (wide_int_to_tree (type, vr->lower_bound ())); + maxlen = tree_to_uhwi (wide_int_to_tree (type, vr->upper_bound ())); } else return false; @@ -5554,16 +5550,12 @@ handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh, /* Reading a character before the final '\0' character. Just set the value range to ~[0, 0] if we don't have anything better. */ - wide_int min, max; - signop sign = TYPE_SIGN (lhs_type); - int prec = TYPE_PRECISION (lhs_type); - value_range_kind vr = get_range_info (lhs, &min, &max); - if (vr == VR_VARYING - || (vr == VR_RANGE - && min == wi::min_value (prec, sign) - && max == wi::max_value (prec, sign))) + value_range vr; + get_range_info (lhs, vr); + if (vr.varying_p ()) set_range_info (lhs, VR_ANTI_RANGE, - wi::zero (prec), wi::zero (prec)); + wi::zero (TYPE_PRECISION (lhs_type)), + wi::zero (TYPE_PRECISION (lhs_type))); } } } -- 2.26.2