]> git.ipfire.org Git - people/ms/gcc.git/commitdiff
Remove vrange as well as irange virtuals.
authorAldy Hernandez <aldyh@redhat.com>
Thu, 18 Jun 2020 17:09:37 +0000 (19:09 +0200)
committerAldy Hernandez <aldyh@redhat.com>
Fri, 19 Jun 2020 13:14:08 +0000 (15:14 +0200)
gcc/value-range-equiv.cc
gcc/value-range-equiv.h
gcc/value-range.cc
gcc/value-range.h

index ab901666f3501a91bf6b201c5d092b7a1fef0d1d..6d8e974e7a944bfdde4669d198d0eb0fb75ba64d 100644 (file)
@@ -30,14 +30,14 @@ along with GCC; see the file COPYING3.  If not see
 value_range_equiv::value_range_equiv (tree min, tree max, bitmap equiv,
                                      value_range_kind kind)
 {
-  m_discriminator = VRANGE_KIND_INT_WITH_EQUIVS;
+  m_discriminator = IRANGE_KIND_INT;
   m_equiv = NULL;
   set (min, max, equiv, kind);
 }
 
 value_range_equiv::value_range_equiv (const value_range &other)
 {
-  m_discriminator = VRANGE_KIND_INT_WITH_EQUIVS;
+  m_discriminator = IRANGE_KIND_INT;
   m_equiv = NULL;
   set (other.min(), other.max (), NULL, other.kind ());
 }
@@ -190,16 +190,8 @@ value_range_equiv::equiv_add (const_tree var,
 }
 
 void
-value_range_equiv::intersect (const vrange &vother)
+value_range_equiv::intersect (const value_range_equiv *other)
 {
-  if (!is_a <const value_range_equiv *> (&vother))
-    {
-      irange::intersect (vother);
-      return;
-    }
-  const value_range_equiv *other = as_a <const value_range_equiv *> (&vother);
-  gcc_checking_assert (other != NULL);
-
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "Intersecting\n  ");
@@ -247,22 +239,8 @@ value_range_equiv::intersect (const vrange &vother)
 }
 
 void
