[COMMITTED] Implement vrange::supports_type_p.

Message ID 20220603073056.2683008-1-aldyh@redhat.com
State Committed
Commit a9058b08381cd76e8d21364f0f5ccddb3777c3fd
Headers
Series [COMMITTED] Implement vrange::supports_type_p. |

Commit Message

Aldy Hernandez June 3, 2022, 7:30 a.m. UTC
  [I have conservatively assumed that both the loop-ch and loop-unswitch
passes, which also use the ranger, only support integers and pointers.
If the goal is to handle other types as well, irange::supports_p()
should be Value_Range::supports_type_p(), and any uses of
int_range_max should be converted to Value_Range.  I can help in the
conversion if you'd like.]

As discussed, this patch disambiguates the use of supports_type_p
throughout, as what ranger supports is a totally different question
than what a given range variant (irange, frange, etc) supports.

Unfortunately we need both a static method and a virtual method, and
they can't be named the same.  The uses are documented in the vrange
class:

+// To query what types ranger and the entire ecosystem can support,
+// use Value_Range::supports_type_p(tree type).  This is a static
+// method available independently of any vrange object.
+//
+// To query what a given vrange variant can support, use:
+//    irange::supports_p ()
+//    frange::supports_p ()
+//    etc
+//
+// To query what a range object can support, use:
+//    void foo (vrange &v, irange &i, frange &f)
+//    {
+//     if (v.supports_type_p (type)) ...
+//     if (i.supports_type_p (type)) ...
+//     if (f.supports_type_p (type)) ...
+//    }

The value_range_equiv::supports_p() method can be use to determine
what legacy VRP supports, as irange::supports_p() will no longer be
applicable in the evrp analyzer code base once irange and prange are
split.

Tested on x86-64 Linux.

gcc/ChangeLog:

	* gimple-range-edge.cc (gimple_outgoing_range_stmt_p): Adjust for
	an object level supports_type_p for irange and a static
	Value_Range::supports_type_p.
	* gimple-range-fold.cc (fold_using_range::range_of_range_op): Same.
	(fold_using_range::range_of_address): Same.
	(fold_using_range::range_of_builtin_call): Same.
	* gimple-range-fold.h (gimple_range_type): Same.
	(gimple_range_ssa_p): Same.
	* gimple-range-path.cc (path_range_query::internal_range_of_expr):
	Same.
	(path_range_query::range_of_stmt): Same.
	(path_range_query::add_to_imports): Same.
	* gimple-range.cc (gimple_ranger::range_on_edge): Same.
	(gimple_ranger::export_global_ranges): Same.
	* gimple-ssa-evrp-analyze.cc
	(evrp_range_analyzer::record_ranges_from_phis):  Same.
	* range-op.cc (range_operator::wi_fold): Same.
	(range_operator::fold_range): Same.
	* tree-ssa-loop-ch.cc (entry_loop_condition_is_static): Same.
	* tree-ssa-loop-unswitch.cc (struct unswitch_predicate): Same.
	(evaluate_control_stmt_using_entry_checks): Same.
	* tree-ssa-threadedge.cc
	(hybrid_jt_simplifier::compute_ranges_from_state): Same.
	* tree-vrp.cc (supported_types_p): Same.
	* value-query.cc (range_query::value_of_expr): Same.
	(range_query::value_on_edge): Same.
	(range_query::value_of_stmt): Same.
	(range_query::get_tree_range): Same.
	(get_range_global): Same.
	(global_range_query::range_of_expr): Same.
	* value-range-equiv.h (class value_range_equiv): Same.
	* value-range.cc (irange::supports_type_p): Same.
	(unsupported_range::supports_type_p): Same.
	* value-range.h (enum value_range_discriminator): Same.
	(Value_Range::init): Same.
	(Value_Range::supports_type_p): Same.
	(irange::supports_type_p): Same.
	(irange::supports_p): Same.
	(vrange::supports_type_p): Same.
	(vrange_allocator::alloc_vrange): Same.
---
 gcc/gimple-range-edge.cc       |  3 +--
 gcc/gimple-range-fold.cc       |  5 ++--
 gcc/gimple-range-fold.h        |  4 +--
 gcc/gimple-range-path.cc       |  6 ++---
 gcc/gimple-range.cc            |  4 +--
 gcc/gimple-ssa-evrp-analyze.cc |  2 +-
 gcc/range-op.cc                |  4 +--
 gcc/tree-ssa-loop-ch.cc        |  2 +-
 gcc/tree-ssa-loop-unswitch.cc  |  6 ++---
 gcc/tree-ssa-threadedge.cc     |  2 +-
 gcc/tree-vrp.cc                |  4 +--
 gcc/value-query.cc             | 16 ++++++------
 gcc/value-range-equiv.h        |  4 +++
 gcc/value-range.cc             | 12 +++++++++
 gcc/value-range.h              | 45 +++++++++++++++++++++++++---------
 15 files changed, 76 insertions(+), 43 deletions(-)
  

Comments

Richard Biener June 13, 2022, 9:43 a.m. UTC | #1
On Fri, Jun 3, 2022 at 9:31 AM Aldy Hernandez <aldyh@redhat.com> wrote:
>
> [I have conservatively assumed that both the loop-ch and loop-unswitch
> passes, which also use the ranger, only support integers and pointers.
> If the goal is to handle other types as well, irange::supports_p()
> should be Value_Range::supports_type_p(), and any uses of
> int_range_max should be converted to Value_Range.  I can help in the
> conversion if you'd like.]

Both should also support float ranges, so yes - if you can send simple
patches I'll review them.

> As discussed, this patch disambiguates the use of supports_type_p
> throughout, as what ranger supports is a totally different question
> than what a given range variant (irange, frange, etc) supports.
>
> Unfortunately we need both a static method and a virtual method, and
> they can't be named the same.  The uses are documented in the vrange
> class:
>
> +// To query what types ranger and the entire ecosystem can support,
> +// use Value_Range::supports_type_p(tree type).  This is a static
> +// method available independently of any vrange object.
> +//
> +// To query what a given vrange variant can support, use:
> +//    irange::supports_p ()
> +//    frange::supports_p ()
> +//    etc
> +//
> +// To query what a range object can support, use:
> +//    void foo (vrange &v, irange &i, frange &f)
> +//    {
> +//     if (v.supports_type_p (type)) ...
> +//     if (i.supports_type_p (type)) ...
> +//     if (f.supports_type_p (type)) ...
> +//    }
>
> The value_range_equiv::supports_p() method can be use to determine
> what legacy VRP supports, as irange::supports_p() will no longer be
> applicable in the evrp analyzer code base once irange and prange are
> split.
>
> Tested on x86-64 Linux.
>
> gcc/ChangeLog:
>
>         * gimple-range-edge.cc (gimple_outgoing_range_stmt_p): Adjust for
>         an object level supports_type_p for irange and a static
>         Value_Range::supports_type_p.
>         * gimple-range-fold.cc (fold_using_range::range_of_range_op): Same.
>         (fold_using_range::range_of_address): Same.
>         (fold_using_range::range_of_builtin_call): Same.
>         * gimple-range-fold.h (gimple_range_type): Same.
>         (gimple_range_ssa_p): Same.
>         * gimple-range-path.cc (path_range_query::internal_range_of_expr):
>         Same.
>         (path_range_query::range_of_stmt): Same.
>         (path_range_query::add_to_imports): Same.
>         * gimple-range.cc (gimple_ranger::range_on_edge): Same.
>         (gimple_ranger::export_global_ranges): Same.
>         * gimple-ssa-evrp-analyze.cc
>         (evrp_range_analyzer::record_ranges_from_phis):  Same.
>         * range-op.cc (range_operator::wi_fold): Same.
>         (range_operator::fold_range): Same.
>         * tree-ssa-loop-ch.cc (entry_loop_condition_is_static): Same.
>         * tree-ssa-loop-unswitch.cc (struct unswitch_predicate): Same.
>         (evaluate_control_stmt_using_entry_checks): Same.
>         * tree-ssa-threadedge.cc
>         (hybrid_jt_simplifier::compute_ranges_from_state): Same.
>         * tree-vrp.cc (supported_types_p): Same.
>         * value-query.cc (range_query::value_of_expr): Same.
>         (range_query::value_on_edge): Same.
>         (range_query::value_of_stmt): Same.
>         (range_query::get_tree_range): Same.
>         (get_range_global): Same.
>         (global_range_query::range_of_expr): Same.
>         * value-range-equiv.h (class value_range_equiv): Same.
>         * value-range.cc (irange::supports_type_p): Same.
>         (unsupported_range::supports_type_p): Same.
>         * value-range.h (enum value_range_discriminator): Same.
>         (Value_Range::init): Same.
>         (Value_Range::supports_type_p): Same.
>         (irange::supports_type_p): Same.
>         (irange::supports_p): Same.
>         (vrange::supports_type_p): Same.
>         (vrange_allocator::alloc_vrange): Same.
> ---
>  gcc/gimple-range-edge.cc       |  3 +--
>  gcc/gimple-range-fold.cc       |  5 ++--
>  gcc/gimple-range-fold.h        |  4 +--
>  gcc/gimple-range-path.cc       |  6 ++---
>  gcc/gimple-range.cc            |  4 +--
>  gcc/gimple-ssa-evrp-analyze.cc |  2 +-
>  gcc/range-op.cc                |  4 +--
>  gcc/tree-ssa-loop-ch.cc        |  2 +-
>  gcc/tree-ssa-loop-unswitch.cc  |  6 ++---
>  gcc/tree-ssa-threadedge.cc     |  2 +-
>  gcc/tree-vrp.cc                |  4 +--
>  gcc/value-query.cc             | 16 ++++++------
>  gcc/value-range-equiv.h        |  4 +++
>  gcc/value-range.cc             | 12 +++++++++
>  gcc/value-range.h              | 45 +++++++++++++++++++++++++---------
>  15 files changed, 76 insertions(+), 43 deletions(-)
>
> diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
> index 6fe33408f7e..03a804ac2be 100644
> --- a/gcc/gimple-range-edge.cc
> +++ b/gcc/gimple-range-edge.cc
> @@ -44,8 +44,7 @@ gimple_outgoing_range_stmt_p (basic_block bb)
>        gimple *s = gsi_stmt (gsi);
>        if (is_a<gcond *> (s) && range_op_handler (s))
>         return gsi_stmt (gsi);
> -      gswitch *sw = dyn_cast<gswitch *> (s);
> -      if (sw && irange::supports_type_p (TREE_TYPE (gimple_switch_index (sw))))
> +      if (is_a <gswitch *> (s))
>         return gsi_stmt (gsi);
>      }
>    return NULL;
> diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
> index c1a801668c4..2a8c66e0c05 100644
> --- a/gcc/gimple-range-fold.cc
> +++ b/gcc/gimple-range-fold.cc
> @@ -632,7 +632,7 @@ fold_using_range::range_of_range_op (vrange &r, gimple *s, fur_source &src)
>             }
>           // Fold range, and register any dependency if available.
>           handler.fold_range (r, type, range1, range2, rel);
> -         if (irange::supports_type_p (type))
> +         if (irange::supports_p (type))
>             relation_fold_and_or (as_a <irange> (r), s, src);
>           if (lhs)
>             {
> @@ -709,7 +709,6 @@ fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src)
>        tree lhs = gimple_get_lhs (stmt);
>        if (lhs && gimple_range_ssa_p (ssa) && src.gori ())
>         src.gori ()->register_dependency (lhs, ssa);
> -      gcc_checking_assert (irange::supports_type_p (TREE_TYPE (ssa)));
>        src.get_operand (r, ssa);
>        range_cast (r, TREE_TYPE (gimple_assign_rhs1 (stmt)));
>
> @@ -985,7 +984,7 @@ fold_using_range::range_of_builtin_call (vrange &r, gcall *call,
>    tree type = gimple_range_type (call);
>    gcc_checking_assert (type);
>
> -  if (irange::supports_type_p (type))
> +  if (irange::supports_p (type))
>      return range_of_builtin_int_call (as_a <irange> (r), call, src);
>
>    return false;
> diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
> index df24280ee40..fbf66275f74 100644
> --- a/gcc/gimple-range-fold.h
> +++ b/gcc/gimple-range-fold.h
> @@ -66,7 +66,7 @@ gimple_range_type (const gimple *s)
>             type = TREE_TYPE (type);
>         }
>      }
> -  if (type && vrange::supports_type_p (type))
> +  if (type && Value_Range::supports_type_p (type))
>      return type;
>    return NULL_TREE;
>  }
> @@ -79,7 +79,7 @@ gimple_range_ssa_p (tree exp)
>    if (exp && TREE_CODE (exp) == SSA_NAME &&
>        !SSA_NAME_IS_VIRTUAL_OPERAND (exp) &&
>        !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) &&
> -      vrange::supports_type_p (TREE_TYPE (exp)))
> +      Value_Range::supports_type_p (TREE_TYPE (exp)))
>      return exp;
>    return NULL_TREE;
>  }
> diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
> index f8ae6fb9ffb..e1b9683c1e4 100644
> --- a/gcc/gimple-range-path.cc
> +++ b/gcc/gimple-range-path.cc
> @@ -192,7 +192,7 @@ path_range_query::range_on_path_entry (vrange &r, tree name)
>  bool
>  path_range_query::internal_range_of_expr (vrange &r, tree name, gimple *stmt)
>  {
> -  if (!vrange::supports_type_p (TREE_TYPE (name)))
> +  if (!r.supports_type_p (TREE_TYPE (name)))
>      return false;
>
>    if (get_cache (r, name))
> @@ -548,7 +548,7 @@ bool
>  path_range_query::add_to_imports (tree name, bitmap imports)
>  {
>    if (TREE_CODE (name) == SSA_NAME
> -      && vrange::supports_type_p (TREE_TYPE (name)))
> +      && Value_Range::supports_type_p (TREE_TYPE (name)))
>      return bitmap_set_bit (imports, SSA_NAME_VERSION (name));
>    return false;
>  }
> @@ -764,7 +764,7 @@ path_range_query::range_of_stmt (vrange &r, gimple *stmt, tree)
>  {
>    tree type = gimple_range_type (stmt);
>
> -  if (!type || !vrange::supports_type_p (type))
> +  if (!type || !r.supports_type_p (type))
>      return false;
>
>    // If resolving unknowns, fold the statement making use of any
> diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
> index 12da16841c2..67dafb2a2c0 100644
> --- a/gcc/gimple-range.cc
> +++ b/gcc/gimple-range.cc
> @@ -201,7 +201,7 @@ bool
>  gimple_ranger::range_on_edge (vrange &r, edge e, tree name)
>  {
>    Value_Range edge_range (TREE_TYPE (name));
> -  gcc_checking_assert (vrange::supports_type_p (TREE_TYPE (name)));
> +  gcc_checking_assert (r.supports_type_p (TREE_TYPE (name)));
>
>    // Do not process values along abnormal edges.
>    if (e->flags & EDGE_ABNORMAL)
> @@ -514,7 +514,7 @@ gimple_ranger::export_global_ranges ()
>               print_header = false;
>             }
>
> -         if (!irange::supports_type_p (TREE_TYPE (name)))
> +         if (!irange::supports_p (TREE_TYPE (name)))
>             continue;
>
>           vrange &v = r;
> diff --git a/gcc/gimple-ssa-evrp-analyze.cc b/gcc/gimple-ssa-evrp-analyze.cc
> index 16e5a75b1db..82142db7976 100644
> --- a/gcc/gimple-ssa-evrp-analyze.cc
> +++ b/gcc/gimple-ssa-evrp-analyze.cc
> @@ -255,7 +255,7 @@ evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
>
>        /* Skips floats and other things we can't represent in a
>          range.  */
> -      if (!value_range::supports_type_p (TREE_TYPE (lhs)))
> +      if (!value_range_equiv::supports_p (TREE_TYPE (lhs)))
>         continue;
>
>        value_range_equiv vr_result;
> diff --git a/gcc/range-op.cc b/gcc/range-op.cc
> index 028b4b7237c..5150c6021b8 100644
> --- a/gcc/range-op.cc
> +++ b/gcc/range-op.cc
> @@ -111,7 +111,7 @@ range_operator::wi_fold (irange &r, tree type,
>                          const wide_int &rh_lb ATTRIBUTE_UNUSED,
>                          const wide_int &rh_ub ATTRIBUTE_UNUSED) const
>  {
> -  gcc_checking_assert (irange::supports_type_p (type));
> +  gcc_checking_assert (r.supports_type_p (type));
>    r.set_varying (type);
>  }
>
> @@ -181,7 +181,7 @@ range_operator::fold_range (irange &r, tree type,
>                             const irange &rh,
>                             relation_kind rel) const
>  {
> -  gcc_checking_assert (irange::supports_type_p (type));
> +  gcc_checking_assert (r.supports_type_p (type));
>    if (empty_range_varying (r, type, lh, rh))
>      return true;
>
> diff --git a/gcc/tree-ssa-loop-ch.cc b/gcc/tree-ssa-loop-ch.cc
> index 2f5a390404c..26d96c0c21a 100644
> --- a/gcc/tree-ssa-loop-ch.cc
> +++ b/gcc/tree-ssa-loop-ch.cc
> @@ -55,7 +55,7 @@ entry_loop_condition_is_static (class loop *l, path_range_query *query)
>    gcond *last = safe_dyn_cast <gcond *> (last_stmt (e->dest));
>
>    if (!last
> -      || !irange::supports_type_p (TREE_TYPE (gimple_cond_lhs (last))))
> +      || !irange::supports_p (TREE_TYPE (gimple_cond_lhs (last))))
>      return false;
>
>    edge true_e, false_e;
> diff --git a/gcc/tree-ssa-loop-unswitch.cc b/gcc/tree-ssa-loop-unswitch.cc
> index ad1d05ccdff..95ccc0b7b47 100644
> --- a/gcc/tree-ssa-loop-unswitch.cc
> +++ b/gcc/tree-ssa-loop-unswitch.cc
> @@ -113,7 +113,7 @@ struct unswitch_predicate
>        true_range (edge_range), edge_index (edge_index_), switch_p (true)
>    {
>      gcc_assert (!(e->flags & (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE))
> -               && irange::supports_type_p (TREE_TYPE (lhs)));
> +               && irange::supports_p (TREE_TYPE (lhs)));
>      false_range = true_range;
>      if (!false_range.varying_p ()
>         && !false_range.undefined_p ())
> @@ -134,7 +134,7 @@ struct unswitch_predicate
>      tree rhs = gimple_cond_rhs (stmt);
>      enum tree_code code = gimple_cond_code (stmt);
>      condition = build2 (code, boolean_type_node, lhs, rhs);
> -    if (irange::supports_type_p (TREE_TYPE (lhs)))
> +    if (irange::supports_p (TREE_TYPE (lhs)))
>        {
>         auto range_op = range_op_handler (code, TREE_TYPE (lhs));
>         int_range<2> rhs_range (TREE_TYPE (rhs));
> @@ -646,7 +646,7 @@ evaluate_control_stmt_using_entry_checks (gimple *stmt,
>                               TREE_OPERAND (last_predicate->condition, 1)))
>         return true_edge ? boolean_true_node : boolean_false_node;
>        /* Else try ranger if it supports LHS.  */
> -      else if (irange::supports_type_p (TREE_TYPE (lhs)))
> +      else if (irange::supports_p (TREE_TYPE (lhs)))
>         {
>           int_range<2> r;
>           int_range_max path_range;
> diff --git a/gcc/tree-ssa-threadedge.cc b/gcc/tree-ssa-threadedge.cc
> index 931aa7479bb..a70aebd10a7 100644
> --- a/gcc/tree-ssa-threadedge.cc
> +++ b/gcc/tree-ssa-threadedge.cc
> @@ -1452,7 +1452,7 @@ hybrid_jt_simplifier::compute_ranges_from_state (gimple *stmt, jt_state *state)
>           tree op = gimple_op (stmt, i);
>           if (op
>               && TREE_CODE (op) == SSA_NAME
> -             && irange::supports_type_p (TREE_TYPE (op)))
> +             && Value_Range::supports_type_p (TREE_TYPE (op)))
>             bitmap_set_bit (imports, SSA_NAME_VERSION (op));
>         }
>      }
> diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
> index 74277617b66..30022dac108 100644
> --- a/gcc/tree-vrp.cc
> +++ b/gcc/tree-vrp.cc
> @@ -932,8 +932,8 @@ supported_types_p (value_range *vr,
>                    tree type0,
>                    tree type1 = NULL)
>  {
> -  if (!value_range::supports_type_p (type0)
> -      || (type1 && !value_range::supports_type_p (type1)))
> +  if (!value_range_equiv::supports_p (type0)
> +      || (type1 && !value_range_equiv::supports_p (type1)))
>      {
>        vr->set_varying (type0);
>        return false;
> diff --git a/gcc/value-query.cc b/gcc/value-query.cc
> index e40e358ebd4..1d7541ce34f 100644
> --- a/gcc/value-query.cc
> +++ b/gcc/value-query.cc
> @@ -80,7 +80,7 @@ range_query::value_of_expr (tree expr, gimple *stmt)
>  {
>    tree t;
>
> -  if (!vrange::supports_type_p (TREE_TYPE (expr)))
> +  if (!Value_Range::supports_type_p (TREE_TYPE (expr)))
>      return NULL_TREE;
>
>    Value_Range r (TREE_TYPE (expr));
> @@ -102,7 +102,7 @@ range_query::value_on_edge (edge e, tree expr)
>  {
>    tree t;
>
> -  if (!vrange::supports_type_p (TREE_TYPE (expr)))
> +  if (!Value_Range::supports_type_p (TREE_TYPE (expr)))
>      return NULL_TREE;
>    Value_Range r (TREE_TYPE (expr));
>    if (range_on_edge (r, e, expr))
> @@ -128,7 +128,7 @@ range_query::value_of_stmt (gimple *stmt, tree name)
>
>    gcc_checking_assert (!name || name == gimple_get_lhs (stmt));
>
> -  if (!name || !vrange::supports_type_p (TREE_TYPE (name)))
> +  if (!name || !Value_Range::supports_type_p (TREE_TYPE (name)))
>      return NULL_TREE;
>    Value_Range r (TREE_TYPE (name));
>    if (range_of_stmt (r, stmt, name) && r.singleton_p (&t))
> @@ -196,7 +196,7 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt)
>    else
>      type = TREE_TYPE (expr);
>
> -  if (!vrange::supports_type_p (type))
> +  if (!Value_Range::supports_type_p (type))
>      {
>        r.set_undefined ();
>        return false;
> @@ -252,7 +252,7 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt)
>      {
>        range_op_handler op (TREE_CODE (expr), type);
>        tree op0_type = TREE_TYPE (TREE_OPERAND (expr, 0));
> -      if (op && vrange::supports_type_p (op0_type))
> +      if (op && Value_Range::supports_type_p (op0_type))
>         {
>           Value_Range r0 (TREE_TYPE (TREE_OPERAND (expr, 0)));
>           Value_Range r1 (type);
> @@ -387,7 +387,7 @@ get_range_global (vrange &r, tree name)
>     }
>    else if (!POINTER_TYPE_P (type) && SSA_NAME_RANGE_INFO (name))
>      {
> -      gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name)));
> +      gcc_checking_assert (irange::supports_p (TREE_TYPE (name)));
>        get_ssa_name_range_info (as_a <irange> (r), name);
>        if (r.undefined_p ())
>         r.set_varying (type);
> @@ -441,9 +441,7 @@ global_range_query global_ranges;
>  bool
>  global_range_query::range_of_expr (vrange &r, tree expr, gimple *stmt)
>  {
> -  tree type = TREE_TYPE (expr);
> -
> -  if (!irange::supports_type_p (type) || !gimple_range_ssa_p (expr))
> +  if (!gimple_range_ssa_p (expr))
>      return get_tree_range (r, expr, stmt);
>
>    get_range_global (r, expr);
> diff --git a/gcc/value-range-equiv.h b/gcc/value-range-equiv.h
> index 743ceb2b227..0a52d1372a1 100644
> --- a/gcc/value-range-equiv.h
> +++ b/gcc/value-range-equiv.h
> @@ -67,6 +67,10 @@ class GTY((user)) value_range_equiv : public value_range
>    void deep_copy (const value_range_equiv *);
>    void dump (FILE *) const;
>    void dump () const;
> +  static bool supports_p (tree type)
> +  {
> +    return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type);
> +  }
>
>   private:
>    /* Deep-copies bitmap argument.  */
> diff --git a/gcc/value-range.cc b/gcc/value-range.cc
> index 429672737a8..c4bcb970094 100644
> --- a/gcc/value-range.cc
> +++ b/gcc/value-range.cc
> @@ -107,6 +107,12 @@ vrange::operator== (const vrange &src) const
>    gcc_unreachable ();
>  }
>
> +bool
> +irange::supports_type_p (tree type) const
> +{
> +  return supports_p (type);
> +}
> +
>  // Return TRUE if R fits in THIS.
>
>  bool
> @@ -140,6 +146,12 @@ unsupported_range::type () const
>    return nullptr;
>  }
>
> +bool
> +unsupported_range::supports_type_p (tree) const
> +{
> +  return false;
> +}
> +
>  void
>  unsupported_range::set_undefined ()
>  {
> diff --git a/gcc/value-range.h b/gcc/value-range.h
> index 5cd0e0ef76a..69cf6c304d6 100644
> --- a/gcc/value-range.h
> +++ b/gcc/value-range.h
> @@ -50,6 +50,23 @@ enum value_range_discriminator
>  };
>
>  // Abstract class for ranges of any of the supported types.
> +//
> +// To query what types ranger and the entire ecosystem can support,
> +// use Value_Range::supports_type_p(tree type).  This is a static
> +// method available independently of any vrange object.
> +//
> +// To query what a given vrange variant can support, use:
> +//    irange::supports_p ()
> +//    frange::supports_p ()
> +//    etc
> +//
> +// To query what a range object can support, use:
> +//    void foo (vrange &v, irange &i, frange &f)
> +//    {
> +//     if (v.supports_type_p (type)) ...
> +//     if (i.supports_type_p (type)) ...
> +//     if (f.supports_type_p (type)) ...
> +//    }
>
>  class vrange
>  {
> @@ -58,6 +75,7 @@ class vrange
>  public:
>    virtual void set (tree, tree, value_range_kind = VR_RANGE) = 0;
>    virtual tree type () const = 0;
> +  virtual bool supports_type_p (tree type) const = 0;
>    virtual void set_varying (tree type) = 0;
>    virtual void set_undefined () = 0;
>    virtual void dump (FILE * = stderr) const = 0;
> @@ -72,8 +90,6 @@ public:
>    virtual void set_nonnegative (tree type) = 0;
>    virtual bool fits_p (const vrange &r) const = 0;
>
> -  static bool supports_type_p (tree);
> -
>    bool varying_p () const;
>    bool undefined_p () const;
>    vrange& operator= (const vrange &);
> @@ -103,7 +119,8 @@ public:
>    virtual void set_undefined () override;
>
>    // Range types.
> -  static bool supports_type_p (tree);
> +  static bool supports_p (tree type);
> +  virtual bool supports_type_p (tree type) const override;
>    virtual tree type () const override;
>
>    // Iteration over sub-ranges.
> @@ -228,6 +245,7 @@ public:
>    unsupported_range ();
>    virtual void set (tree, tree, value_range_kind) override;
>    virtual tree type () const override;
> +  virtual bool supports_type_p (tree type) const override;
>    virtual void set_varying (tree type) override;
>    virtual void set_undefined () override;
>    virtual void dump (FILE *) const override;
> @@ -331,6 +349,7 @@ public:
>    operator vrange &();
>    operator const vrange &() const;
>    void dump (FILE *out = stderr) const;
> +  static bool supports_type_p (tree type);
>
>    // Convenience methods for vrange compatability.
>    void set (tree min, tree max, value_range_kind kind = VR_RANGE)
> @@ -387,7 +406,7 @@ Value_Range::init (tree type)
>  {
>    gcc_checking_assert (TYPE_P (type));
>
> -  if (irange::supports_type_p (type))
> +  if (irange::supports_p (type))
>      m_vrange = &m_irange;
>    else
>      m_vrange = &m_unsupported;
> @@ -444,6 +463,14 @@ Value_Range::operator const vrange &() const
>    return *m_vrange;
>  }
>
> +// Return TRUE if TYPE is supported by the vrange infrastructure.
> +
> +inline bool
> +Value_Range::supports_type_p (tree type)
> +{
> +  return irange::supports_p (type);
> +}
> +
>  // Returns true for an old-school value_range as described above.
>  inline bool
>  irange::legacy_mode_p () const
> @@ -580,7 +607,7 @@ irange::nonzero_p () const
>  }
>
>  inline bool
> -irange::supports_type_p (tree type)
> +irange::supports_p (tree type)
>  {
>    return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type);
>  }
> @@ -864,12 +891,6 @@ irange::normalize_kind ()
>      }
>  }
>
> -inline bool
> -vrange::supports_type_p (tree type)
> -{
> -  return irange::supports_type_p (type);
> -}
> -
>  // Return the maximum value for TYPE.
>
>  inline tree
> @@ -944,7 +965,7 @@ vrange_allocator::alloc (unsigned bytes)
>  inline vrange *
>  vrange_allocator::alloc_vrange (tree type)
>  {
> -  if (irange::supports_type_p (type))
> +  if (irange::supports_p (type))
>      return alloc_irange (2);
>
>    gcc_unreachable ();
> --
> 2.36.1
>
  
Aldy Hernandez June 27, 2022, 7 p.m. UTC | #2
The conversion for loop-ch is trivial, since the range of a
GIMPLE_COND is always an integer.

OK for trunk?

p.s. The loop unswitch code requires a bit more thought, since there
are numerous range temporaries in the code that are not necessarily
integers.

On Mon, Jun 13, 2022 at 11:44 AM Richard Biener
<richard.guenther@gmail.com> wrote:
>
> On Fri, Jun 3, 2022 at 9:31 AM Aldy Hernandez <aldyh@redhat.com> wrote:
> >
> > [I have conservatively assumed that both the loop-ch and loop-unswitch
> > passes, which also use the ranger, only support integers and pointers.
> > If the goal is to handle other types as well, irange::supports_p()
> > should be Value_Range::supports_type_p(), and any uses of
> > int_range_max should be converted to Value_Range.  I can help in the
> > conversion if you'd like.]
>
> Both should also support float ranges, so yes - if you can send simple
> patches I'll review them.
>
> > As discussed, this patch disambiguates the use of supports_type_p
> > throughout, as what ranger supports is a totally different question
> > than what a given range variant (irange, frange, etc) supports.
> >
> > Unfortunately we need both a static method and a virtual method, and
> > they can't be named the same.  The uses are documented in the vrange
> > class:
> >
> > +// To query what types ranger and the entire ecosystem can support,
> > +// use Value_Range::supports_type_p(tree type).  This is a static
> > +// method available independently of any vrange object.
> > +//
> > +// To query what a given vrange variant can support, use:
> > +//    irange::supports_p ()
> > +//    frange::supports_p ()
> > +//    etc
> > +//
> > +// To query what a range object can support, use:
> > +//    void foo (vrange &v, irange &i, frange &f)
> > +//    {
> > +//     if (v.supports_type_p (type)) ...
> > +//     if (i.supports_type_p (type)) ...
> > +//     if (f.supports_type_p (type)) ...
> > +//    }
> >
> > The value_range_equiv::supports_p() method can be use to determine
> > what legacy VRP supports, as irange::supports_p() will no longer be
> > applicable in the evrp analyzer code base once irange and prange are
> > split.
> >
> > Tested on x86-64 Linux.
> >
> > gcc/ChangeLog:
> >
> >         * gimple-range-edge.cc (gimple_outgoing_range_stmt_p): Adjust for
> >         an object level supports_type_p for irange and a static
> >         Value_Range::supports_type_p.
> >         * gimple-range-fold.cc (fold_using_range::range_of_range_op): Same.
> >         (fold_using_range::range_of_address): Same.
> >         (fold_using_range::range_of_builtin_call): Same.
> >         * gimple-range-fold.h (gimple_range_type): Same.
> >         (gimple_range_ssa_p): Same.
> >         * gimple-range-path.cc (path_range_query::internal_range_of_expr):
> >         Same.
> >         (path_range_query::range_of_stmt): Same.
> >         (path_range_query::add_to_imports): Same.
> >         * gimple-range.cc (gimple_ranger::range_on_edge): Same.
> >         (gimple_ranger::export_global_ranges): Same.
> >         * gimple-ssa-evrp-analyze.cc
> >         (evrp_range_analyzer::record_ranges_from_phis):  Same.
> >         * range-op.cc (range_operator::wi_fold): Same.
> >         (range_operator::fold_range): Same.
> >         * tree-ssa-loop-ch.cc (entry_loop_condition_is_static): Same.
> >         * tree-ssa-loop-unswitch.cc (struct unswitch_predicate): Same.
> >         (evaluate_control_stmt_using_entry_checks): Same.
> >         * tree-ssa-threadedge.cc
> >         (hybrid_jt_simplifier::compute_ranges_from_state): Same.
> >         * tree-vrp.cc (supported_types_p): Same.
> >         * value-query.cc (range_query::value_of_expr): Same.
> >         (range_query::value_on_edge): Same.
> >         (range_query::value_of_stmt): Same.
> >         (range_query::get_tree_range): Same.
> >         (get_range_global): Same.
> >         (global_range_query::range_of_expr): Same.
> >         * value-range-equiv.h (class value_range_equiv): Same.
> >         * value-range.cc (irange::supports_type_p): Same.
> >         (unsupported_range::supports_type_p): Same.
> >         * value-range.h (enum value_range_discriminator): Same.
> >         (Value_Range::init): Same.
> >         (Value_Range::supports_type_p): Same.
> >         (irange::supports_type_p): Same.
> >         (irange::supports_p): Same.
> >         (vrange::supports_type_p): Same.
> >         (vrange_allocator::alloc_vrange): Same.
> > ---
> >  gcc/gimple-range-edge.cc       |  3 +--
> >  gcc/gimple-range-fold.cc       |  5 ++--
> >  gcc/gimple-range-fold.h        |  4 +--
> >  gcc/gimple-range-path.cc       |  6 ++---
> >  gcc/gimple-range.cc            |  4 +--
> >  gcc/gimple-ssa-evrp-analyze.cc |  2 +-
> >  gcc/range-op.cc                |  4 +--
> >  gcc/tree-ssa-loop-ch.cc        |  2 +-
> >  gcc/tree-ssa-loop-unswitch.cc  |  6 ++---
> >  gcc/tree-ssa-threadedge.cc     |  2 +-
> >  gcc/tree-vrp.cc                |  4 +--
> >  gcc/value-query.cc             | 16 ++++++------
> >  gcc/value-range-equiv.h        |  4 +++
> >  gcc/value-range.cc             | 12 +++++++++
> >  gcc/value-range.h              | 45 +++++++++++++++++++++++++---------
> >  15 files changed, 76 insertions(+), 43 deletions(-)
> >
> > diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
> > index 6fe33408f7e..03a804ac2be 100644
> > --- a/gcc/gimple-range-edge.cc
> > +++ b/gcc/gimple-range-edge.cc
> > @@ -44,8 +44,7 @@ gimple_outgoing_range_stmt_p (basic_block bb)
> >        gimple *s = gsi_stmt (gsi);
> >        if (is_a<gcond *> (s) && range_op_handler (s))
> >         return gsi_stmt (gsi);
> > -      gswitch *sw = dyn_cast<gswitch *> (s);
> > -      if (sw && irange::supports_type_p (TREE_TYPE (gimple_switch_index (sw))))
> > +      if (is_a <gswitch *> (s))
> >         return gsi_stmt (gsi);
> >      }
> >    return NULL;
> > diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
> > index c1a801668c4..2a8c66e0c05 100644
> > --- a/gcc/gimple-range-fold.cc
> > +++ b/gcc/gimple-range-fold.cc
> > @@ -632,7 +632,7 @@ fold_using_range::range_of_range_op (vrange &r, gimple *s, fur_source &src)
> >             }
> >           // Fold range, and register any dependency if available.
> >           handler.fold_range (r, type, range1, range2, rel);
> > -         if (irange::supports_type_p (type))
> > +         if (irange::supports_p (type))
> >             relation_fold_and_or (as_a <irange> (r), s, src);
> >           if (lhs)
> >             {
> > @@ -709,7 +709,6 @@ fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src)
> >        tree lhs = gimple_get_lhs (stmt);
> >        if (lhs && gimple_range_ssa_p (ssa) && src.gori ())
> >         src.gori ()->register_dependency (lhs, ssa);
> > -      gcc_checking_assert (irange::supports_type_p (TREE_TYPE (ssa)));
> >        src.get_operand (r, ssa);
> >        range_cast (r, TREE_TYPE (gimple_assign_rhs1 (stmt)));
> >
> > @@ -985,7 +984,7 @@ fold_using_range::range_of_builtin_call (vrange &r, gcall *call,
> >    tree type = gimple_range_type (call);
> >    gcc_checking_assert (type);
> >
> > -  if (irange::supports_type_p (type))
> > +  if (irange::supports_p (type))
> >      return range_of_builtin_int_call (as_a <irange> (r), call, src);
> >
> >    return false;
> > diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
> > index df24280ee40..fbf66275f74 100644
> > --- a/gcc/gimple-range-fold.h
> > +++ b/gcc/gimple-range-fold.h
> > @@ -66,7 +66,7 @@ gimple_range_type (const gimple *s)
> >             type = TREE_TYPE (type);
> >         }
> >      }
> > -  if (type && vrange::supports_type_p (type))
> > +  if (type && Value_Range::supports_type_p (type))
> >      return type;
> >    return NULL_TREE;
> >  }
> > @@ -79,7 +79,7 @@ gimple_range_ssa_p (tree exp)
> >    if (exp && TREE_CODE (exp) == SSA_NAME &&
> >        !SSA_NAME_IS_VIRTUAL_OPERAND (exp) &&
> >        !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) &&
> > -      vrange::supports_type_p (TREE_TYPE (exp)))
> > +      Value_Range::supports_type_p (TREE_TYPE (exp)))
> >      return exp;
> >    return NULL_TREE;
> >  }
> > diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
> > index f8ae6fb9ffb..e1b9683c1e4 100644
> > --- a/gcc/gimple-range-path.cc
> > +++ b/gcc/gimple-range-path.cc
> > @@ -192,7 +192,7 @@ path_range_query::range_on_path_entry (vrange &r, tree name)
> >  bool
> >  path_range_query::internal_range_of_expr (vrange &r, tree name, gimple *stmt)
> >  {
> > -  if (!vrange::supports_type_p (TREE_TYPE (name)))
> > +  if (!r.supports_type_p (TREE_TYPE (name)))
> >      return false;
> >
> >    if (get_cache (r, name))
> > @@ -548,7 +548,7 @@ bool
> >  path_range_query::add_to_imports (tree name, bitmap imports)
> >  {
> >    if (TREE_CODE (name) == SSA_NAME
> > -      && vrange::supports_type_p (TREE_TYPE (name)))
> > +      && Value_Range::supports_type_p (TREE_TYPE (name)))
> >      return bitmap_set_bit (imports, SSA_NAME_VERSION (name));
> >    return false;
> >  }
> > @@ -764,7 +764,7 @@ path_range_query::range_of_stmt (vrange &r, gimple *stmt, tree)
> >  {
> >    tree type = gimple_range_type (stmt);
> >
> > -  if (!type || !vrange::supports_type_p (type))
> > +  if (!type || !r.supports_type_p (type))
> >      return false;
> >
> >    // If resolving unknowns, fold the statement making use of any
> > diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
> > index 12da16841c2..67dafb2a2c0 100644
> > --- a/gcc/gimple-range.cc
> > +++ b/gcc/gimple-range.cc
> > @@ -201,7 +201,7 @@ bool
> >  gimple_ranger::range_on_edge (vrange &r, edge e, tree name)
> >  {
> >    Value_Range edge_range (TREE_TYPE (name));
> > -  gcc_checking_assert (vrange::supports_type_p (TREE_TYPE (name)));
> > +  gcc_checking_assert (r.supports_type_p (TREE_TYPE (name)));
> >
> >    // Do not process values along abnormal edges.
> >    if (e->flags & EDGE_ABNORMAL)
> > @@ -514,7 +514,7 @@ gimple_ranger::export_global_ranges ()
> >               print_header = false;
> >             }
> >
> > -         if (!irange::supports_type_p (TREE_TYPE (name)))
> > +         if (!irange::supports_p (TREE_TYPE (name)))
> >             continue;
> >
> >           vrange &v = r;
> > diff --git a/gcc/gimple-ssa-evrp-analyze.cc b/gcc/gimple-ssa-evrp-analyze.cc
> > index 16e5a75b1db..82142db7976 100644
> > --- a/gcc/gimple-ssa-evrp-analyze.cc
> > +++ b/gcc/gimple-ssa-evrp-analyze.cc
> > @@ -255,7 +255,7 @@ evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
> >
> >        /* Skips floats and other things we can't represent in a
> >          range.  */
> > -      if (!value_range::supports_type_p (TREE_TYPE (lhs)))
> > +      if (!value_range_equiv::supports_p (TREE_TYPE (lhs)))
> >         continue;
> >
> >        value_range_equiv vr_result;
> > diff --git a/gcc/range-op.cc b/gcc/range-op.cc
> > index 028b4b7237c..5150c6021b8 100644
> > --- a/gcc/range-op.cc
> > +++ b/gcc/range-op.cc
> > @@ -111,7 +111,7 @@ range_operator::wi_fold (irange &r, tree type,
> >                          const wide_int &rh_lb ATTRIBUTE_UNUSED,
> >                          const wide_int &rh_ub ATTRIBUTE_UNUSED) const
> >  {
> > -  gcc_checking_assert (irange::supports_type_p (type));
> > +  gcc_checking_assert (r.supports_type_p (type));
> >    r.set_varying (type);
> >  }
> >
> > @@ -181,7 +181,7 @@ range_operator::fold_range (irange &r, tree type,
> >                             const irange &rh,
> >                             relation_kind rel) const
> >  {
> > -  gcc_checking_assert (irange::supports_type_p (type));
> > +  gcc_checking_assert (r.supports_type_p (type));
> >    if (empty_range_varying (r, type, lh, rh))
> >      return true;
> >
> > diff --git a/gcc/tree-ssa-loop-ch.cc b/gcc/tree-ssa-loop-ch.cc
> > index 2f5a390404c..26d96c0c21a 100644
> > --- a/gcc/tree-ssa-loop-ch.cc
> > +++ b/gcc/tree-ssa-loop-ch.cc
> > @@ -55,7 +55,7 @@ entry_loop_condition_is_static (class loop *l, path_range_query *query)
> >    gcond *last = safe_dyn_cast <gcond *> (last_stmt (e->dest));
> >
> >    if (!last
> > -      || !irange::supports_type_p (TREE_TYPE (gimple_cond_lhs (last))))
> > +      || !irange::supports_p (TREE_TYPE (gimple_cond_lhs (last))))
> >      return false;
> >
> >    edge true_e, false_e;
> > diff --git a/gcc/tree-ssa-loop-unswitch.cc b/gcc/tree-ssa-loop-unswitch.cc
> > index ad1d05ccdff..95ccc0b7b47 100644
> > --- a/gcc/tree-ssa-loop-unswitch.cc
> > +++ b/gcc/tree-ssa-loop-unswitch.cc
> > @@ -113,7 +113,7 @@ struct unswitch_predicate
> >        true_range (edge_range), edge_index (edge_index_), switch_p (true)
> >    {
> >      gcc_assert (!(e->flags & (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE))
> > -               && irange::supports_type_p (TREE_TYPE (lhs)));
> > +               && irange::supports_p (TREE_TYPE (lhs)));
> >      false_range = true_range;
> >      if (!false_range.varying_p ()
> >         && !false_range.undefined_p ())
> > @@ -134,7 +134,7 @@ struct unswitch_predicate
> >      tree rhs = gimple_cond_rhs (stmt);
> >      enum tree_code code = gimple_cond_code (stmt);
> >      condition = build2 (code, boolean_type_node, lhs, rhs);
> > -    if (irange::supports_type_p (TREE_TYPE (lhs)))
> > +    if (irange::supports_p (TREE_TYPE (lhs)))
> >        {
> >         auto range_op = range_op_handler (code, TREE_TYPE (lhs));
> >         int_range<2> rhs_range (TREE_TYPE (rhs));
> > @@ -646,7 +646,7 @@ evaluate_control_stmt_using_entry_checks (gimple *stmt,
> >                               TREE_OPERAND (last_predicate->condition, 1)))
> >         return true_edge ? boolean_true_node : boolean_false_node;
> >        /* Else try ranger if it supports LHS.  */
> > -      else if (irange::supports_type_p (TREE_TYPE (lhs)))
> > +      else if (irange::supports_p (TREE_TYPE (lhs)))
> >         {
> >           int_range<2> r;
> >           int_range_max path_range;
> > diff --git a/gcc/tree-ssa-threadedge.cc b/gcc/tree-ssa-threadedge.cc
> > index 931aa7479bb..a70aebd10a7 100644
> > --- a/gcc/tree-ssa-threadedge.cc
> > +++ b/gcc/tree-ssa-threadedge.cc
> > @@ -1452,7 +1452,7 @@ hybrid_jt_simplifier::compute_ranges_from_state (gimple *stmt, jt_state *state)
> >           tree op = gimple_op (stmt, i);
> >           if (op
> >               && TREE_CODE (op) == SSA_NAME
> > -             && irange::supports_type_p (TREE_TYPE (op)))
> > +             && Value_Range::supports_type_p (TREE_TYPE (op)))
> >             bitmap_set_bit (imports, SSA_NAME_VERSION (op));
> >         }
> >      }
> > diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
> > index 74277617b66..30022dac108 100644
> > --- a/gcc/tree-vrp.cc
> > +++ b/gcc/tree-vrp.cc
> > @@ -932,8 +932,8 @@ supported_types_p (value_range *vr,
> >                    tree type0,
> >                    tree type1 = NULL)
> >  {
> > -  if (!value_range::supports_type_p (type0)
> > -      || (type1 && !value_range::supports_type_p (type1)))
> > +  if (!value_range_equiv::supports_p (type0)
> > +      || (type1 && !value_range_equiv::supports_p (type1)))
> >      {
> >        vr->set_varying (type0);
> >        return false;
> > diff --git a/gcc/value-query.cc b/gcc/value-query.cc
> > index e40e358ebd4..1d7541ce34f 100644
> > --- a/gcc/value-query.cc
> > +++ b/gcc/value-query.cc
> > @@ -80,7 +80,7 @@ range_query::value_of_expr (tree expr, gimple *stmt)
> >  {
> >    tree t;
> >
> > -  if (!vrange::supports_type_p (TREE_TYPE (expr)))
> > +  if (!Value_Range::supports_type_p (TREE_TYPE (expr)))
> >      return NULL_TREE;
> >
> >    Value_Range r (TREE_TYPE (expr));
> > @@ -102,7 +102,7 @@ range_query::value_on_edge (edge e, tree expr)
> >  {
> >    tree t;
> >
> > -  if (!vrange::supports_type_p (TREE_TYPE (expr)))
> > +  if (!Value_Range::supports_type_p (TREE_TYPE (expr)))
> >      return NULL_TREE;
> >    Value_Range r (TREE_TYPE (expr));
> >    if (range_on_edge (r, e, expr))
> > @@ -128,7 +128,7 @@ range_query::value_of_stmt (gimple *stmt, tree name)
> >
> >    gcc_checking_assert (!name || name == gimple_get_lhs (stmt));
> >
> > -  if (!name || !vrange::supports_type_p (TREE_TYPE (name)))
> > +  if (!name || !Value_Range::supports_type_p (TREE_TYPE (name)))
> >      return NULL_TREE;
> >    Value_Range r (TREE_TYPE (name));
> >    if (range_of_stmt (r, stmt, name) && r.singleton_p (&t))
> > @@ -196,7 +196,7 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt)
> >    else
> >      type = TREE_TYPE (expr);
> >
> > -  if (!vrange::supports_type_p (type))
> > +  if (!Value_Range::supports_type_p (type))
> >      {
> >        r.set_undefined ();
> >        return false;
> > @@ -252,7 +252,7 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt)
> >      {
> >        range_op_handler op (TREE_CODE (expr), type);
> >        tree op0_type = TREE_TYPE (TREE_OPERAND (expr, 0));
> > -      if (op && vrange::supports_type_p (op0_type))
> > +      if (op && Value_Range::supports_type_p (op0_type))
> >         {
> >           Value_Range r0 (TREE_TYPE (TREE_OPERAND (expr, 0)));
> >           Value_Range r1 (type);
> > @@ -387,7 +387,7 @@ get_range_global (vrange &r, tree name)
> >     }
> >    else if (!POINTER_TYPE_P (type) && SSA_NAME_RANGE_INFO (name))
> >      {
> > -      gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name)));
> > +      gcc_checking_assert (irange::supports_p (TREE_TYPE (name)));
> >        get_ssa_name_range_info (as_a <irange> (r), name);
> >        if (r.undefined_p ())
> >         r.set_varying (type);
> > @@ -441,9 +441,7 @@ global_range_query global_ranges;
> >  bool
> >  global_range_query::range_of_expr (vrange &r, tree expr, gimple *stmt)
> >  {
> > -  tree type = TREE_TYPE (expr);
> > -
> > -  if (!irange::supports_type_p (type) || !gimple_range_ssa_p (expr))
> > +  if (!gimple_range_ssa_p (expr))
> >      return get_tree_range (r, expr, stmt);
> >
> >    get_range_global (r, expr);
> > diff --git a/gcc/value-range-equiv.h b/gcc/value-range-equiv.h
> > index 743ceb2b227..0a52d1372a1 100644
> > --- a/gcc/value-range-equiv.h
> > +++ b/gcc/value-range-equiv.h
> > @@ -67,6 +67,10 @@ class GTY((user)) value_range_equiv : public value_range
> >    void deep_copy (const value_range_equiv *);
> >    void dump (FILE *) const;
> >    void dump () const;
> > +  static bool supports_p (tree type)
> > +  {
> > +    return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type);
> > +  }
> >
> >   private:
> >    /* Deep-copies bitmap argument.  */
> > diff --git a/gcc/value-range.cc b/gcc/value-range.cc
> > index 429672737a8..c4bcb970094 100644
> > --- a/gcc/value-range.cc
> > +++ b/gcc/value-range.cc
> > @@ -107,6 +107,12 @@ vrange::operator== (const vrange &src) const
> >    gcc_unreachable ();
> >  }
> >
> > +bool
> > +irange::supports_type_p (tree type) const
> > +{
> > +  return supports_p (type);
> > +}
> > +
> >  // Return TRUE if R fits in THIS.
> >
> >  bool
> > @@ -140,6 +146,12 @@ unsupported_range::type () const
> >    return nullptr;
> >  }
> >
> > +bool
> > +unsupported_range::supports_type_p (tree) const
> > +{
> > +  return false;
> > +}
> > +
> >  void
> >  unsupported_range::set_undefined ()
> >  {
> > diff --git a/gcc/value-range.h b/gcc/value-range.h
> > index 5cd0e0ef76a..69cf6c304d6 100644
> > --- a/gcc/value-range.h
> > +++ b/gcc/value-range.h
> > @@ -50,6 +50,23 @@ enum value_range_discriminator
> >  };
> >
> >  // Abstract class for ranges of any of the supported types.
> > +//
> > +// To query what types ranger and the entire ecosystem can support,
> > +// use Value_Range::supports_type_p(tree type).  This is a static
> > +// method available independently of any vrange object.
> > +//
> > +// To query what a given vrange variant can support, use:
> > +//    irange::supports_p ()
> > +//    frange::supports_p ()
> > +//    etc
> > +//
> > +// To query what a range object can support, use:
> > +//    void foo (vrange &v, irange &i, frange &f)
> > +//    {
> > +//     if (v.supports_type_p (type)) ...
> > +//     if (i.supports_type_p (type)) ...
> > +//     if (f.supports_type_p (type)) ...
> > +//    }
> >
> >  class vrange
> >  {
> > @@ -58,6 +75,7 @@ class vrange
> >  public:
> >    virtual void set (tree, tree, value_range_kind = VR_RANGE) = 0;
> >    virtual tree type () const = 0;
> > +  virtual bool supports_type_p (tree type) const = 0;
> >    virtual void set_varying (tree type) = 0;
> >    virtual void set_undefined () = 0;
> >    virtual void dump (FILE * = stderr) const = 0;
> > @@ -72,8 +90,6 @@ public:
> >    virtual void set_nonnegative (tree type) = 0;
> >    virtual bool fits_p (const vrange &r) const = 0;
> >
> > -  static bool supports_type_p (tree);
> > -
> >    bool varying_p () const;
> >    bool undefined_p () const;
> >    vrange& operator= (const vrange &);
> > @@ -103,7 +119,8 @@ public:
> >    virtual void set_undefined () override;
> >
> >    // Range types.
> > -  static bool supports_type_p (tree);
> > +  static bool supports_p (tree type);
> > +  virtual bool supports_type_p (tree type) const override;
> >    virtual tree type () const override;
> >
> >    // Iteration over sub-ranges.
> > @@ -228,6 +245,7 @@ public:
> >    unsupported_range ();
> >    virtual void set (tree, tree, value_range_kind) override;
> >    virtual tree type () const override;
> > +  virtual bool supports_type_p (tree type) const override;
> >    virtual void set_varying (tree type) override;
> >    virtual void set_undefined () override;
> >    virtual void dump (FILE *) const override;
> > @@ -331,6 +349,7 @@ public:
> >    operator vrange &();
> >    operator const vrange &() const;
> >    void dump (FILE *out = stderr) const;
> > +  static bool supports_type_p (tree type);
> >
> >    // Convenience methods for vrange compatability.
> >    void set (tree min, tree max, value_range_kind kind = VR_RANGE)
> > @@ -387,7 +406,7 @@ Value_Range::init (tree type)
> >  {
> >    gcc_checking_assert (TYPE_P (type));
> >
> > -  if (irange::supports_type_p (type))
> > +  if (irange::supports_p (type))
> >      m_vrange = &m_irange;
> >    else
> >      m_vrange = &m_unsupported;
> > @@ -444,6 +463,14 @@ Value_Range::operator const vrange &() const
> >    return *m_vrange;
> >  }
> >
> > +// Return TRUE if TYPE is supported by the vrange infrastructure.
> > +
> > +inline bool
> > +Value_Range::supports_type_p (tree type)
> > +{
> > +  return irange::supports_p (type);
> > +}
> > +
> >  // Returns true for an old-school value_range as described above.
> >  inline bool
> >  irange::legacy_mode_p () const
> > @@ -580,7 +607,7 @@ irange::nonzero_p () const
> >  }
> >
> >  inline bool
> > -irange::supports_type_p (tree type)
> > +irange::supports_p (tree type)
> >  {
> >    return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type);
> >  }
> > @@ -864,12 +891,6 @@ irange::normalize_kind ()
> >      }
> >  }
> >
> > -inline bool
> > -vrange::supports_type_p (tree type)
> > -{
> > -  return irange::supports_type_p (type);
> > -}
> > -
> >  // Return the maximum value for TYPE.
> >
> >  inline tree
> > @@ -944,7 +965,7 @@ vrange_allocator::alloc (unsigned bytes)
> >  inline vrange *
> >  vrange_allocator::alloc_vrange (tree type)
> >  {
> > -  if (irange::supports_type_p (type))
> > +  if (irange::supports_p (type))
> >      return alloc_irange (2);
> >
> >    gcc_unreachable ();
> > --
> > 2.36.1
> >
>
  
Richard Biener June 28, 2022, 7:36 a.m. UTC | #3
On Mon, Jun 27, 2022 at 9:00 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>
> The conversion for loop-ch is trivial, since the range of a
> GIMPLE_COND is always an integer.

Yes - but doesn't this hint at the fact that the irange::supports_p is
useless because it checks on the type of the comparison operand
rather than the type of the comparison (boolean_type_node)?

So .. instead of replacing it, remove it?

Richard.

> OK for trunk?
>
> p.s. The loop unswitch code requires a bit more thought, since there
> are numerous range temporaries in the code that are not necessarily
> integers.
>
> On Mon, Jun 13, 2022 at 11:44 AM Richard Biener
> <richard.guenther@gmail.com> wrote:
> >
> > On Fri, Jun 3, 2022 at 9:31 AM Aldy Hernandez <aldyh@redhat.com> wrote:
> > >
> > > [I have conservatively assumed that both the loop-ch and loop-unswitch
> > > passes, which also use the ranger, only support integers and pointers.
> > > If the goal is to handle other types as well, irange::supports_p()
> > > should be Value_Range::supports_type_p(), and any uses of
> > > int_range_max should be converted to Value_Range.  I can help in the
> > > conversion if you'd like.]
> >
> > Both should also support float ranges, so yes - if you can send simple
> > patches I'll review them.
> >
> > > As discussed, this patch disambiguates the use of supports_type_p
> > > throughout, as what ranger supports is a totally different question
> > > than what a given range variant (irange, frange, etc) supports.
> > >
> > > Unfortunately we need both a static method and a virtual method, and
> > > they can't be named the same.  The uses are documented in the vrange
> > > class:
> > >
> > > +// To query what types ranger and the entire ecosystem can support,
> > > +// use Value_Range::supports_type_p(tree type).  This is a static
> > > +// method available independently of any vrange object.
> > > +//
> > > +// To query what a given vrange variant can support, use:
> > > +//    irange::supports_p ()
> > > +//    frange::supports_p ()
> > > +//    etc
> > > +//
> > > +// To query what a range object can support, use:
> > > +//    void foo (vrange &v, irange &i, frange &f)
> > > +//    {
> > > +//     if (v.supports_type_p (type)) ...
> > > +//     if (i.supports_type_p (type)) ...
> > > +//     if (f.supports_type_p (type)) ...
> > > +//    }
> > >
> > > The value_range_equiv::supports_p() method can be use to determine
> > > what legacy VRP supports, as irange::supports_p() will no longer be
> > > applicable in the evrp analyzer code base once irange and prange are
> > > split.
> > >
> > > Tested on x86-64 Linux.
> > >
> > > gcc/ChangeLog:
> > >
> > >         * gimple-range-edge.cc (gimple_outgoing_range_stmt_p): Adjust for
> > >         an object level supports_type_p for irange and a static
> > >         Value_Range::supports_type_p.
> > >         * gimple-range-fold.cc (fold_using_range::range_of_range_op): Same.
> > >         (fold_using_range::range_of_address): Same.
> > >         (fold_using_range::range_of_builtin_call): Same.
> > >         * gimple-range-fold.h (gimple_range_type): Same.
> > >         (gimple_range_ssa_p): Same.
> > >         * gimple-range-path.cc (path_range_query::internal_range_of_expr):
> > >         Same.
> > >         (path_range_query::range_of_stmt): Same.
> > >         (path_range_query::add_to_imports): Same.
> > >         * gimple-range.cc (gimple_ranger::range_on_edge): Same.
> > >         (gimple_ranger::export_global_ranges): Same.
> > >         * gimple-ssa-evrp-analyze.cc
> > >         (evrp_range_analyzer::record_ranges_from_phis):  Same.
> > >         * range-op.cc (range_operator::wi_fold): Same.
> > >         (range_operator::fold_range): Same.
> > >         * tree-ssa-loop-ch.cc (entry_loop_condition_is_static): Same.
> > >         * tree-ssa-loop-unswitch.cc (struct unswitch_predicate): Same.
> > >         (evaluate_control_stmt_using_entry_checks): Same.
> > >         * tree-ssa-threadedge.cc
> > >         (hybrid_jt_simplifier::compute_ranges_from_state): Same.
> > >         * tree-vrp.cc (supported_types_p): Same.
> > >         * value-query.cc (range_query::value_of_expr): Same.
> > >         (range_query::value_on_edge): Same.
> > >         (range_query::value_of_stmt): Same.
> > >         (range_query::get_tree_range): Same.
> > >         (get_range_global): Same.
> > >         (global_range_query::range_of_expr): Same.
> > >         * value-range-equiv.h (class value_range_equiv): Same.
> > >         * value-range.cc (irange::supports_type_p): Same.
> > >         (unsupported_range::supports_type_p): Same.
> > >         * value-range.h (enum value_range_discriminator): Same.
> > >         (Value_Range::init): Same.
> > >         (Value_Range::supports_type_p): Same.
> > >         (irange::supports_type_p): Same.
> > >         (irange::supports_p): Same.
> > >         (vrange::supports_type_p): Same.
> > >         (vrange_allocator::alloc_vrange): Same.
> > > ---
> > >  gcc/gimple-range-edge.cc       |  3 +--
> > >  gcc/gimple-range-fold.cc       |  5 ++--
> > >  gcc/gimple-range-fold.h        |  4 +--
> > >  gcc/gimple-range-path.cc       |  6 ++---
> > >  gcc/gimple-range.cc            |  4 +--
> > >  gcc/gimple-ssa-evrp-analyze.cc |  2 +-
> > >  gcc/range-op.cc                |  4 +--
> > >  gcc/tree-ssa-loop-ch.cc        |  2 +-
> > >  gcc/tree-ssa-loop-unswitch.cc  |  6 ++---
> > >  gcc/tree-ssa-threadedge.cc     |  2 +-
> > >  gcc/tree-vrp.cc                |  4 +--
> > >  gcc/value-query.cc             | 16 ++++++------
> > >  gcc/value-range-equiv.h        |  4 +++
> > >  gcc/value-range.cc             | 12 +++++++++
> > >  gcc/value-range.h              | 45 +++++++++++++++++++++++++---------
> > >  15 files changed, 76 insertions(+), 43 deletions(-)
> > >
> > > diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
> > > index 6fe33408f7e..03a804ac2be 100644
> > > --- a/gcc/gimple-range-edge.cc
> > > +++ b/gcc/gimple-range-edge.cc
> > > @@ -44,8 +44,7 @@ gimple_outgoing_range_stmt_p (basic_block bb)
> > >        gimple *s = gsi_stmt (gsi);
> > >        if (is_a<gcond *> (s) && range_op_handler (s))
> > >         return gsi_stmt (gsi);
> > > -      gswitch *sw = dyn_cast<gswitch *> (s);
> > > -      if (sw && irange::supports_type_p (TREE_TYPE (gimple_switch_index (sw))))
> > > +      if (is_a <gswitch *> (s))
> > >         return gsi_stmt (gsi);
> > >      }
> > >    return NULL;
> > > diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
> > > index c1a801668c4..2a8c66e0c05 100644
> > > --- a/gcc/gimple-range-fold.cc
> > > +++ b/gcc/gimple-range-fold.cc
> > > @@ -632,7 +632,7 @@ fold_using_range::range_of_range_op (vrange &r, gimple *s, fur_source &src)
> > >             }
> > >           // Fold range, and register any dependency if available.
> > >           handler.fold_range (r, type, range1, range2, rel);
> > > -         if (irange::supports_type_p (type))
> > > +         if (irange::supports_p (type))
> > >             relation_fold_and_or (as_a <irange> (r), s, src);
> > >           if (lhs)
> > >             {
> > > @@ -709,7 +709,6 @@ fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src)
> > >        tree lhs = gimple_get_lhs (stmt);
> > >        if (lhs && gimple_range_ssa_p (ssa) && src.gori ())
> > >         src.gori ()->register_dependency (lhs, ssa);
> > > -      gcc_checking_assert (irange::supports_type_p (TREE_TYPE (ssa)));
> > >        src.get_operand (r, ssa);
> > >        range_cast (r, TREE_TYPE (gimple_assign_rhs1 (stmt)));
> > >
> > > @@ -985,7 +984,7 @@ fold_using_range::range_of_builtin_call (vrange &r, gcall *call,
> > >    tree type = gimple_range_type (call);
> > >    gcc_checking_assert (type);
> > >
> > > -  if (irange::supports_type_p (type))
> > > +  if (irange::supports_p (type))
> > >      return range_of_builtin_int_call (as_a <irange> (r), call, src);
> > >
> > >    return false;
> > > diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
> > > index df24280ee40..fbf66275f74 100644
> > > --- a/gcc/gimple-range-fold.h
> > > +++ b/gcc/gimple-range-fold.h
> > > @@ -66,7 +66,7 @@ gimple_range_type (const gimple *s)
> > >             type = TREE_TYPE (type);
> > >         }
> > >      }
> > > -  if (type && vrange::supports_type_p (type))
> > > +  if (type && Value_Range::supports_type_p (type))
> > >      return type;
> > >    return NULL_TREE;
> > >  }
> > > @@ -79,7 +79,7 @@ gimple_range_ssa_p (tree exp)
> > >    if (exp && TREE_CODE (exp) == SSA_NAME &&
> > >        !SSA_NAME_IS_VIRTUAL_OPERAND (exp) &&
> > >        !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) &&
> > > -      vrange::supports_type_p (TREE_TYPE (exp)))
> > > +      Value_Range::supports_type_p (TREE_TYPE (exp)))
> > >      return exp;
> > >    return NULL_TREE;
> > >  }
> > > diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
> > > index f8ae6fb9ffb..e1b9683c1e4 100644
> > > --- a/gcc/gimple-range-path.cc
> > > +++ b/gcc/gimple-range-path.cc
> > > @@ -192,7 +192,7 @@ path_range_query::range_on_path_entry (vrange &r, tree name)
> > >  bool
> > >  path_range_query::internal_range_of_expr (vrange &r, tree name, gimple *stmt)
> > >  {
> > > -  if (!vrange::supports_type_p (TREE_TYPE (name)))
> > > +  if (!r.supports_type_p (TREE_TYPE (name)))
> > >      return false;
> > >
> > >    if (get_cache (r, name))
> > > @@ -548,7 +548,7 @@ bool
> > >  path_range_query::add_to_imports (tree name, bitmap imports)
> > >  {
> > >    if (TREE_CODE (name) == SSA_NAME
> > > -      && vrange::supports_type_p (TREE_TYPE (name)))
> > > +      && Value_Range::supports_type_p (TREE_TYPE (name)))
> > >      return bitmap_set_bit (imports, SSA_NAME_VERSION (name));
> > >    return false;
> > >  }
> > > @@ -764,7 +764,7 @@ path_range_query::range_of_stmt (vrange &r, gimple *stmt, tree)
> > >  {
> > >    tree type = gimple_range_type (stmt);
> > >
> > > -  if (!type || !vrange::supports_type_p (type))
> > > +  if (!type || !r.supports_type_p (type))
> > >      return false;
> > >
> > >    // If resolving unknowns, fold the statement making use of any
> > > diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
> > > index 12da16841c2..67dafb2a2c0 100644
> > > --- a/gcc/gimple-range.cc
> > > +++ b/gcc/gimple-range.cc
> > > @@ -201,7 +201,7 @@ bool
> > >  gimple_ranger::range_on_edge (vrange &r, edge e, tree name)
> > >  {
> > >    Value_Range edge_range (TREE_TYPE (name));
> > > -  gcc_checking_assert (vrange::supports_type_p (TREE_TYPE (name)));
> > > +  gcc_checking_assert (r.supports_type_p (TREE_TYPE (name)));
> > >
> > >    // Do not process values along abnormal edges.
> > >    if (e->flags & EDGE_ABNORMAL)
> > > @@ -514,7 +514,7 @@ gimple_ranger::export_global_ranges ()
> > >               print_header = false;
> > >             }
> > >
> > > -         if (!irange::supports_type_p (TREE_TYPE (name)))
> > > +         if (!irange::supports_p (TREE_TYPE (name)))
> > >             continue;
> > >
> > >           vrange &v = r;
> > > diff --git a/gcc/gimple-ssa-evrp-analyze.cc b/gcc/gimple-ssa-evrp-analyze.cc
> > > index 16e5a75b1db..82142db7976 100644
> > > --- a/gcc/gimple-ssa-evrp-analyze.cc
> > > +++ b/gcc/gimple-ssa-evrp-analyze.cc
> > > @@ -255,7 +255,7 @@ evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
> > >
> > >        /* Skips floats and other things we can't represent in a
> > >          range.  */
> > > -      if (!value_range::supports_type_p (TREE_TYPE (lhs)))
> > > +      if (!value_range_equiv::supports_p (TREE_TYPE (lhs)))
> > >         continue;
> > >
> > >        value_range_equiv vr_result;
> > > diff --git a/gcc/range-op.cc b/gcc/range-op.cc
> > > index 028b4b7237c..5150c6021b8 100644
> > > --- a/gcc/range-op.cc
> > > +++ b/gcc/range-op.cc
> > > @@ -111,7 +111,7 @@ range_operator::wi_fold (irange &r, tree type,
> > >                          const wide_int &rh_lb ATTRIBUTE_UNUSED,
> > >                          const wide_int &rh_ub ATTRIBUTE_UNUSED) const
> > >  {
> > > -  gcc_checking_assert (irange::supports_type_p (type));
> > > +  gcc_checking_assert (r.supports_type_p (type));
> > >    r.set_varying (type);
> > >  }
> > >
> > > @@ -181,7 +181,7 @@ range_operator::fold_range (irange &r, tree type,
> > >                             const irange &rh,
> > >                             relation_kind rel) const
> > >  {
> > > -  gcc_checking_assert (irange::supports_type_p (type));
> > > +  gcc_checking_assert (r.supports_type_p (type));
> > >    if (empty_range_varying (r, type, lh, rh))
> > >      return true;
> > >
> > > diff --git a/gcc/tree-ssa-loop-ch.cc b/gcc/tree-ssa-loop-ch.cc
> > > index 2f5a390404c..26d96c0c21a 100644
> > > --- a/gcc/tree-ssa-loop-ch.cc
> > > +++ b/gcc/tree-ssa-loop-ch.cc
> > > @@ -55,7 +55,7 @@ entry_loop_condition_is_static (class loop *l, path_range_query *query)
> > >    gcond *last = safe_dyn_cast <gcond *> (last_stmt (e->dest));
> > >
> > >    if (!last
> > > -      || !irange::supports_type_p (TREE_TYPE (gimple_cond_lhs (last))))
> > > +      || !irange::supports_p (TREE_TYPE (gimple_cond_lhs (last))))
> > >      return false;
> > >
> > >    edge true_e, false_e;
> > > diff --git a/gcc/tree-ssa-loop-unswitch.cc b/gcc/tree-ssa-loop-unswitch.cc
> > > index ad1d05ccdff..95ccc0b7b47 100644
> > > --- a/gcc/tree-ssa-loop-unswitch.cc
> > > +++ b/gcc/tree-ssa-loop-unswitch.cc
> > > @@ -113,7 +113,7 @@ struct unswitch_predicate
> > >        true_range (edge_range), edge_index (edge_index_), switch_p (true)
> > >    {
> > >      gcc_assert (!(e->flags & (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE))
> > > -               && irange::supports_type_p (TREE_TYPE (lhs)));
> > > +               && irange::supports_p (TREE_TYPE (lhs)));
> > >      false_range = true_range;
> > >      if (!false_range.varying_p ()
> > >         && !false_range.undefined_p ())
> > > @@ -134,7 +134,7 @@ struct unswitch_predicate
> > >      tree rhs = gimple_cond_rhs (stmt);
> > >      enum tree_code code = gimple_cond_code (stmt);
> > >      condition = build2 (code, boolean_type_node, lhs, rhs);
> > > -    if (irange::supports_type_p (TREE_TYPE (lhs)))
> > > +    if (irange::supports_p (TREE_TYPE (lhs)))
> > >        {
> > >         auto range_op = range_op_handler (code, TREE_TYPE (lhs));
> > >         int_range<2> rhs_range (TREE_TYPE (rhs));
> > > @@ -646,7 +646,7 @@ evaluate_control_stmt_using_entry_checks (gimple *stmt,
> > >                               TREE_OPERAND (last_predicate->condition, 1)))
> > >         return true_edge ? boolean_true_node : boolean_false_node;
> > >        /* Else try ranger if it supports LHS.  */
> > > -      else if (irange::supports_type_p (TREE_TYPE (lhs)))
> > > +      else if (irange::supports_p (TREE_TYPE (lhs)))
> > >         {
> > >           int_range<2> r;
> > >           int_range_max path_range;
> > > diff --git a/gcc/tree-ssa-threadedge.cc b/gcc/tree-ssa-threadedge.cc
> > > index 931aa7479bb..a70aebd10a7 100644
> > > --- a/gcc/tree-ssa-threadedge.cc
> > > +++ b/gcc/tree-ssa-threadedge.cc
> > > @@ -1452,7 +1452,7 @@ hybrid_jt_simplifier::compute_ranges_from_state (gimple *stmt, jt_state *state)
> > >           tree op = gimple_op (stmt, i);
> > >           if (op
> > >               && TREE_CODE (op) == SSA_NAME
> > > -             && irange::supports_type_p (TREE_TYPE (op)))
> > > +             && Value_Range::supports_type_p (TREE_TYPE (op)))
> > >             bitmap_set_bit (imports, SSA_NAME_VERSION (op));
> > >         }
> > >      }
> > > diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
> > > index 74277617b66..30022dac108 100644
> > > --- a/gcc/tree-vrp.cc
> > > +++ b/gcc/tree-vrp.cc
> > > @@ -932,8 +932,8 @@ supported_types_p (value_range *vr,
> > >                    tree type0,
> > >                    tree type1 = NULL)
> > >  {
> > > -  if (!value_range::supports_type_p (type0)
> > > -      || (type1 && !value_range::supports_type_p (type1)))
> > > +  if (!value_range_equiv::supports_p (type0)
> > > +      || (type1 && !value_range_equiv::supports_p (type1)))
> > >      {
> > >        vr->set_varying (type0);
> > >        return false;
> > > diff --git a/gcc/value-query.cc b/gcc/value-query.cc
> > > index e40e358ebd4..1d7541ce34f 100644
> > > --- a/gcc/value-query.cc
> > > +++ b/gcc/value-query.cc
> > > @@ -80,7 +80,7 @@ range_query::value_of_expr (tree expr, gimple *stmt)
> > >  {
> > >    tree t;
> > >
> > > -  if (!vrange::supports_type_p (TREE_TYPE (expr)))
> > > +  if (!Value_Range::supports_type_p (TREE_TYPE (expr)))
> > >      return NULL_TREE;
> > >
> > >    Value_Range r (TREE_TYPE (expr));
> > > @@ -102,7 +102,7 @@ range_query::value_on_edge (edge e, tree expr)
> > >  {
> > >    tree t;
> > >
> > > -  if (!vrange::supports_type_p (TREE_TYPE (expr)))
> > > +  if (!Value_Range::supports_type_p (TREE_TYPE (expr)))
> > >      return NULL_TREE;
> > >    Value_Range r (TREE_TYPE (expr));
> > >    if (range_on_edge (r, e, expr))
> > > @@ -128,7 +128,7 @@ range_query::value_of_stmt (gimple *stmt, tree name)
> > >
> > >    gcc_checking_assert (!name || name == gimple_get_lhs (stmt));
> > >
> > > -  if (!name || !vrange::supports_type_p (TREE_TYPE (name)))
> > > +  if (!name || !Value_Range::supports_type_p (TREE_TYPE (name)))
> > >      return NULL_TREE;
> > >    Value_Range r (TREE_TYPE (name));
> > >    if (range_of_stmt (r, stmt, name) && r.singleton_p (&t))
> > > @@ -196,7 +196,7 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt)
> > >    else
> > >      type = TREE_TYPE (expr);
> > >
> > > -  if (!vrange::supports_type_p (type))
> > > +  if (!Value_Range::supports_type_p (type))
> > >      {
> > >        r.set_undefined ();
> > >        return false;
> > > @@ -252,7 +252,7 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt)
> > >      {
> > >        range_op_handler op (TREE_CODE (expr), type);
> > >        tree op0_type = TREE_TYPE (TREE_OPERAND (expr, 0));
> > > -      if (op && vrange::supports_type_p (op0_type))
> > > +      if (op && Value_Range::supports_type_p (op0_type))
> > >         {
> > >           Value_Range r0 (TREE_TYPE (TREE_OPERAND (expr, 0)));
> > >           Value_Range r1 (type);
> > > @@ -387,7 +387,7 @@ get_range_global (vrange &r, tree name)
> > >     }
> > >    else if (!POINTER_TYPE_P (type) && SSA_NAME_RANGE_INFO (name))
> > >      {
> > > -      gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name)));
> > > +      gcc_checking_assert (irange::supports_p (TREE_TYPE (name)));
> > >        get_ssa_name_range_info (as_a <irange> (r), name);
> > >        if (r.undefined_p ())
> > >         r.set_varying (type);
> > > @@ -441,9 +441,7 @@ global_range_query global_ranges;
> > >  bool
> > >  global_range_query::range_of_expr (vrange &r, tree expr, gimple *stmt)
> > >  {
> > > -  tree type = TREE_TYPE (expr);
> > > -
> > > -  if (!irange::supports_type_p (type) || !gimple_range_ssa_p (expr))
> > > +  if (!gimple_range_ssa_p (expr))
> > >      return get_tree_range (r, expr, stmt);
> > >
> > >    get_range_global (r, expr);
> > > diff --git a/gcc/value-range-equiv.h b/gcc/value-range-equiv.h
> > > index 743ceb2b227..0a52d1372a1 100644
> > > --- a/gcc/value-range-equiv.h
> > > +++ b/gcc/value-range-equiv.h
> > > @@ -67,6 +67,10 @@ class GTY((user)) value_range_equiv : public value_range
> > >    void deep_copy (const value_range_equiv *);
> > >    void dump (FILE *) const;
> > >    void dump () const;
> > > +  static bool supports_p (tree type)
> > > +  {
> > > +    return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type);
> > > +  }
> > >
> > >   private:
> > >    /* Deep-copies bitmap argument.  */
> > > diff --git a/gcc/value-range.cc b/gcc/value-range.cc
> > > index 429672737a8..c4bcb970094 100644
> > > --- a/gcc/value-range.cc
> > > +++ b/gcc/value-range.cc
> > > @@ -107,6 +107,12 @@ vrange::operator== (const vrange &src) const
> > >    gcc_unreachable ();
> > >  }
> > >
> > > +bool
> > > +irange::supports_type_p (tree type) const
> > > +{
> > > +  return supports_p (type);
> > > +}
> > > +
> > >  // Return TRUE if R fits in THIS.
> > >
> > >  bool
> > > @@ -140,6 +146,12 @@ unsupported_range::type () const
> > >    return nullptr;
> > >  }
> > >
> > > +bool
> > > +unsupported_range::supports_type_p (tree) const
> > > +{
> > > +  return false;
> > > +}
> > > +
> > >  void
> > >  unsupported_range::set_undefined ()
> > >  {
> > > diff --git a/gcc/value-range.h b/gcc/value-range.h
> > > index 5cd0e0ef76a..69cf6c304d6 100644
> > > --- a/gcc/value-range.h
> > > +++ b/gcc/value-range.h
> > > @@ -50,6 +50,23 @@ enum value_range_discriminator
> > >  };
> > >
> > >  // Abstract class for ranges of any of the supported types.
> > > +//
> > > +// To query what types ranger and the entire ecosystem can support,
> > > +// use Value_Range::supports_type_p(tree type).  This is a static
> > > +// method available independently of any vrange object.
> > > +//
> > > +// To query what a given vrange variant can support, use:
> > > +//    irange::supports_p ()
> > > +//    frange::supports_p ()
> > > +//    etc
> > > +//
> > > +// To query what a range object can support, use:
> > > +//    void foo (vrange &v, irange &i, frange &f)
> > > +//    {
> > > +//     if (v.supports_type_p (type)) ...
> > > +//     if (i.supports_type_p (type)) ...
> > > +//     if (f.supports_type_p (type)) ...
> > > +//    }
> > >
> > >  class vrange
> > >  {
> > > @@ -58,6 +75,7 @@ class vrange
> > >  public:
> > >    virtual void set (tree, tree, value_range_kind = VR_RANGE) = 0;
> > >    virtual tree type () const = 0;
> > > +  virtual bool supports_type_p (tree type) const = 0;
> > >    virtual void set_varying (tree type) = 0;
> > >    virtual void set_undefined () = 0;
> > >    virtual void dump (FILE * = stderr) const = 0;
> > > @@ -72,8 +90,6 @@ public:
> > >    virtual void set_nonnegative (tree type) = 0;
> > >    virtual bool fits_p (const vrange &r) const = 0;
> > >
> > > -  static bool supports_type_p (tree);
> > > -
> > >    bool varying_p () const;
> > >    bool undefined_p () const;
> > >    vrange& operator= (const vrange &);
> > > @@ -103,7 +119,8 @@ public:
> > >    virtual void set_undefined () override;
> > >
> > >    // Range types.
> > > -  static bool supports_type_p (tree);
> > > +  static bool supports_p (tree type);
> > > +  virtual bool supports_type_p (tree type) const override;
> > >    virtual tree type () const override;
> > >
> > >    // Iteration over sub-ranges.
> > > @@ -228,6 +245,7 @@ public:
> > >    unsupported_range ();
> > >    virtual void set (tree, tree, value_range_kind) override;
> > >    virtual tree type () const override;
> > > +  virtual bool supports_type_p (tree type) const override;
> > >    virtual void set_varying (tree type) override;
> > >    virtual void set_undefined () override;
> > >    virtual void dump (FILE *) const override;
> > > @@ -331,6 +349,7 @@ public:
> > >    operator vrange &();
> > >    operator const vrange &() const;
> > >    void dump (FILE *out = stderr) const;
> > > +  static bool supports_type_p (tree type);
> > >
> > >    // Convenience methods for vrange compatability.
> > >    void set (tree min, tree max, value_range_kind kind = VR_RANGE)
> > > @@ -387,7 +406,7 @@ Value_Range::init (tree type)
> > >  {
> > >    gcc_checking_assert (TYPE_P (type));
> > >
> > > -  if (irange::supports_type_p (type))
> > > +  if (irange::supports_p (type))
> > >      m_vrange = &m_irange;
> > >    else
> > >      m_vrange = &m_unsupported;
> > > @@ -444,6 +463,14 @@ Value_Range::operator const vrange &() const
> > >    return *m_vrange;
> > >  }
> > >
> > > +// Return TRUE if TYPE is supported by the vrange infrastructure.
> > > +
> > > +inline bool
> > > +Value_Range::supports_type_p (tree type)
> > > +{
> > > +  return irange::supports_p (type);
> > > +}
> > > +
> > >  // Returns true for an old-school value_range as described above.
> > >  inline bool
> > >  irange::legacy_mode_p () const
> > > @@ -580,7 +607,7 @@ irange::nonzero_p () const
> > >  }
> > >
> > >  inline bool
> > > -irange::supports_type_p (tree type)
> > > +irange::supports_p (tree type)
> > >  {
> > >    return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type);
> > >  }
> > > @@ -864,12 +891,6 @@ irange::normalize_kind ()
> > >      }
> > >  }
> > >
> > > -inline bool
> > > -vrange::supports_type_p (tree type)
> > > -{
> > > -  return irange::supports_type_p (type);
> > > -}
> > > -
> > >  // Return the maximum value for TYPE.
> > >
> > >  inline tree
> > > @@ -944,7 +965,7 @@ vrange_allocator::alloc (unsigned bytes)
> > >  inline vrange *
> > >  vrange_allocator::alloc_vrange (tree type)
> > >  {
> > > -  if (irange::supports_type_p (type))
> > > +  if (irange::supports_p (type))
> > >      return alloc_irange (2);
> > >
> > >    gcc_unreachable ();
> > > --
> > > 2.36.1
> > >
> >
  
Aldy Hernandez June 28, 2022, 9:33 a.m. UTC | #4
On Tue, Jun 28, 2022 at 9:36 AM Richard Biener
<richard.guenther@gmail.com> wrote:
>
> On Mon, Jun 27, 2022 at 9:00 PM Aldy Hernandez <aldyh@redhat.com> wrote:
> >
> > The conversion for loop-ch is trivial, since the range of a
> > GIMPLE_COND is always an integer.
>
> Yes - but doesn't this hint at the fact that the irange::supports_p is
> useless because it checks on the type of the comparison operand
> rather than the type of the comparison (boolean_type_node)?
>
> So .. instead of replacing it, remove it?

You're absolutely right.

OK pending tests?

Aldy
  
Richard Biener June 28, 2022, 10:15 a.m. UTC | #5
On Tue, Jun 28, 2022 at 11:33 AM Aldy Hernandez <aldyh@redhat.com> wrote:
>
> On Tue, Jun 28, 2022 at 9:36 AM Richard Biener
> <richard.guenther@gmail.com> wrote:
> >
> > On Mon, Jun 27, 2022 at 9:00 PM Aldy Hernandez <aldyh@redhat.com> wrote:
> > >
> > > The conversion for loop-ch is trivial, since the range of a
> > > GIMPLE_COND is always an integer.
> >
> > Yes - but doesn't this hint at the fact that the irange::supports_p is
> > useless because it checks on the type of the comparison operand
> > rather than the type of the comparison (boolean_type_node)?
> >
> > So .. instead of replacing it, remove it?
>
> You're absolutely right.
>
> OK pending tests?

Yes.

> Aldy
  

Patch

diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
index 6fe33408f7e..03a804ac2be 100644
--- a/gcc/gimple-range-edge.cc
+++ b/gcc/gimple-range-edge.cc
@@ -44,8 +44,7 @@  gimple_outgoing_range_stmt_p (basic_block bb)
       gimple *s = gsi_stmt (gsi);
       if (is_a<gcond *> (s) && range_op_handler (s))
 	return gsi_stmt (gsi);
-      gswitch *sw = dyn_cast<gswitch *> (s);
-      if (sw && irange::supports_type_p (TREE_TYPE (gimple_switch_index (sw))))
+      if (is_a <gswitch *> (s))
 	return gsi_stmt (gsi);
     }
   return NULL;
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index c1a801668c4..2a8c66e0c05 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -632,7 +632,7 @@  fold_using_range::range_of_range_op (vrange &r, gimple *s, fur_source &src)
 	    }
 	  // Fold range, and register any dependency if available.
 	  handler.fold_range (r, type, range1, range2, rel);
