aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2020-06-18 19:09:37 +0200
committerAldy Hernandez <aldyh@redhat.com>2020-06-19 15:14:08 +0200
commit7cefb069fa9d631566a201ad71fa1a370ab04d17 (patch)
treeb95a5a288bc963e728a8c3d266866a2f952566a4 /gcc
parent6472945db3885a749fb17073a3dee25c9839b21a (diff)
downloadgcc-7cefb069fa9d631566a201ad71fa1a370ab04d17.zip
gcc-7cefb069fa9d631566a201ad71fa1a370ab04d17.tar.gz
gcc-7cefb069fa9d631566a201ad71fa1a370ab04d17.tar.bz2
Remove vrange as well as irange virtuals.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/value-range-equiv.cc39
-rw-r--r--gcc/value-range-equiv.h20
-rw-r--r--gcc/value-range.cc162
-rw-r--r--gcc/value-range.h130
4 files changed, 164 insertions, 187 deletions
diff --git a/gcc/value-range-equiv.cc b/gcc/value-range-equiv.cc
index ab90166..6d8e974 100644
--- a/gcc/value-range-equiv.cc
+++ b/gcc/value-range-equiv.cc
@@ -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
@@ -299,12 +276,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
{
value_range::dump (file);
diff --git a/gcc/value-range-equiv.h b/gcc/value-range-equiv.h
index 7cf4bcb..1cb06d9 100644
--- a/gcc/value-range-equiv.h
+++ b/gcc/value-range-equiv.h
@@ -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
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index ffe1835..b369d2b 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -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;
}
-
+
// 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)
}
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);
}
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 6588086..2c20445 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -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)