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.

After this, all the pieces are in place to throw the switch for
sub-ranges (MAX_PAIRS=2), and then implement the inverse of a constant
range (for example, nonzero).

I'm going to give this all weekend to settle, before I enable
sub-ranges.

Pushed.

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.
---
 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 153a2aecb48..c64bf09e9fe 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 a7369d1eb0f..6c2838eecc8 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);
-- 
2.47.3

Reply via email to