-	  if (irange::supports_type_p (type))
+	  if (irange::supports_p (type))
 	    relation_fold_and_or (as_a <irange> (r), s, src);
 	  if (lhs)
 	    {
@@ -709,7 +709,6 @@  fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src)
       tree lhs = gimple_get_lhs (stmt);
       if (lhs && gimple_range_ssa_p (ssa) && src.gori ())
 	src.gori ()->register_dependency (lhs, ssa);
-      gcc_checking_assert (irange::supports_type_p (TREE_TYPE (ssa)));
       src.get_operand (r, ssa);
       range_cast (r, TREE_TYPE (gimple_assign_rhs1 (stmt)));
 
@@ -985,7 +984,7 @@  fold_using_range::range_of_builtin_call (vrange &r, gcall *call,
   tree type = gimple_range_type (call);
   gcc_checking_assert (type);
 
-  if (irange::supports_type_p (type))
+  if (irange::supports_p (type))
     return range_of_builtin_int_call (as_a <irange> (r), call, src);
 
   return false;
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index df24280ee40..fbf66275f74 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -66,7 +66,7 @@  gimple_range_type (const gimple *s)
 	    type = TREE_TYPE (type);
 	}
     }
-  if (type && vrange::supports_type_p (type))
+  if (type && Value_Range::supports_type_p (type))
     return type;
   return NULL_TREE;
 }
