[gcc r17-2829] [frange] Store sub-ranges in a variable-length trailing array.

Aldy Hernandez via Gcc-cvs <[email protected]> Thu, 30 Jul 2026 14:05:55 +0000 (GMT)
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:80ade12f5384a27fbed0717fcee9c39427f9f989

commit r17-2829-g80ade12f5384a27fbed0717fcee9c39427f9f989
Author: Aldy Hernandez <[email protected]>
Date:   Wed Jul 29 17:59:02 2026 +0000

    [frange] Store sub-ranges in a variable-length trailing array.
    
    frange_storage held a fixed frange_pair m_pairs[MAX_PAIRS], so every
    cached range reserved space for MAX_PAIRS sub-ranges even though the
    large majority hold one.  Mirror irange_storage: a trailing frange_pair
    array that alloc () sizes to the range's actual num_pairs ().
    
    Tested on ppc64le Linux.  The usual regstrap, LAPACK, Fortran assembly
    checks for no functional changes apply.
    
    gcc/ChangeLog:
    
            * value-range-storage.h (class frange_storage): Replace the fixed
            m_pairs[MAX_PAIRS] with a variable-length trailing array and an
            m_max_ranges capacity; declare size and the constructor.
            * value-range-storage.cc (frange_storage::size): New.
            (frange_storage::alloc): Allocate size (r) bytes.
            (frange_storage::frange_storage): New; record m_max_ranges.
            (frange_storage::fits_p): Check m_max_ranges.

Diff:
---
 gcc/value-range-storage.cc | 22 ++++++++++++++++++----
 gcc/value-range-storage.h  |  8 +++++---
 2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc
index 153a2aecb48f..c64bf09e9fe1 100644
--- a/gcc/value-range-storage.cc
+++ b/gcc/value-range-storage.cc
@@ -507,17 +507,31 @@ debug (const irange_storage &storage)
 // frange_storage implementation
 //============================================================================
 
+// Return the number of bytes to allocate for an frange_storage holding R.
+
+size_t
+frange_storage::size (const frange &r)
+{
+  return sizeof (frange_storage) + (r.num_pairs () - 1) * sizeof (frange_pair);
+}
+
 // Allocate a new frange_storage object initialized to R.
 
 frange_storage *
 frange_storage::alloc (vrange_internal_alloc &allocator, const frange &r)
 {
-  size_t size = sizeof (frange_storage);
-  frange_storage *p = static_cast <frange_storage *> (allocator.alloc (size));
+  frange_storage *p
+    = static_cast <frange_storage *> (allocator.alloc (size (r)));
   new (p) frange_storage (r);
   return p;
 }
 
+frange_storage::frange_storage (const frange &r)
+  : vrange_storage (VR_FRANGE), m_max_ranges (r.num_pairs ())
+{
+  set_frange (r);
+}
+
 void
 frange_storage::set_frange (const frange &r)
 {
@@ -584,9 +598,9 @@ frange_storage::equal_p (const frange &r) const
 }
 
 bool
-frange_storage::fits_p (const frange &) const
+frange_storage::fits_p (const frange &r) const
 {
-  return true;
+  return m_max_ranges >= r.num_pairs ();
 }
 
 //============================================================================
diff --git a/gcc/value-range-storage.h b/gcc/value-range-storage.h
index a7369d1eb0f7..6c2838eecc82 100644
--- a/gcc/value-range-storage.h
+++ b/gcc/value-range-storage.h
@@ -162,15 +162,17 @@ class GTY((tag ("VR_FRANGE"))) frange_storage : public vrange_storage
   bool equal_p (const frange &r) const;
   bool fits_p (const frange &) const;
  private:
-  frange_storage (const frange &r) : vrange_storage (VR_FRANGE)
-    { set_frange (r); }
+  frange_storage (const frange &r);
   DISABLE_COPY_AND_ASSIGN (frange_storage);
+  static size_t size (const frange &r);
 
   enum value_range_kind m_kind;
-  frange_pair m_pairs[frange::MAX_PAIRS];
+  // The max number of sub-ranges that fit in this storage.
+  const unsigned char m_max_ranges;
   unsigned char m_num_ranges;
   bool m_pos_nan;
   bool m_neg_nan;
+  frange_pair m_pairs[1];
 };
 
 extern vrange_storage *ggc_alloc_vrange_storage (tree type);