[gcc r17-2828] [frange] Rewrite union to merge sub-ranges.

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

commit r17-2828-g8cfdd1ed0f0da83a8426ac6a30e33dc945fbfcde
Author: Aldy Hernandez <[email protected]>
Date:   Thu Jul 30 08:55:14 2026 +0000

    [frange] Rewrite union to merge sub-ranges.
    
    Replace the single-interval union_ with a sub-range aware one.
    
    Like the intersect rewrite, do this ahead of raising MAX_PAIRS.  It is
    still 1, so set_pairs collapses the result back to a single range.  No
    functional change.
    
    Tested on ppc64le: regstrap, LAPACK, no changes on a corpus of Fortran
    files.
    
    gcc/ChangeLog:
    
            * value-range.cc (frange::union_): Merge both operands' sub-ranges
            via set_pairs instead of widening to the hull.

Diff:
---
 gcc/value-range.cc | 39 ++++++++++++++++++---------------------
 1 file changed, 18 insertions(+), 21 deletions(-)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 472ff37a1df2..18aa82733a4b 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -1324,29 +1324,26 @@ frange::union_ (const vrange &v)
   // Combine NAN info.
   if (known_isnan () || r.known_isnan ())
     return union_nans (r);
-  bool changed = false;
-  if (m_pos_nan != r.m_pos_nan || m_neg_nan != r.m_neg_nan)
-    {
-      m_pos_nan |= r.m_pos_nan;
-      m_neg_nan |= r.m_neg_nan;
-      changed = true;
-    }
 
-  // FIXME: Rewrite for sub-ranges.
-  // Combine endpoints.  This needs to be rewritten for sub-ranges.
-  if (frange_cmp (r.m_pairs[0].min, m_pairs[0].min) < 0)
-    {
-      m_pairs[0].min = r.m_pairs[0].min;
-      changed = true;
-    }
-  if (frange_cmp (m_pairs[0].max, r.m_pairs[0].max) < 0)
-    {
-      m_pairs[0].max = r.m_pairs[0].max;
-      changed = true;
-    }
+  frange save = *this;
+  m_pos_nan |= r.m_pos_nan;
+  m_neg_nan |= r.m_neg_nan;
 
-  changed |= normalize_kind ();
-  return changed;
+  // Throw both operands' sub-ranges into the pot as set_pairs will
+  // canonicalize things and hand us back at most MAX_PAIRS.
+  //
+  // NOTE: Both operands are already sorted and disjoint, so a merge could
+  // combine them in O(n) like irange::union_ rather than have set_pairs
+  // re-sort.  Not worth it while MAX_PAIRS is tiny; revisit if it grows.
+  frange_pair pairs[2 * MAX_PAIRS];
+  unsigned n = 0;
+  for (unsigned i = 0; i < save.m_num_ranges; ++i)
+    pairs[n++] = save.m_pairs[i];
+  for (unsigned i = 0; i < r.m_num_ranges; ++i)
+    pairs[n++] = r.m_pairs[i];
+
+  set_pairs (pairs, n);
+  return *this != save;
 }
 
 // Intersect two ranges when one is known to be a NAN.