diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-08-24 16:50:14 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-24 16:50:14 +0000 |
commit | d3cf195ab46d7effe806990aa6b7a409bf8e46df (patch) | |
tree | eb33d22a749417ad62a3fc87c2dc8cfb3452632a /gcc/value-range.h | |
parent | 825a44b40ce6cfa76470e53d0746b1e64b99ee5b (diff) | |
parent | 2e77960b14527ff216fa188479de9142fbb9d34c (diff) | |
download | gcc-d3cf195ab46d7effe806990aa6b7a409bf8e46df.zip gcc-d3cf195ab46d7effe806990aa6b7a409bf8e46df.tar.gz gcc-d3cf195ab46d7effe806990aa6b7a409bf8e46df.tar.bz2 |
Merge #1498
1498: Merge from GCC upstream r=philberty a=philberty
Lets see if it builds.
Co-authored-by: GCC Administrator <gccadmin@gcc.gnu.org>
Co-authored-by: Dimitrije Milošević <dimitrije.milosevic@syrmia.com>
Co-authored-by: Aldy Hernandez <aldyh@redhat.com>
Co-authored-by: Jakub Jelinek <jakub@redhat.com>
Co-authored-by: Martin Liska <mliska@suse.cz>
Co-authored-by: Roger Sayle <roger@nextmovesoftware.com>
Co-authored-by: Sam Feifer <sfeifer@redhat.com>
Co-authored-by: Andrew Stubbs <ams@codesourcery.com>
Co-authored-by: Jose E. Marchesi <jose.marchesi@oracle.com>
Co-authored-by: H.J. Lu <hjl.tools@gmail.com>
Co-authored-by: David Malcolm <dmalcolm@redhat.com>
Co-authored-by: Richard Biener <rguenther@suse.de>
Co-authored-by: Immad Mir <mirimmad@outlook.com>
Diffstat (limited to 'gcc/value-range.h')
-rw-r--r-- | gcc/value-range.h | 642 |
1 files changed, 528 insertions, 114 deletions
diff --git a/gcc/value-range.h b/gcc/value-range.h index d4cba22..f0075d0 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -22,6 +22,8 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_VALUE_RANGE_H #define GCC_VALUE_RANGE_H +class irange; + // Types of value ranges. enum value_range_kind { @@ -37,24 +39,92 @@ enum value_range_kind VR_LAST }; -// Range of values that can be associated with an SSA_NAME. +// Discriminator between different vrange types. + +enum value_range_discriminator +{ + // Range holds an integer or pointer. + VR_IRANGE, + // Floating point range. + VR_FRANGE, + // Range holds an unsupported type. + VR_UNKNOWN +}; + +// 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. // -// This is the base class without any storage. +// 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 +{ + template <typename T> friend bool is_a (vrange &); + friend class Value_Range; +public: + virtual void accept (const class vrange_visitor &v) const = 0; + virtual void set (tree, tree, value_range_kind = VR_RANGE); + virtual tree type () const; + virtual bool supports_type_p (const_tree type) const; + virtual void set_varying (tree type); + virtual void set_undefined (); + virtual bool union_ (const vrange &); + virtual bool intersect (const vrange &); + virtual bool singleton_p (tree *result = NULL) const; + virtual bool contains_p (tree cst) const; + virtual bool zero_p () const; + virtual bool nonzero_p () const; + virtual void set_nonzero (tree type); + virtual void set_zero (tree type); + virtual void set_nonnegative (tree type); + virtual bool fits_p (const vrange &r) const; + + bool varying_p () const; + bool undefined_p () const; + vrange& operator= (const vrange &); + bool operator== (const vrange &) const; + bool operator!= (const vrange &r) const { return !(*this == r); } + void dump (FILE *) const; -class GTY((user)) irange + enum value_range_kind kind () const; // DEPRECATED + +protected: + ENUM_BITFIELD(value_range_kind) m_kind : 8; + ENUM_BITFIELD(value_range_discriminator) m_discriminator : 4; +}; + +// An integer range without any storage. + +class GTY((user)) irange : public vrange { - friend class irange_allocator; + friend class vrange_allocator; + friend class irange_storage_slot; // For legacy_mode_p checks. public: // In-place setters. - void set (tree, tree, value_range_kind = VR_RANGE); - void set_nonzero (tree); - void set_zero (tree); - void set_varying (tree type); - void set_undefined (); + virtual void set (tree, tree, value_range_kind = VR_RANGE) override; + virtual void set_nonzero (tree type) override; + virtual void set_zero (tree type) override; + virtual void set_nonnegative (tree type) override; + virtual void set_varying (tree type) override; + virtual void set_undefined () override; // Range types. - static bool supports_type_p (tree); - tree type () const; + static bool supports_p (const_tree type); + virtual bool supports_type_p (const_tree type) const override; + virtual tree type () const override; // Iteration over sub-ranges. unsigned num_pairs () const; @@ -63,17 +133,14 @@ public: wide_int upper_bound () const; // Predicates. - bool zero_p () const; - bool nonzero_p () const; - bool undefined_p () const; - bool varying_p () const; - bool singleton_p (tree *result = NULL) const; - bool contains_p (tree) const; + virtual bool zero_p () const override; + virtual bool nonzero_p () const override; + virtual bool singleton_p (tree *result = NULL) const override; + virtual bool contains_p (tree cst) const override; // In-place operators. - void union_ (const irange &); - void intersect (const irange &); - void intersect (const wide_int& lb, const wide_int& ub); + virtual bool union_ (const vrange &) override; + virtual bool intersect (const vrange &) override; void invert (); // Operator overloads. @@ -82,12 +149,14 @@ public: bool operator!= (const irange &r) const { return !(*this == r); } // Misc methods. - bool fits_p (const irange &r) { return m_max_ranges >= r.num_pairs (); } - void dump (FILE * = stderr) const; - void debug () const; + virtual bool fits_p (const vrange &r) const override; + virtual void accept (const vrange_visitor &v) const override; + + // Nonzero masks. + wide_int get_nonzero_bits () const; + void set_nonzero_bits (const wide_int_ref &bits); // Deprecated legacy public methods. - enum value_range_kind kind () const; // DEPRECATED tree min () const; // DEPRECATED tree max () const; // DEPRECATED bool symbolic_p () const; // DEPRECATED @@ -95,10 +164,8 @@ public: void normalize_symbolics (); // DEPRECATED void normalize_addresses (); // DEPRECATED bool may_contain_p (tree) const; // DEPRECATED - void set (tree); // DEPRECATED - bool equal_p (const irange &) const; // DEPRECATED - void union_ (const class irange *); // DEPRECATED - void intersect (const irange *); // DEPRECATED + bool legacy_verbose_union_ (const class irange *); // DEPRECATED + bool legacy_verbose_intersect (const irange *); // DEPRECATED protected: irange (tree *, unsigned); @@ -108,10 +175,12 @@ protected: tree tree_upper_bound () const; // In-place operators. - void irange_union (const irange &); - void irange_intersect (const irange &); + bool irange_union (const irange &); + bool irange_intersect (const irange &); void irange_set (tree, tree); void irange_set_anti_range (tree, tree); + bool irange_contains_p (const irange &) const; + bool irange_single_pair_union (const irange &r); void normalize_kind (); @@ -134,10 +203,14 @@ private: void irange_set_1bit_anti_range (tree, tree); bool varying_compatible_p () const; + void set_nonzero_bits (tree mask); + bool intersect_nonzero_bits (const irange &r); + bool union_nonzero_bits (const irange &r); + bool intersect (const wide_int& lb, const wide_int& ub); unsigned char m_num_ranges; unsigned char m_max_ranges; - ENUM_BITFIELD(value_range_kind) m_kind : 8; + tree m_nonzero_mask; tree *m_base; }; @@ -155,6 +228,7 @@ public: int_range (tree type); int_range (const int_range &); int_range (const irange &); + virtual ~int_range () = default; int_range& operator= (const int_range &); private: template <unsigned X> friend void gt_ggc_mx (int_range<X> *); @@ -171,6 +245,194 @@ private: tree m_ranges[N*2]; }; +// Unsupported temporaries may be created by ranger before it's known +// they're unsupported, or by vr_values::get_value_range. + +class unsupported_range : public vrange +{ +public: + unsupported_range () + { + m_discriminator = VR_UNKNOWN; + set_undefined (); + } + virtual void set_undefined () final override + { + m_kind = VR_UNDEFINED; + } + virtual void accept (const vrange_visitor &v) const override; +}; + +// Floating point property to represent possible values of a NAN, INF, etc. + +class fp_prop +{ +public: + enum kind { + UNDEFINED = 0x0, // Prop is impossible. + YES = 0x1, // Prop is definitely set. + NO = 0x2, // Prop is definitely not set. + VARYING = (YES | NO) // Prop may hold. + }; + fp_prop (kind f) : m_kind (f) { } + bool varying_p () const { return m_kind == VARYING; } + bool undefined_p () const { return m_kind == UNDEFINED; } + bool yes_p () const { return m_kind == YES; } + bool no_p () const { return m_kind == NO; } +private: + unsigned char m_kind : 2; +}; + +// Accessors for individual FP properties. + +#define FP_PROP_ACCESSOR(NAME) \ + void NAME##_set_varying () { u.bits.NAME = fp_prop::VARYING; } \ + void NAME##_set_yes () { u.bits.NAME = fp_prop::YES; } \ + void NAME##_set_no () { u.bits.NAME = fp_prop::NO; } \ + bool NAME##_varying_p () const { return u.bits.NAME == fp_prop::VARYING; } \ + bool NAME##_undefined_p () const { return u.bits.NAME == fp_prop::UNDEFINED; } \ + bool NAME##_yes_p () const { return u.bits.NAME == fp_prop::YES; } \ + bool NAME##_no_p () const { return u.bits.NAME == fp_prop::NO; } \ + fp_prop get_##NAME () const \ + { return fp_prop ((fp_prop::kind) u.bits.NAME); } \ + void set_##NAME (fp_prop::kind f) { u.bits.NAME = f; } + +// Aggregate of all the FP properties in an frange packed into one +// structure to save space. Using explicit fp_prop's in the frange, +// would take one byte per property because of padding. Instead, we +// can save all properties into one byte. + +class frange_props +{ +public: + frange_props () { set_varying (); } + void set_varying () { u.bytes = 0xff; } + void set_undefined () { u.bytes = 0; } + bool varying_p () { return u.bytes == 0xff; } + bool undefined_p () { return u.bytes == 0; } + bool union_ (const frange_props &other); + bool intersect (const frange_props &other); + bool operator== (const frange_props &other) const; + FP_PROP_ACCESSOR(nan) + FP_PROP_ACCESSOR(inf) + FP_PROP_ACCESSOR(ninf) +private: + union { + struct { + unsigned char nan : 2; + unsigned char inf : 2; + unsigned char ninf : 2; + } bits; + unsigned char bytes; + } u; +}; + +// Accessors for getting/setting all FP properties at once. + +#define FRANGE_PROP_ACCESSOR(NAME) \ + fp_prop get_##NAME () const { return m_props.get_##NAME (); } \ + void set_##NAME (fp_prop::kind f) \ + { \ + m_props.set_##NAME (f); \ + normalize_kind (); \ + } + +// A floating point range. + +class frange : public vrange +{ + friend class frange_storage_slot; +public: + frange (); + frange (const frange &); + static bool supports_p (const_tree type) + { + return SCALAR_FLOAT_TYPE_P (type); + } + virtual tree type () const override; + virtual void set (tree, tree, value_range_kind = VR_RANGE) override; + virtual void set_varying (tree type) override; + virtual void set_undefined () override; + virtual bool union_ (const vrange &) override; + virtual bool intersect (const vrange &) override; + virtual bool supports_type_p (const_tree type) const override; + virtual void accept (const vrange_visitor &v) const override; + frange& operator= (const frange &); + bool operator== (const frange &) const; + bool operator!= (const frange &r) const { return !(*this == r); } + + // Each fp_prop can be accessed with get_PROP() and set_PROP(). + FRANGE_PROP_ACCESSOR(nan) + FRANGE_PROP_ACCESSOR(inf) + FRANGE_PROP_ACCESSOR(ninf) +private: + void verify_range (); + bool normalize_kind (); + + frange_props m_props; + tree m_type; +}; + +// is_a<> and as_a<> implementation for vrange. + +// Anything we haven't specialized is a hard fail. +template <typename T> +inline bool +is_a (vrange &) +{ + gcc_unreachable (); + return false; +} + +template <typename T> +inline bool +is_a (const vrange &v) +{ + // Reuse is_a <vrange> to implement the const version. + const T &derived = static_cast<const T &> (v); + return is_a <T> (const_cast<T &> (derived)); +} + +template <typename T> +inline T & +as_a (vrange &v) +{ + gcc_checking_assert (is_a <T> (v)); + return static_cast <T &> (v); +} + +template <typename T> +inline const T & +as_a (const vrange &v) +{ + gcc_checking_assert (is_a <T> (v)); + return static_cast <const T &> (v); +} + +// Specializations for the different range types. + +template <> +inline bool +is_a <irange> (vrange &v) +{ + return v.m_discriminator == VR_IRANGE; +} + +template <> +inline bool +is_a <frange> (vrange &v) +{ + return v.m_discriminator == VR_FRANGE; +} + +class vrange_visitor +{ +public: + virtual void visit (const irange &) const { } + virtual void visit (const frange &) const { } + virtual void visit (const unsupported_range &) const { } +}; + // This is a special int_range<1> 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 "legacy range" (as @@ -185,6 +447,160 @@ typedef int_range<1> value_range; // calculations. typedef int_range<255> int_range_max; +// This is an "infinite" precision range object for use in temporary +// calculations for any of the handled types. The object can be +// transparently used as a vrange. + +class Value_Range +{ +public: + Value_Range (); + Value_Range (const vrange &r); + Value_Range (tree type); + Value_Range (const Value_Range &); + void set_type (tree type); + vrange& operator= (const vrange &); + bool operator== (const Value_Range &r) const; + bool operator!= (const Value_Range &r) const; + operator vrange &(); + operator const vrange &() const; + void dump (FILE *) const; + static bool supports_type_p (const_tree type); + + // Convenience methods for vrange compatability. + void set (tree min, tree max, value_range_kind kind = VR_RANGE) + { return m_vrange->set (min, max, kind); } + tree type () { return m_vrange->type (); } + enum value_range_kind kind () { return m_vrange->kind (); } + bool varying_p () const { return m_vrange->varying_p (); } + bool undefined_p () const { return m_vrange->undefined_p (); } + void set_varying (tree type) { m_vrange->set_varying (type); } + void set_undefined () { m_vrange->set_undefined (); } + bool union_ (const vrange &r) { return m_vrange->union_ (r); } + bool intersect (const vrange &r) { return m_vrange->intersect (r); } + bool singleton_p (tree *result = NULL) const + { return m_vrange->singleton_p (result); } + bool zero_p () const { return m_vrange->zero_p (); } + wide_int lower_bound () const; // For irange/prange compatability. + wide_int upper_bound () const; // For irange/prange compatability. + void accept (const vrange_visitor &v) const { m_vrange->accept (v); } +private: + void init (tree type); + unsupported_range m_unsupported; + vrange *m_vrange; + int_range_max m_irange; + frange m_frange; +}; + +inline +Value_Range::Value_Range () +{ + m_vrange = &m_unsupported; +} + +// Copy constructor from a vrange. + +inline +Value_Range::Value_Range (const vrange &r) +{ + *this = r; +} + +// Copy constructor from a TYPE. The range of the temporary is set to +// UNDEFINED. + +inline +Value_Range::Value_Range (tree type) +{ + init (type); +} + +inline +Value_Range::Value_Range (const Value_Range &r) +{ + m_vrange = r.m_vrange; +} + +// Initialize object so it is possible to store temporaries of TYPE +// into it. + +inline void +Value_Range::init (tree type) +{ + gcc_checking_assert (TYPE_P (type)); + + if (irange::supports_p (type)) + m_vrange = &m_irange; + else if (frange::supports_p (type)) + m_vrange = &m_frange; + else + m_vrange = &m_unsupported; +} + +// Set the temporary to allow storing temporaries of TYPE. The range +// of the temporary is set to UNDEFINED. + +inline void +Value_Range::set_type (tree type) +{ + init (type); + m_vrange->set_undefined (); +} + +// Assignment operator for temporaries. Copying incompatible types is +// allowed. + +inline vrange & +Value_Range::operator= (const vrange &r) +{ + if (is_a <irange> (r)) + { + m_irange = as_a <irange> (r); + m_vrange = &m_irange; + } + else if (is_a <frange> (r)) + { + m_frange = as_a <frange> (r); + m_vrange = &m_frange; + } + else + gcc_unreachable (); + + return *m_vrange; +} + +inline bool +Value_Range::operator== (const Value_Range &r) const +{ + return *m_vrange == *r.m_vrange; +} + +inline bool +Value_Range::operator!= (const Value_Range &r) const +{ + return *m_vrange != *r.m_vrange; +} + +inline +Value_Range::operator vrange &() +{ + return *m_vrange; +} + +inline +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 (const_tree type) +{ + return irange::supports_p (type) || frange::supports_p (type); +} + // Returns true for an old-school value_range as described above. inline bool irange::legacy_mode_p () const @@ -195,13 +611,13 @@ irange::legacy_mode_p () const 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 irange *); +extern void dump_value_range (FILE *, const vrange *); extern bool vrp_val_is_min (const_tree); extern bool vrp_val_is_max (const_tree); extern bool vrp_operand_equal_p (const_tree, const_tree); inline value_range_kind -irange::kind () const +vrange::kind () const { return m_kind; } @@ -283,7 +699,8 @@ irange::varying_compatible_p () const signop sign = TYPE_SIGN (t); if (INTEGRAL_TYPE_P (t)) return (wi::to_wide (l) == wi::min_value (prec, sign) - && wi::to_wide (u) == wi::max_value (prec, sign)); + && wi::to_wide (u) == wi::max_value (prec, sign) + && !m_nonzero_mask); if (POINTER_TYPE_P (t)) return (wi::to_wide (l) == 0 && wi::to_wide (u) == wi::max_value (prec, sign)); @@ -291,13 +708,13 @@ irange::varying_compatible_p () const } inline bool -irange::varying_p () const +vrange::varying_p () const { return m_kind == VR_VARYING; } inline bool -irange::undefined_p () const +vrange::undefined_p () const { return m_kind == VR_UNDEFINED; } @@ -321,11 +738,9 @@ irange::nonzero_p () const } inline bool -irange::supports_type_p (tree type) +irange::supports_p (const_tree type) { - if (type && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))) - return type; - return false; + return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type); } inline bool @@ -348,6 +763,8 @@ gt_ggc_mx (irange *x) gt_ggc_mx (x->m_base[i * 2]); gt_ggc_mx (x->m_base[i * 2 + 1]); } + if (x->m_nonzero_mask) + gt_ggc_mx (x->m_nonzero_mask); } inline void @@ -358,6 +775,8 @@ gt_pch_nx (irange *x) gt_pch_nx (x->m_base[i * 2]); gt_pch_nx (x->m_base[i * 2 + 1]); } + if (x->m_nonzero_mask) + gt_pch_nx (x->m_nonzero_mask); } inline void @@ -368,6 +787,8 @@ gt_pch_nx (irange *x, gt_pointer_operator op, void *cookie) op (&x->m_base[i * 2], NULL, cookie); op (&x->m_base[i * 2 + 1], NULL, cookie); } + if (x->m_nonzero_mask) + op (&x->m_nonzero_mask, NULL, cookie); } template<unsigned N> @@ -396,10 +817,10 @@ gt_pch_nx (int_range<N> *x, gt_pointer_operator op, void *cookie) inline irange::irange (tree *base, unsigned nranges) { + m_discriminator = VR_IRANGE; m_base = base; - m_num_ranges = 0; m_max_ranges = nranges; - m_kind = VR_UNDEFINED; + set_undefined (); } // Constructors for int_range<>. @@ -458,16 +879,11 @@ int_range<N>::operator= (const int_range &src) } inline void -irange::set (tree val) -{ - set (val, val); -} - -inline void irange::set_undefined () { m_kind = VR_UNDEFINED; m_num_ranges = 0; + m_nonzero_mask = NULL; } inline void @@ -475,6 +891,7 @@ irange::set_varying (tree type) { m_kind = VR_VARYING; m_num_ranges = 1; + m_nonzero_mask = NULL; if (INTEGRAL_TYPE_P (type)) { @@ -503,12 +920,6 @@ irange::set_varying (tree type) m_base[0] = m_base[1] = error_mark_node; } -inline bool -irange::operator== (const irange &r) const -{ - return equal_p (r); -} - // Return the lower bound of a sub-range. PAIR is the sub-range in // question. @@ -545,22 +956,24 @@ irange::upper_bound () const return upper_bound (pairs - 1); } -inline void -irange::union_ (const irange &r) +inline bool +irange::union_ (const vrange &r) { dump_flags_t m_flags = dump_flags; dump_flags &= ~TDF_DETAILS; - irange::union_ (&r); + bool ret = irange::legacy_verbose_union_ (&as_a <irange> (r)); dump_flags = m_flags; + return ret; } -inline void -irange::intersect (const irange &r) +inline bool +irange::intersect (const vrange &r) { dump_flags_t m_flags = dump_flags; dump_flags &= ~TDF_DETAILS; - irange::intersect (&r); + bool ret = irange::legacy_verbose_intersect (&as_a <irange> (r)); dump_flags = m_flags; + return ret; } // Set value range VR to a nonzero range of type TYPE. @@ -582,7 +995,7 @@ irange::set_zero (tree type) { tree z = build_int_cst (type, 0); if (legacy_mode_p ()) - set (z); + set (z, z); else irange_set (z, z); } @@ -593,7 +1006,7 @@ inline void irange::normalize_kind () { if (m_num_ranges == 0) - m_kind = VR_UNDEFINED; + set_undefined (); else if (varying_compatible_p ()) { if (m_kind == VR_RANGE) @@ -617,6 +1030,12 @@ vrp_val_max (const_tree type) wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type)); return wide_int_to_tree (const_cast<tree> (type), max); } + if (frange::supports_p (type)) + { + REAL_VALUE_TYPE real; + real_inf (&real); + return build_real (const_cast <tree> (type), real); + } return NULL_TREE; } @@ -629,79 +1048,74 @@ vrp_val_min (const_tree type) return TYPE_MIN_VALUE (type); if (POINTER_TYPE_P (type)) return build_zero_cst (const_cast<tree> (type)); + if (frange::supports_p (type)) + { + REAL_VALUE_TYPE real, real_ninf; + real_inf (&real); + real_ninf = real_value_negate (&real); + return build_real (const_cast <tree> (type), real_ninf); + } return NULL_TREE; } -// This is the irange storage class. It is used to allocate the -// minimum amount of storage needed for a given irange. Storage is -// automatically freed at destruction of the storage class. -// -// It is meant for long term storage, as opposed to int_range_max -// which is meant for intermediate temporary results on the stack. -// -// The newly allocated irange is initialized to the empty set -// (undefined_p() is true). +// Supporting methods for frange. -class irange_allocator +inline bool +frange_props::operator== (const frange_props &other) const { -public: - irange_allocator (); - ~irange_allocator (); - // Return a new range with NUM_PAIRS. - irange *allocate (unsigned num_pairs); - // Return a copy of SRC with the minimum amount of sub-ranges needed - // to represent it. - irange *allocate (const irange &src); - void *get_memory (unsigned num_bytes); -private: - DISABLE_COPY_AND_ASSIGN (irange_allocator); - struct obstack m_obstack; -}; + return u.bytes == other.u.bytes; +} -inline -irange_allocator::irange_allocator () +inline bool +frange_props::union_ (const frange_props &other) { - obstack_init (&m_obstack); + unsigned char saved = u.bytes; + u.bytes |= other.u.bytes; + return u.bytes != saved; } -inline -irange_allocator::~irange_allocator () +inline bool +frange_props::intersect (const frange_props &other) { - obstack_free (&m_obstack, NULL); + unsigned char saved = u.bytes; + u.bytes &= other.u.bytes; + return u.bytes != saved; } -// Provide a hunk of memory from the obstack. -inline void * -irange_allocator::get_memory (unsigned num_bytes) +inline +frange::frange () { - void *r = obstack_alloc (&m_obstack, num_bytes); - return r; + m_discriminator = VR_FRANGE; + set_undefined (); } -// Return a new range with NUM_PAIRS. - -inline irange * -irange_allocator::allocate (unsigned num_pairs) +inline +frange::frange (const frange &src) { - // Never allocate 0 pairs. - // Don't allocate 1 either, or we get legacy value_range's. - if (num_pairs < 2) - num_pairs = 2; + m_discriminator = VR_FRANGE; + *this = src; +} - size_t nbytes = sizeof (tree) * 2 * num_pairs; +inline tree +frange::type () const +{ + return m_type; +} - // Allocate the irange and required memory for the vector. - void *r = obstack_alloc (&m_obstack, sizeof (irange)); - tree *mem = (tree *) obstack_alloc (&m_obstack, nbytes); - return new (r) irange (mem, num_pairs); +inline void +frange::set_varying (tree type) +{ + m_kind = VR_VARYING; + m_type = type; + m_props.set_varying (); } -inline irange * -irange_allocator::allocate (const irange &src) +inline void +frange::set_undefined () { - irange *r = allocate (src.num_pairs ()); - *r = src; - return r; + m_kind = VR_UNDEFINED; + m_type = NULL; + m_props.set_undefined (); } #endif // GCC_VALUE_RANGE_H |