Implement vrange::supports_type_p.
authorAldy Hernandez <aldyh@redhat.com>
Tue, 31 May 2022 12:04:51 +0000 (14:04 +0200)
committerAldy Hernandez <aldyh@redhat.com>
Fri, 3 Jun 2022 08:31:00 +0000 (10:31 +0200)
[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.

15 files changed:
gcc/gimple-range-edge.cc
gcc/gimple-range-fold.cc
gcc/gimple-range-fold.h
gcc/gimple-range-path.cc
gcc/gimple-range.cc
gcc/gimple-ssa-evrp-analyze.cc
gcc/range-op.cc
gcc/tree-ssa-loop-ch.cc
gcc/tree-ssa-loop-unswitch.cc
gcc/tree-ssa-threadedge.cc
gcc/tree-vrp.cc
gcc/value-query.cc
gcc/value-range-equiv.h
gcc/value-range.cc
gcc/value-range.h

index 6fe3340..03a804a 100644 (file)
@@ -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;
index c1a8016..2a8c66e 100644 (file)
@@ -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;
index df24280..fbf6627 100644 (file)
@@ -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;
 }
index f8ae6fb..e1b9683 100644 (file)
@@ -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
index 12da168..67dafb2 100644 (file)
@@ -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;
index 16e5a75..82142db 100644 (file)
@@ -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;
index 028b4b7..5150c60 100644 (file)
@@ -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;
 
index 2f5a390..26d96c0 100644 (file)
@@ -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;
index 61c04ed..50b66c1 100644 (file)
@@ -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;
index 931aa74..a70aebd 100644 (file)
@@ -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));
        }
     }
index 7427761..30022da 100644 (file)
@@ -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;
index e40e358..1d7541c 100644 (file)
@@ -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);
index 743ceb2..0a52d13 100644 (file)
@@ -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.  */
index 4296727..c4bcb97 100644 (file)
@@ -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 ()
 {
index 5cd0e0e..69cf6c3 100644 (file)
@@ -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 ();