-value_range_equiv::intersect (const value_range_equiv *other)
-{
-  intersect (*other);
-}
-
-void
-value_range_equiv::union_ (const vrange &vother)
+value_range_equiv::union_ (const value_range_equiv *other)
 {
-  if (!is_a <const value_range_equiv *> (&vother))
-    {
-      irange::union_ (vother);
-      return;
-    }
-  const value_range_equiv *other = as_a <const value_range_equiv *> (&vother);
-  gcc_checking_assert (other != NULL);
-
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "Meeting\n  ");
@@ -278,8 +256,7 @@ value_range_equiv::union_ (const vrange &vother)
     this->deep_copy (other);
   else
     {
-      gcc_checking_assert (other->simple_ranges_p ());
-      value_range tem = union_helper (this, (const value_range *) other);
+      value_range tem = union_helper (this, other);
       this->update (tem.min (), tem.max (), tem.kind ());
 
       /* The resulting set of equivalences is always the intersection of
@@ -298,12 +275,6 @@ value_range_equiv::union_ (const vrange &vother)
     }
 }
 
-void
-value_range_equiv::union_ (const value_range_equiv *other)
-{
-  union_ (*other);
-}
-
 void
 value_range_equiv::dump (FILE *file) const
 {
index 7cf4bcb8532814e3fdd7b501b8515ca75cf08874..1cb06d9f24216931039db598b320194030bcd3aa 100644 (file)
@@ -29,7 +29,7 @@ class GTY((user)) value_range_equiv : public value_range
  public:
   value_range_equiv () : value_range ()
     {
-      m_discriminator = VRANGE_KIND_INT_WITH_EQUIVS;
+      m_discriminator = IRANGE_KIND_INT;
       m_equiv = NULL;
     }
   value_range_equiv (const value_range &);
@@ -54,8 +54,6 @@ class GTY((user)) value_range_equiv : public value_range
   bool operator!= (const value_range_equiv &) const /* = delete */;
   void intersect (const value_range_equiv *);
   void union_ (const value_range_equiv *);
-  virtual void intersect (const vrange &);
-  virtual void union_ (const vrange &);
   bool equal_p (const value_range_equiv &, bool ignore_equivs) const;
 
   /* Types of value ranges.  */
@@ -85,20 +83,4 @@ class GTY((user)) value_range_equiv : public value_range
 
 extern void dump_value_range (FILE *, const value_range_equiv *);
 
-template <>
-template <>
-inline bool
-is_a_helper <const value_range_equiv *>::test (const vrange *p)
-{
-  return p && p->m_discriminator == VRANGE_KIND_INT_WITH_EQUIVS;
-}
-
-template <>
-template <>
-inline bool
-is_a_helper <value_range_equiv *>::test (vrange *p)
-{
-  return p && p->m_discriminator == VRANGE_KIND_INT_WITH_EQUIVS;
-}
-
 #endif // GCC_VALUE_RANGE_EQUIV_H
index ffe18351ae6b1d3cb21f0c2c9ee36b737e4e8b56..b369d2b12a868a1a35d7975f25233acb08919fa9 100644 (file)
@@ -27,36 +27,38 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pretty-print.h"
 #include "fold-const.h"
 
-// Abstract vrange implementation.
+// Here we copy between any two irange's.  The ranges can be simple or
+// multi-ranges, and copying between any combination works correctly.
 
-unsigned
-vrange::num_pairs () const
-{
-  return m_num_ranges;
-}
-
-vrange&
-vrange::operator= (const vrange &src)
+irange&
+irange::operator= (const irange &src)
 {
   if (compatible_copy_p (src))
     copy_compatible_range (src);
   else if (simple_ranges_p () != src.simple_ranges_p ())
     copy_simple_range (src);
   else
-    copy_incompatible_range (src);
+    {
+      set_undefined ();
+      union_ (src);
+    }
   return *this;
 }
 
+// Return TRUE if copying SRC to THIS can be done trivially.  Trivial
+// copies are those that can be done by just straight up copying the
+// fields, without having to squish or expand ranges (as is the case
+// when copying between a simple and a multi-range).
+
 bool
-vrange::compatible_copy_p (const vrange &src) const
+irange::compatible_copy_p (const irange &src) const
 {
   if (src.undefined_p () || src.varying_p ())
     return true;
 
   // Symbolics may be copied straight because there's only one
   // representation for them.
-  const irange *int_range = as_a <const irange *> (&src);
-  if (int_range && !range_has_numeric_bounds_p (int_range))
+  if (!range_has_numeric_bounds_p (&src))
     return true;
 
   if (simple_ranges_p () != src.simple_ranges_p ())
@@ -65,8 +67,10 @@ vrange::compatible_copy_p (const vrange &src) const
   return m_max_ranges >= src.m_num_ranges;
 }
 
+// Trivial copy from SRC to THIS by copying the component fields.
+
 void
-vrange::copy_compatible_range (const vrange &src)
+irange::copy_compatible_range (const irange &src)
 {
   if (src.undefined_p ())
     set_undefined ();
@@ -84,12 +88,8 @@ vrange::copy_compatible_range (const vrange &src)
     }
 }
 
-void
-vrange::copy_incompatible_range (const vrange &src)
-{
-  set_undefined ();
-  union_ (src);
-}
+// Return TRUE if SRC is a multi-range that can be represented as a
+// VR_ANTI_RANGE.
 
 bool
 irange::maybe_anti_range (const irange &src) const
@@ -107,10 +107,12 @@ irange::maybe_anti_range (const irange &src) const
          && ub == type_max);
 }
 
+// Copy between a simple and a multi-range or vice-versa.
+
 void
