]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
More memory efficient prange_storage.
authorAndrew MacLeod <amacleod@redhat.com>
Wed, 11 Feb 2026 15:57:24 +0000 (10:57 -0500)
committerAndrew MacLeod <amacleod@redhat.com>
Wed, 6 May 2026 13:43:43 +0000 (09:43 -0400)
* 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.

gcc/value-range-storage.cc
gcc/value-range-storage.h

index f2f4a5c52f8a60f73e3be2b4db744fb86debb9e9..7fa104228f76feeaba68c3a85ffdb129567813eb 100644 (file)
@@ -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<NINTS>::extra_size (prec);
-    }
+  prange_format format (r);
+  size_t size = sizeof (prange_storage) + format.extra_size;
   prange_storage *p = static_cast <prange_storage *> (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<NINTS>::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<NINTS>::extra_size (prec, num) : 0;
+  return f.extra_size <= curr;
 }
 
 \f
index e7a5700c142da39e46ada45b2f91a67ca89f969f..78a6f4efb623f31ab5451895fae57154936bd174 100644 (file)
@@ -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 <typename T> void set_low (const T &x) { m_trailing_ints[0] = x; }
-  template <typename T> void set_high (const T &x) { m_trailing_ints[1] = x; }
-  template <typename T> void set_value (const T &x) { m_trailing_ints[2] = x; }
-  template <typename T> 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 <typename T> void set_word (unsigned i, const T &x, tree)
+    { m_trailing_ints[i] = x; }
 
   static const unsigned int NINTS = 4;
   trailing_wide_ints<NINTS> m_trailing_ints;