@@ -79,7 +79,7 @@  gimple_range_ssa_p (tree exp)
   if (exp && TREE_CODE (exp) == SSA_NAME &&
       !SSA_NAME_IS_VIRTUAL_OPERAND (exp) &&
       !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) &&
-      vrange::supports_type_p (TREE_TYPE (exp)))
+      Value_Range::supports_type_p (TREE_TYPE (exp)))
     return exp;
   return NULL_TREE;
 }
diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
index f8ae6fb9ffb..e1b9683c1e4 100644
--- a/gcc/gimple-range-path.cc
+++ b/gcc/gimple-range-path.cc
@@ -192,7 +192,7 @@  path_range_query::range_on_path_entry (vrange &r, tree name)
 bool
 path_range_query::internal_range_of_expr (vrange &r, tree name, gimple *stmt)
 {
-  if (!vrange::supports_type_p (TREE_TYPE (name)))
+  if (!r.supports_type_p (TREE_TYPE (name)))
     return false;
 
   if (get_cache (r, name))
@@ -548,7 +548,7 @@  bool
 path_range_query::add_to_imports (tree name, bitmap imports)
 {
   if (TREE_CODE (name) == SSA_NAME
-      && vrange::supports_type_p (TREE_TYPE (name)))
+      && Value_Range::supports_type_p (TREE_TYPE (name)))
     return bitmap_set_bit (imports, SSA_NAME_VERSION (name));
   return false;
 }