-irange::copy_simple_range (const vrange &vsrc)
+irange::copy_simple_range (const irange &vsrc)
 {
-  const irange *src = as_a <const irange *> (&vsrc);
+  const irange *src = &vsrc;
   gcc_checking_assert (src->simple_ranges_p () != simple_ranges_p ());
 
   if (src->undefined_p ())
@@ -144,7 +146,7 @@ irange::copy_simple_range (const vrange &vsrc)
 irange::irange (tree *base, unsigned nranges)
 {
   m_kind = VR_UNDEFINED;
-  m_discriminator = VRANGE_KIND_INT;
+  m_discriminator = IRANGE_KIND_INT;
   m_base = base;
   m_num_ranges = 0;
   m_max_ranges = nranges;
@@ -152,10 +154,9 @@ irange::irange (tree *base, unsigned nranges)
 
 irange::irange (tree *base, unsigned nranges, const irange &other)
 {
-  m_discriminator = VRANGE_KIND_INT;
+  m_discriminator = IRANGE_KIND_INT;
   m_base = base;
   m_max_ranges = nranges;
-  // Uses the generic vrange copy constructor to copy without sharing.
   *this = other;
 }
 
@@ -201,12 +202,37 @@ template<unsigned N>
 int_range<N>&
 int_range<N>::operator= (const int_range &src)
 {
-  vrange::operator= (src);
+  irange::operator= (src);
   return *this;
 }
-\f
+
 // widest_irange implementation
 
+template <>
+template <>
+inline bool
+is_a_helper <const irange *>::test (const irange *p)
+{
+  return p && (p->m_discriminator == IRANGE_KIND_INT
+              || p->m_discriminator == IRANGE_KIND_WIDEST_INT);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const widest_irange *>::test (const irange *p)
+{
+  return p && p->m_discriminator == IRANGE_KIND_WIDEST_INT;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <widest_irange *>::test (irange *p)
+{
+  return p && p->m_discriminator == IRANGE_KIND_WIDEST_INT;
+}
+
 widest_irange::widest_irange ()
   : irange (m_ranges, m_sub_ranges_in_local_storage)
 {
@@ -218,7 +244,7 @@ widest_irange::widest_irange (const widest_irange &other)
 {
   init_widest_irange ();
   resize_if_needed (other.num_pairs ());
-  vrange::operator= (other);
+  irange::operator= (other);
 }
 
 widest_irange::widest_irange (tree min, tree max, value_range_kind kind)
@@ -251,7 +277,7 @@ widest_irange::widest_irange (const irange &other)
 {
   init_widest_irange ();
   resize_if_needed (other.num_pairs ());
-  vrange::operator= (other);
+  irange::operator= (other);
 }
 
 widest_irange::~widest_irange ()
@@ -265,7 +291,7 @@ widest_irange::~widest_irange ()
 widest_irange &
 widest_irange::operator= (const widest_irange &src)
 {
-  vrange::operator= (src);
+  irange::operator= (src);
   return *this;
 }
 
@@ -273,6 +299,7 @@ void
 widest_irange::init_widest_irange ()
 {
   m_blob = NULL;
+  m_discriminator = IRANGE_KIND_WIDEST_INT;
 }
 
 void
@@ -281,7 +308,9 @@ widest_irange::resize_if_needed (unsigned nranges)
   if (m_max_ranges >= nranges)
     return;
 
-  // We're about to double the size.  Bail if it won't fit.
+  // If the reallocation below will exceed the maximum number of
+  // ranges that fit in the m_max_ranges field, just leave things as
+  // they are.  This is the theoreticaly max we can handle.
   if (nranges * 2 > sizeof (m_max_ranges) * 255)
     return;
 
@@ -300,22 +329,6 @@ widest_irange::resize_if_needed (unsigned nranges)
     }
 }
 
-void
-widest_irange::union_ (const vrange &other)
-{
-  unsigned size = num_pairs () + other.num_pairs ();
-  resize_if_needed (size);
-  irange::union_ (other);
-}
-
-void
-widest_irange::invert ()
-{
-  unsigned size = num_pairs () + 1;
-  resize_if_needed (size);
-  irange::invert ();
-}
-
 int widest_irange::stats_used_buckets[11];
 
 void
@@ -350,16 +363,17 @@ dump_value_range_stats (FILE *file)
 }
 \f
 void
-vrange::set_undefined ()
+irange::set_undefined ()
 {
   if (simple_ranges_p ())
     m_kind = VR_UNDEFINED;
-  else m_kind = VR_RANGE;
+  else
+    m_kind = VR_RANGE;
   m_num_ranges = 0;
 }
 
 void
-vrange::set_varying (tree type)
+irange::set_varying (tree type)
 {
   if (simple_ranges_p ())
     m_kind = VR_VARYING;
@@ -548,6 +562,8 @@ irange::set (tree min, tree max, value_range_kind kind)
     check ();
 }
 
+// Set range for a multi-range irange from an anti-range ~[MIN,MAX].
+
 void
 irange::multi_range_set_anti_range (tree min, tree max)
 {
@@ -1693,6 +1709,11 @@ union_helper (const value_range *vr0, const value_range *vr1)
 void
 irange::union_ (const irange *other)
 {
+  if (widest_irange *widest = dyn_cast <widest_irange *> (this))
+    {
+      unsigned size = num_pairs () + other->num_pairs ();
+      widest->resize_if_needed (size);
+    }
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "Meeting\n  ");
@@ -1750,11 +1771,10 @@ private:
 /* Range union, but for references.  */
 
 void
-irange::union_ (const vrange &vr)
+irange::union_ (const irange &r)
 {
   disable_dump_details details;
-  const irange *other = as_a <const irange *> (&vr);
-  union_ (other);
+  union_ (&r);
 }
 
 void
@@ -1805,13 +1825,14 @@ irange::intersect (const irange *other)
 /* Range intersect, but for references.  */
 
 void
-irange::intersect (const vrange &vr)
+irange::intersect (const irange &r)
 {
   disable_dump_details details;
-  const irange *other = as_a <const irange *> (&vr);
-  intersect (other);
+  intersect (&r);
 }
 
+// union_ for multi-ranges.
+
 void
 irange::multi_range_union (const irange &r)
 {
@@ -1954,6 +1975,8 @@ irange::intersect_from_wide_ints (const wide_int &x, const wide_int &y)
     check ();
 }
 
+// intersect for multi-ranges.
+
 void
 irange::multi_range_intersect (const irange &r)
 {
@@ -2006,6 +2029,14 @@ subtract_one (const wide_int &x, tree type, wi::overflow_type &overflow)
 void
 irange::invert ()
 {
+  // Resize a widest_irange if needed.
+  if (widest_irange *widest = dyn_cast <widest_irange *> (this))
+    {
+      unsigned size = num_pairs () + 1;
+      widest->resize_if_needed (size);
+    }
+
+  // Handle simple ranges.
   if (simple_ranges_p ())
     {
       /* We can't just invert VR_RANGE and VR_ANTI_RANGE because we may
@@ -2114,6 +2145,8 @@ irange::invert ()
     check ();
 }
 
+// Dump a simple range.
+
 void
 irange::simple_dump (FILE *file) const
 {
@@ -2172,13 +2205,14 @@ dump_bound_with_infinite_markers (FILE *file, tree bound)
     print_generic_expr (file, bound);
 }
 
+// Dump any range.
+
 void
-vrange::dump (FILE *file) const
+irange::dump (FILE *file) const
 {
-  const irange *ir = as_a <const irange *> (this);
-  if (ir && simple_ranges_p ())
+  if (simple_ranges_p ())
     {
-      ir->simple_dump (file);
+      simple_dump (file);
       return;
     }
   if (undefined_p ())
@@ -2206,7 +2240,7 @@ vrange::dump (FILE *file) const
   else if (m_kind == VR_ANTI_RANGE)
     {
       gcc_checking_assert (m_num_ranges == 1);
-      gcc_checking_assert (!range_has_numeric_bounds_p (ir));
+      gcc_checking_assert (!range_has_numeric_bounds_p (this));
       tree lb = m_base[0];
       tree ub = m_base[1];
       fprintf (file, "~[");
@@ -2220,20 +2254,20 @@ vrange::dump (FILE *file) const
 }
 
 void
-dump_value_range (FILE *file, const vrange *vr)
+dump_value_range (FILE *file, const irange *vr)
 {
   vr->dump (file);
 }
 
 DEBUG_FUNCTION void
-debug (const vrange *vr)
+debug (const irange *vr)
 {
   dump_value_range (stderr, vr);
   fprintf (stderr, "\n");
 }
 
 DEBUG_FUNCTION void
-debug (const vrange &vr)
+debug (const irange &vr)
 {
   debug (&vr);
 }
index 6588086147cce261048acca271a578e079b92ce5..2c204457066af3ab8a5062c590c7b431dc6214b0 100644 (file)
@@ -35,48 +35,20 @@ enum value_range_kind
   VR_LAST
 };
 
-enum vrange_discriminator
-{
-  VRANGE_KIND_UNKNOWN,
-  VRANGE_KIND_INT,
-  VRANGE_KIND_INT_WITH_EQUIVS
-};
+// Helper for is_a<> to distinguish between irange and widest_irange.
 
-class vrange
+enum irange_discriminator
 {
-public:
-  unsigned num_pairs () const;
-  bool undefined_p () const;
-  bool varying_p () const;
-  void set_undefined ();
-  void set_varying (tree type);
-  tree type () const;
-  void dump (FILE * = stderr) const;
-  vrange& operator= (const vrange &);
-  virtual void union_ (const vrange &) = 0;
-  virtual void intersect (const vrange &) = 0;
-  virtual void invert () = 0;
-protected:
-  bool simple_ranges_p () const { return m_max_ranges == 1; }
-private:
-  bool compatible_copy_p (const vrange &) const;
-  void copy_compatible_range (const vrange &);
-  void copy_incompatible_range (const vrange &);
-  virtual void copy_simple_range (const vrange &) = 0;
-
-public:
-  // For is_a_helper.
-  enum vrange_discriminator m_discriminator;
-protected:
-  unsigned char m_num_ranges;
-  unsigned char m_max_ranges;
-  value_range_kind m_kind;
-  tree *m_base;
+  IRANGE_KIND_UNKNOWN,
+  IRANGE_KIND_INT,
+  IRANGE_KIND_WIDEST_INT
 };
 
 // Range of values that can be associated with an SSA_NAME.
+//
+// This is the base class without any storage.
 
-class irange : public vrange
+class irange
 {
 public:
   void set (tree, tree, value_range_kind = VR_RANGE);
@@ -91,21 +63,28 @@ public:
   /* Types of value ranges.  */
   bool symbolic_p () const;
   bool constant_p () const;
+  bool undefined_p () const;
+  bool varying_p () const;
+  void set_varying (tree type);
+  void set_undefined ();
 
   void union_ (const irange *);
   void intersect (const irange *);
-  virtual void union_ (const vrange &);
-  virtual void intersect (const vrange &);
+  void union_ (const irange &);
+  void intersect (const irange &);
 
+  irange& operator= (const irange &);
   bool operator== (const irange &) const;
   bool operator!= (const irange &r) const { return !(*this == r); }
   bool equal_p (const irange &) const;
 
   /* Misc methods.  */
+  tree type () const;
   bool may_contain_p (tree) const;
   bool zero_p () const;
   bool nonzero_p () const;
   bool singleton_p (tree *result = NULL) const;
+  void dump (FILE * = stderr) const;
   void simple_dump (FILE *) const;
 
   static bool supports_type_p (tree);
@@ -117,17 +96,18 @@ public:
   wide_int lower_bound (unsigned = 0) const;
   wide_int upper_bound (unsigned) const;
   wide_int upper_bound () const;
-  virtual void invert ();
+  void invert ();
 
 protected:
   void check ();
+  // Returns true for an old-school value_range with anti ranges.
+  bool simple_ranges_p () const { return m_max_ranges == 1; }
   irange (tree *, unsigned);
   irange (tree *, unsigned, const irange &);
 
 private:
   int value_inside_range (tree) const;
 
-  virtual void copy_simple_range (const vrange &);
   void intersect_from_wide_ints (const wide_int &, const wide_int &);
   bool maybe_anti_range (const irange &) const;
   void multi_range_set_anti_range (tree, tree);
@@ -135,8 +115,23 @@ private:
   void multi_range_intersect (const irange &);
   tree tree_lower_bound (unsigned = 0) const;
   tree tree_upper_bound (unsigned) const;
+
+  bool compatible_copy_p (const irange &) const;
+  void copy_compatible_range (const irange &);
+  void copy_simple_range (const irange &);
+
+public:
+  ENUM_BITFIELD(irange_discriminator) m_discriminator : 8;
+protected:
+  unsigned char m_num_ranges;
+  unsigned char m_max_ranges;
+  ENUM_BITFIELD(value_range_kind) m_kind : 8;
+
+  tree *m_base;
 };
 
+// int_range<N> describes an irange with N pairs of ranges.
+
 template<unsigned N>
 class GTY((user)) int_range : public irange
 {
@@ -165,6 +160,25 @@ private:
   tree m_ranges[N*2];
 };
 
+// This is a special int_range<> with only one pair, plus
+// VR_ANTI_RANGE magic to describe slightly more than can be described
+// in one pair.  It is described in the code as a "simple range" (as
+// opposed to multi-ranges which have multiple sub-ranges).  It is
+// provided for backward compatibility with the more limited,
+// traditional value_range's.
+//
+// simple_ranges_p() returns true for value_range's.
+//
+// There are copy methods to seamlessly copy to/fro multi-ranges.
+
+typedef int_range<1> value_range;
+
+// An irange with "unlimited" sub-ranges.  In reality we are limited
+// by the number of values that fit in an `m_num_ranges'.
+//
+// A widest_irange starts with a handful of sub-ranges in local
+// storage and will grow into the heap as necessary.
+
 class widest_irange : public irange
 {
 public:
@@ -177,16 +191,14 @@ public:
   widest_irange (const irange &);
   ~widest_irange ();
   widest_irange& operator= (const widest_irange &);
-
-  virtual void union_ (const vrange &);
-  virtual void invert ();
+  void resize_if_needed (unsigned);
 #if CHECKING_P
   static void stats_dump (FILE *);
 #endif
+
 private:
   static const unsigned m_sub_ranges_in_local_storage = 5;
   void init_widest_irange ();
-  void resize_if_needed (unsigned);
 
   // Memory usage stats.
   void stats_register_use (void);
@@ -196,14 +208,12 @@ private:
   tree m_ranges[m_sub_ranges_in_local_storage*2];
 };
 
-typedef int_range<1> value_range;
-
 value_range union_helper (const value_range *, const value_range *);
 value_range intersect_helper (const value_range *, const value_range *);
 extern bool range_has_numeric_bounds_p (const irange *);
 extern bool ranges_from_anti_range (const value_range *,
                                    value_range *, value_range *);
-extern void dump_value_range (FILE *, const vrange *);
+extern void dump_value_range (FILE *, const irange *);
 extern void dump_value_range_stats (FILE *);
 extern bool vrp_val_is_min (const_tree);
 extern bool vrp_val_is_max (const_tree);
@@ -244,7 +254,7 @@ irange::kind () const
 }
 
 inline tree
-vrange::type () const
+irange::type () const
 {
   gcc_checking_assert (!undefined_p ());
   return TREE_TYPE (m_base[0]);
@@ -277,7 +287,7 @@ irange::max () const
 }
 
 inline bool
-vrange::varying_p () const
+irange::varying_p () const
 {
   if (simple_ranges_p ())
     return m_kind == VR_VARYING;
@@ -288,7 +298,7 @@ vrange::varying_p () const
 }
 
 inline bool
-vrange::undefined_p () const
+irange::undefined_p () const
 {
   if (simple_ranges_p ())
     {
@@ -341,26 +351,6 @@ range_includes_zero_p (const irange *vr)
   return vr->may_contain_p (build_zero_cst (vr->type ()));
 }
 
-template <>
-template <>
-inline bool
-is_a_helper <const irange *>::test (const vrange *p)
-{
-  return p
-    && (p->m_discriminator == VRANGE_KIND_INT
-       || p->m_discriminator == VRANGE_KIND_INT_WITH_EQUIVS);
-}
-
-template <>
-template <>
-inline bool
-is_a_helper <irange *>::test (vrange *p)
-{
-  return p
-    && (p->m_discriminator == VRANGE_KIND_INT
-       || p->m_discriminator == VRANGE_KIND_INT_WITH_EQUIVS);
-}
-
 template<unsigned N>
 static inline void
 gt_ggc_mx (int_range<N> *x)