From: Andrew MacLeod Date: Wed, 11 Feb 2026 15:57:24 +0000 (-0500) Subject: More memory efficient prange_storage. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8f449d2752caff3f8e669b8a9b903fac2eadd1fa;p=thirdparty%2Fgcc.git More memory efficient prange_storage. * value-range-storage.cc (prange_storage::alloc): Use prange_format. (prange_storage::prange_storage): Likewise. (prange_format::prange_format): New. (prange_storage::set_prange): Use prange_foramt and only write required words to storage. (prange_storage::get_prange): Only read required words. (prange_storage::equal_p): Adjust for new enum. (prange_storage::fits_p): Use prange_format to determine size. * value-range-storage.h (enum prange_kind): New. (class prange_format): New. (get_low, get_high, get_value, get_mask): Replace with get_word. (set_low, set_high, set_value, set_mask): Replace with set_word. (get_word): New. (set_word): New. --- diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc index f2f4a5c52f8..7fa104228f7 100644 --- a/gcc/value-range-storage.cc +++ b/gcc/value-range-storage.cc @@ -593,12 +593,8 @@ frange_storage::fits_p (const frange &) const prange_storage * prange_storage::alloc (vrange_internal_alloc &allocator, const prange &r) { - size_t size = sizeof (prange_storage); - if (!r.undefined_p ()) - { - unsigned prec = TYPE_PRECISION (r.type ()); - size += trailing_wide_ints::extra_size (prec); - } + prange_format format (r); + size_t size = sizeof (prange_storage) + format.extra_size; prange_storage *p = static_cast (allocator.alloc (size)); new (p) prange_storage (r); return p; @@ -608,64 +604,163 @@ prange_storage::alloc (vrange_internal_alloc &allocator, const prange &r) prange_storage::prange_storage (const prange &r) { - // It is the caller's responsibility to allocate enough space such - // that the precision fits. + prange_format format (r); + m_trailing_ints.set_precision (format.precision, format.num_words); + set_prange (r); +} + +// FIll the format structure for range R. + +prange_storage::prange_format::prange_format (const prange &r) +{ + kind = PR_UNDEFINED; + has_bitmask = 0; + extra_size = 0; + precision = 0; + num_words = 0; + if (r.undefined_p ()) - // Undefined ranges do not require any extra space for trailing - // wide ints. - m_trailing_ints.set_precision (0); + return; + + if (r.varying_p ()) + { + kind = PR_VARYING; + return; + } + + if (r.zero_p ()) + { + kind = PR_ZERO; + return; + } + + if (r.nonzero_p ()) + kind = PR_NONZERO; else - m_trailing_ints.set_precision (TYPE_PRECISION (r.type ())); + { + prange tmp (r.type ()); + if (r.lower_bound () == tmp.lower_bound () + && r.upper_bound () == tmp.upper_bound ()) + kind = PR_FULL; + else + { + // PR_OTHER requires words of storage for the end points. + kind = PR_OTHER; + num_words += 2; + } + } + precision = TYPE_PRECISION (r.type ()); + has_bitmask = !r.get_bitmask ().unknown_p (); - set_prange (r); + // Bitmasks require 2 words of storage. + if (has_bitmask) + num_words += 2; + + if (num_words != 0) + extra_size = trailing_wide_ints::extra_size (precision, num_words); + + // PR_FULL must have a bitmask, or it should be PR_VARYING. + gcc_checking_assert (kind != PR_FULL || has_bitmask); } void prange_storage::set_prange (const prange &r) { - if (r.undefined_p ()) - m_kind = VR_UNDEFINED; - else if (r.varying_p ()) - m_kind = VR_VARYING; - else + prange_format format (r); + m_kind = format.kind; + m_has_bitmask = format.has_bitmask; + unsigned index = 0; + + switch (m_kind) + { + case PR_UNDEFINED: + case PR_VARYING: + case PR_ZERO: + return; + case PR_NONZERO: + case PR_FULL: + break; + case PR_OTHER: + set_word (index++, r.lower_bound (), r.type ()); + set_word (index++, r.upper_bound (), r.type ()); + break; + default: + gcc_unreachable (); + } + + if (m_has_bitmask) { - m_kind = VR_RANGE; - set_low (r.lower_bound ()); - set_high (r.upper_bound ()); irange_bitmask bm = r.m_bitmask; - set_value (bm.value ()); - set_mask (bm.mask ()); + set_word (index++, r.m_bitmask.value (), r.type ()); + set_word (index++, r.m_bitmask.mask (), r.type ()); } + gcc_checking_assert (index == format.num_words); } void prange_storage::get_prange (prange &r, tree type) const { gcc_checking_assert (r.supports_type_p (type)); + unsigned index = 0; + switch (m_kind) + { + case PR_UNDEFINED: + r.set_undefined (); + return; - if (m_kind == VR_UNDEFINED) - r.set_undefined (); - else if (m_kind == VR_VARYING) - r.set_varying (type); - else + case PR_VARYING: + r.set_varying (type); + return; + + case PR_ZERO: + r.set_zero (type); + return; + + case PR_NONZERO: + r.set_nonzero (type); + break; + + case PR_FULL: + { + r.m_kind = VR_RANGE; + r.m_type = type; + prange tmp (type); + r.m_min = tmp.lower_bound (); + r.m_max = tmp.upper_bound (); + break; + } + + case PR_OTHER: + { + gcc_checking_assert (m_kind == PR_OTHER); + r.m_kind = VR_RANGE; + r.m_type = type; + r.m_min = get_word (index++, type); + r.m_max = get_word (index++, type); + break; + } + default: + gcc_unreachable (); + } + + if (m_has_bitmask) { - gcc_checking_assert (m_kind == VR_RANGE); - gcc_checking_assert (TYPE_PRECISION (type) == m_trailing_ints.get_precision ()); - r.m_kind = VR_RANGE; - r.m_type = type; - r.m_min = get_low (); - r.m_max = get_high (); - r.m_bitmask = irange_bitmask (get_value (), get_mask ()); - if (flag_checking) - r.verify_range (); + wide_int value = get_word (index++, type); + wide_int mask = get_word (index++, type); + r.m_bitmask = irange_bitmask (value, mask); } + else + r.m_bitmask.set_unknown (TYPE_PRECISION (type)); + + if (flag_checking) + r.verify_range (); } bool prange_storage::equal_p (const prange &r) const { if (r.undefined_p ()) - return m_kind == VR_UNDEFINED; + return m_kind == PR_UNDEFINED; prange tmp; get_prange (tmp, r.type ()); @@ -680,7 +775,11 @@ prange_storage::fits_p (const prange &r) const if (r.undefined_p ()) return true; - return TYPE_PRECISION (r.type ()) <= m_trailing_ints.get_precision (); + prange_format f (r); + unsigned prec = m_trailing_ints.get_precision (); + unsigned num = m_trailing_ints.num_elements (); + size_t curr = num ? trailing_wide_ints::extra_size (prec, num) : 0; + return f.extra_size <= curr; } diff --git a/gcc/value-range-storage.h b/gcc/value-range-storage.h index e7a5700c142..78a6f4efb62 100644 --- a/gcc/value-range-storage.h +++ b/gcc/value-range-storage.h @@ -113,19 +113,35 @@ private: DISABLE_COPY_AND_ASSIGN (prange_storage); prange_storage (const prange &r); - enum value_range_kind m_kind : 3; + // A prange_format class summarizes the storage requirements for a prange + // which are then used to initialize the prange_storage fields. + enum prange_kind { PR_UNDEFINED, // VR_UNDEFINED + PR_VARYING, // VR_VARYING + PR_ZERO, // [0, 0] + PR_NONZERO, // [1, +INF] + PR_FULL, // [0, +INF] (Must have bitmask) + PR_OTHER }; // [x, y] + class prange_format + { + public: + prange_format (const prange &r); + enum prange_kind kind; + bool has_bitmask; + size_t extra_size; + unsigned short precision; + unsigned num_words; + }; + + enum prange_kind m_kind; + bool m_has_bitmask; // We don't use TRAILING_WIDE_INT_ACCESSOR because the getters here // must be const. Perhaps TRAILING_WIDE_INT_ACCESSOR could be made // const and return wide_int instead of trailing_wide_int. - wide_int get_low () const { return m_trailing_ints[0]; } - wide_int get_high () const { return m_trailing_ints[1]; } - wide_int get_value () const { return m_trailing_ints[2]; } - wide_int get_mask () const { return m_trailing_ints[3]; } - template void set_low (const T &x) { m_trailing_ints[0] = x; } - template void set_high (const T &x) { m_trailing_ints[1] = x; } - template void set_value (const T &x) { m_trailing_ints[2] = x; } - template void set_mask (const T &x) { m_trailing_ints[3] = x; } + wide_int get_word (unsigned i, tree) const + { return m_trailing_ints[i]; } + template void set_word (unsigned i, const T &x, tree) + { m_trailing_ints[i] = x; } static const unsigned int NINTS = 4; trailing_wide_ints m_trailing_ints;