@@ -764,7 +764,7 @@  path_range_query::range_of_stmt (vrange &r, gimple *stmt, tree)
 {
   tree type = gimple_range_type (stmt);
 
-  if (!type || !vrange::supports_type_p (type))
+  if (!type || !r.supports_type_p (type))
     return false;
 
   // If resolving unknowns, fold the statement making use of any
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index 12da16841c2..67dafb2a2c0 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -201,7 +201,7 @@  bool
 gimple_ranger::range_on_edge (vrange &r, edge e, tree name)
 {
   Value_Range edge_range (TREE_TYPE (name));
-  gcc_checking_assert (vrange::supports_type_p (TREE_TYPE (name)));
+  gcc_checking_assert (r.supports_type_p (TREE_TYPE (name)));
 
   // Do not process values along abnormal edges.
   if (e->flags & EDGE_ABNORMAL)
@@ -514,7 +514,7 @@  gimple_ranger::export_global_ranges ()
 	      print_header = false;
 	    }
 
-	  if (!irange::supports_type_p (TREE_TYPE (name)))
+	  if (!irange::supports_p (TREE_TYPE (name)))
 	    continue;
 
 	  vrange &v = r;
diff --git a/gcc/gimple-ssa-evrp-analyze.cc b/gcc/gimple-ssa-evrp-analyze.cc
index 16e5a75b1db..82142db7976 100644
--- a/gcc/gimple-ssa-evrp-analyze.cc
+++ b/gcc/gimple-ssa-evrp-analyze.cc
@@ -255,7 +255,7 @@  evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
 
       /* Skips floats and other things we can't represent in a
 	 range.  */
-      if (!value_range::supports_type_p (TREE_TYPE (lhs)))
+      if (!value_range_equiv::supports_p (TREE_TYPE (lhs)))
 	continue;
 
       value_range_equiv vr_result;
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 028b4b7237c..5150c6021b8 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -111,7 +111,7 @@  range_operator::wi_fold (irange &r, tree type,
 			 const wide_int &rh_lb ATTRIBUTE_UNUSED,
 			 const wide_int &rh_ub ATTRIBUTE_UNUSED) const
 {
-  gcc_checking_assert (irange::supports_type_p (type));
+  gcc_checking_assert (r.supports_type_p (type));
   r.set_varying (type);
 }
 
@@ -181,7 +181,7 @@  range_operator::fold_range (irange &r, tree type,
 			    const irange &rh,
 			    relation_kind rel) const
 {
-  gcc_checking_assert (irange::supports_type_p (type));
+  gcc_checking_assert (r.supports_type_p (type));
   if (empty_range_varying (r, type, lh, rh))
     return true;
 
diff --git a/gcc/tree-ssa-loop-ch.cc b/gcc/tree-ssa-loop-ch.cc
index 2f5a390404c..26d96c0c21a 100644
--- a/gcc/tree-ssa-loop-ch.cc
+++ b/gcc/tree-ssa-loop-ch.cc
@@ -55,7 +55,7 @@  entry_loop_condition_is_static (class loop *l, path_range_query *query)
   gcond *last = safe_dyn_cast <gcond *> (last_stmt (e->dest));
 
   if (!last
-      || !irange::supports_type_p (TREE_TYPE (gimple_cond_lhs (last))))
+      || !irange::supports_p (TREE_TYPE (gimple_cond_lhs (last))))
     return false;
 
   edge true_e, false_e;
diff --git a/gcc/tree-ssa-loop-unswitch.cc b/gcc/tree-ssa-loop-unswitch.cc
index ad1d05ccdff..95ccc0b7b47 100644
--- a/gcc/tree-ssa-loop-unswitch.cc
+++ b/gcc/tree-ssa-loop-unswitch.cc
@@ -113,7 +113,7 @@  struct unswitch_predicate
       true_range (edge_range), edge_index (edge_index_), switch_p (true)
   {
     gcc_assert (!(e->flags & (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE))
-		&& irange::supports_type_p (TREE_TYPE (lhs)));
+		&& irange::supports_p (TREE_TYPE (lhs)));
     false_range = true_range;
     if (!false_range.varying_p ()
 	&& !false_range.undefined_p ())
@@ -134,7 +134,7 @@  struct unswitch_predicate
     tree rhs = gimple_cond_rhs (stmt);
     enum tree_code code = gimple_cond_code (stmt);
     condition = build2 (code, boolean_type_node, lhs, rhs);
-    if (irange::supports_type_p (TREE_TYPE (lhs)))
+    if (irange::supports_p (TREE_TYPE (lhs)))
       {
 	auto range_op = range_op_handler (code, TREE_TYPE (lhs));
 	int_range<2> rhs_range (TREE_TYPE (rhs));
@@ -646,7 +646,7 @@  evaluate_control_stmt_using_entry_checks (gimple *stmt,
 			      TREE_OPERAND (last_predicate->condition, 1)))
 	return true_edge ? boolean_true_node : boolean_false_node;
       /* Else try ranger if it supports LHS.  */
-      else if (irange::supports_type_p (TREE_TYPE (lhs)))
+      else if (irange::supports_p (TREE_TYPE (lhs)))
 	{
 	  int_range<2> r;
 	  int_range_max path_range;
diff --git a/gcc/tree-ssa-threadedge.cc b/gcc/tree-ssa-threadedge.cc
index 931aa7479bb..a70aebd10a7 100644
--- a/gcc/tree-ssa-threadedge.cc
+++ b/gcc/tree-ssa-threadedge.cc
@@ -1452,7 +1452,7 @@  hybrid_jt_simplifier::compute_ranges_from_state (gimple *stmt, jt_state *state)
 	  tree op = gimple_op (stmt, i);
 	  if (op
 	      && TREE_CODE (op) == SSA_NAME
-	      && irange::supports_type_p (TREE_TYPE (op)))
+	      && Value_Range::supports_type_p (TREE_TYPE (op)))
 	    bitmap_set_bit (imports, SSA_NAME_VERSION (op));
 	}
     }
diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
index 74277617b66..30022dac108 100644
--- a/gcc/tree-vrp.cc
+++ b/gcc/tree-vrp.cc
@@ -932,8 +932,8 @@  supported_types_p (value_range *vr,
 		   tree type0,
 		   tree type1 = NULL)
 {
-  if (!value_range::supports_type_p (type0)
-      || (type1 && !value_range::supports_type_p (type1)))
+  if (!value_range_equiv::supports_p (type0)
+      || (type1 && !value_range_equiv::supports_p (type1)))
     {
       vr->set_varying (type0);
       return false;
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index e40e358ebd4..1d7541ce34f 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -80,7 +80,7 @@  range_query::value_of_expr (tree expr, gimple *stmt)
 {
   tree t;
 
-  if (!vrange::supports_type_p (TREE_TYPE (expr)))
+  if (!Value_Range::supports_type_p (TREE_TYPE (expr)))
     return NULL_TREE;
 
   Value_Range r (TREE_TYPE (expr));
@@ -102,7 +102,7 @@  range_query::value_on_edge (edge e, tree expr)
 {
   tree t;
 
-  if (!vrange::supports_type_p (TREE_TYPE (expr)))
+  if (!Value_Range::supports_type_p (TREE_TYPE (expr)))
     return NULL_TREE;
   Value_Range r (TREE_TYPE (expr));
   if (range_on_edge (r, e, expr))
@@ -128,7 +128,7 @@  range_query::value_of_stmt (gimple *stmt, tree name)
 
   gcc_checking_assert (!name || name == gimple_get_lhs (stmt));
 
-  if (!name || !vrange::supports_type_p (TREE_TYPE (name)))
+  if (!name || !Value_Range::supports_type_p (TREE_TYPE (name)))
     return NULL_TREE;
   Value_Range r (TREE_TYPE (name));
   if (range_of_stmt (r, stmt, name) && r.singleton_p (&t))
@@ -196,7 +196,7 @@  range_query::get_tree_range (vrange &r, tree expr, gimple *stmt)
   else
     type = TREE_TYPE (expr);
 
-  if (!vrange::supports_type_p (type))
+  if (!Value_Range::supports_type_p (type))
     {
       r.set_undefined ();
       return false;
@@ -252,7 +252,7 @@  range_query::get_tree_range (vrange &r, tree expr, gimple *stmt)
     {
       range_op_handler op (TREE_CODE (expr), type);
       tree op0_type = TREE_TYPE (TREE_OPERAND (expr, 0));
-      if (op && vrange::supports_type_p (op0_type))
+      if (op && Value_Range::supports_type_p (op0_type))
 	{
 	  Value_Range r0 (TREE_TYPE (TREE_OPERAND (expr, 0)));
 	  Value_Range r1 (type);
@@ -387,7 +387,7 @@  get_range_global (vrange &r, tree name)
    }
   else if (!POINTER_TYPE_P (type) && SSA_NAME_RANGE_INFO (name))
     {
-      gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name)));
+      gcc_checking_assert (irange::supports_p (TREE_TYPE (name)));
       get_ssa_name_range_info (as_a <irange> (r), name);
       if (r.undefined_p ())
 	r.set_varying (type);
@@ -441,9 +441,7 @@  global_range_query global_ranges;
 bool
 global_range_query::range_of_expr (vrange &r, tree expr, gimple *stmt)
 {
-  tree type = TREE_TYPE (expr);
-
-  if (!irange::supports_type_p (type) || !gimple_range_ssa_p (expr))
+  if (!gimple_range_ssa_p (expr))
     return get_tree_range (r, expr, stmt);
 
   get_range_global (r, expr);
diff --git a/gcc/value-range-equiv.h b/gcc/value-range-equiv.h
index 743ceb2b227..0a52d1372a1 100644
--- a/gcc/value-range-equiv.h
+++ b/gcc/value-range-equiv.h
@@ -67,6 +67,10 @@  class GTY((user)) value_range_equiv : public value_range
   void deep_copy (const value_range_equiv *);
   void dump (FILE *) const;
   void dump () const;
+  static bool supports_p (tree type)
+  {
+    return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type);
+  }
 
  private:
   /* Deep-copies bitmap argument.  */
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 429672737a8..c4bcb970094 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -107,6 +107,12 @@  vrange::operator== (const vrange &src) const
   gcc_unreachable ();
 }
 
+bool
+irange::supports_type_p (tree type) const
+{
+  return supports_p (type);
+}
+
 // Return TRUE if R fits in THIS.
 
 bool
@@ -140,6 +146,12 @@  unsupported_range::type () const
   return nullptr;
 }
 
+bool
+unsupported_range::supports_type_p (tree) const
+{
+  return false;
+}
+
 void
 unsupported_range::set_undefined ()
 {
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 5cd0e0ef76a..69cf6c304d6 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -50,6 +50,23 @@  enum value_range_discriminator
 };
 
 // Abstract class for ranges of any of the supported types.
+//
+// To query what types ranger and the entire ecosystem can support,
+// use Value_Range::supports_type_p(tree type).  This is a static
+// method available independently of any vrange object.
+//
+// To query what a given vrange variant can support, use:
+//    irange::supports_p ()
+//    frange::supports_p ()
+//    etc
+//
+// To query what a range object can support, use:
+//    void foo (vrange &v, irange &i, frange &f)
+//    {
+//	if (v.supports_type_p (type)) ...
+//	if (i.supports_type_p (type)) ...
+//	if (f.supports_type_p (type)) ...
+//    }
 
 class vrange
 {
@@ -58,6 +75,7 @@  class vrange
 public:
   virtual void set (tree, tree, value_range_kind = VR_RANGE) = 0;
   virtual tree type () const = 0;
+  virtual bool supports_type_p (tree type) const = 0;
   virtual void set_varying (tree type) = 0;
   virtual void set_undefined () = 0;
   virtual void dump (FILE * = stderr) const = 0;
@@ -72,8 +90,6 @@  public:
   virtual void set_nonnegative (tree type) = 0;
   virtual bool fits_p (const vrange &r) const = 0;
 
-  static bool supports_type_p (tree);
-
   bool varying_p () const;
   bool undefined_p () const;
   vrange& operator= (const vrange &);
@@ -103,7 +119,8 @@  public:
   virtual void set_undefined () override;
 
   // Range types.
-  static bool supports_type_p (tree);
+  static bool supports_p (tree type);
+  virtual bool supports_type_p (tree type) const override;
   virtual tree type () const override;
 
   // Iteration over sub-ranges.
@@ -228,6 +245,7 @@  public:
   unsupported_range ();
   virtual void set (tree, tree, value_range_kind) override;
   virtual tree type () const override;
+  virtual bool supports_type_p (tree type) const override;
   virtual void set_varying (tree type) override;
   virtual void set_undefined () override;
   virtual void dump (FILE *) const override;
@@ -331,6 +349,7 @@  public:
   operator vrange &();
   operator const vrange &() const;
   void dump (FILE *out = stderr) const;
+  static bool supports_type_p (tree type);
 
   // Convenience methods for vrange compatability.
   void set (tree min, tree max, value_range_kind kind = VR_RANGE)
@@ -387,7 +406,7 @@  Value_Range::init (tree type)
 {
   gcc_checking_assert (TYPE_P (type));
 
-  if (irange::supports_type_p (type))
+  if (irange::supports_p (type))
     m_vrange = &m_irange;
   else
     m_vrange = &m_unsupported;
@@ -444,6 +463,14 @@  Value_Range::operator const vrange &() const
   return *m_vrange;
 }
 
+// Return TRUE if TYPE is supported by the vrange infrastructure.
+
+inline bool
+Value_Range::supports_type_p (tree type)
+{
+  return irange::supports_p (type);
+}
+
 // Returns true for an old-school value_range as described above.
 inline bool
 irange::legacy_mode_p () const
@@ -580,7 +607,7 @@  irange::nonzero_p () const
 }
 
 inline bool
-irange::supports_type_p (tree type)
+irange::supports_p (tree type)
 {
   return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type);
 }
@@ -864,12 +891,6 @@  irange::normalize_kind ()
     }
 }
 
-inline bool
-vrange::supports_type_p (tree type)
-{
-  return irange::supports_type_p (type);
-}
-
 // Return the maximum value for TYPE.
 
 inline tree
@@ -944,7 +965,7 @@  vrange_allocator::alloc (unsigned bytes)
 inline vrange *
 vrange_allocator::alloc_vrange (tree type)
 {
-  if (irange::supports_type_p (type))
+  if (irange::supports_p (type))
     return alloc_irange (2);
 
   gcc_unreachable ();