From: Aldy Hernandez Date: Tue, 28 Jul 2026 11:23:16 +0000 (+0000) Subject: [frange] Rewrite intersect to meet sub-ranges pairwise. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eb2a693190a71c5671de024dd4a0e4f961ef8b87;p=thirdparty%2Fgcc.git [frange] Rewrite intersect to meet sub-ranges pairwise. Replace the single-interval intersect with a sub-range aware one. MAX_PAIRS is still 1, so the cross product yields at most one piece. No functional change, for now. Tested on ppc64le: regstrap, LAPACK, no changes on a corpus of Fortran files. gcc/ChangeLog: * value-range.cc (frange_min, frange_max): New. (frange::intersect_nans): Use set_nan. (frange::intersect): Meet every sub-range against every other. --- diff --git a/gcc/value-range.cc b/gcc/value-range.cc index ac8096746e3..472ff37a1df 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -1013,6 +1013,18 @@ frange_cmp (const REAL_VALUE_TYPE &a, const REAL_VALUE_TYPE &b) return 0; } +static inline const REAL_VALUE_TYPE & +frange_min (const REAL_VALUE_TYPE &a, const REAL_VALUE_TYPE &b) +{ + return frange_cmp (a, b) <= 0 ? a : b; +} + +static inline const REAL_VALUE_TYPE & +frange_max (const REAL_VALUE_TYPE &a, const REAL_VALUE_TYPE &b) +{ + return frange_cmp (a, b) >= 0 ? a : b; +} + // Return TRUE if [..., A_MAX] and [B_MIN, ...] can be fused into one interval, // either because they overlap or because no representable value exists between // them. The latter is how -0.0 and +0.0 abut: there is nothing in between, so @@ -1347,11 +1359,9 @@ frange::intersect_nans (const frange &r) m_pos_nan &= r.m_pos_nan; m_neg_nan &= r.m_neg_nan; if (maybe_isnan ()) - m_kind = VR_NAN; + set_nan (m_type, get_nan_state ()); else set_undefined (); - if (flag_checking) - verify_range (); return true; } @@ -1376,43 +1386,44 @@ frange::intersect (const vrange &v) // Combine NAN info. if (known_isnan () || r.known_isnan ()) return intersect_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. - if (frange_cmp (m_pairs[0].min, r.m_pairs[0].min) < 0) - { - m_pairs[0].min = r.m_pairs[0].min; - changed = true; - } - if (frange_cmp (r.m_pairs[0].max, 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; - // FIXME: Rewrite for sub-ranges. - // If the endpoints are swapped, the resulting range is empty. This also - // catches [+0.0, -0.0], which is also empty. - if (frange_cmp (m_pairs[0].max, m_pairs[0].min) < 0) + // Meet every sub-range against every other. Two sorted, disjoint sets of at + // most MAX_PAIRS each cannot yield more than MAX_PAIRS^2 pieces. + // + // NOTE: Since both operands are sorted, a merge-style meet like irange would + // be O(n) and leave set_pairs nothing to sort. Not worth it while MAX_PAIRS + // is tiny; revisit if it grows. + frange_pair pairs[MAX_PAIRS * MAX_PAIRS]; + unsigned n = 0; + for (unsigned i = 0; i < save.m_num_ranges; ++i) + for (unsigned j = 0; j < r.m_num_ranges; ++j) + { + const REAL_VALUE_TYPE &min + = frange_max (save.m_pairs[i].min, r.m_pairs[j].min); + const REAL_VALUE_TYPE &max + = frange_min (save.m_pairs[i].max, r.m_pairs[j].max); + // A reversed interval means these two do not overlap. This also + // catches [+0.0, -0.0], which is empty rather than nonsensical. + if (frange_cmp (min, max) <= 0) + pairs[n++] = { min, max }; + } + + // Nothing but a possible NAN survives. + if (n == 0) { if (maybe_isnan ()) - m_kind = VR_NAN; + set_nan (m_type, get_nan_state ()); else set_undefined (); - if (flag_checking) - verify_range (); return true; } - changed |= normalize_kind (); - return changed; + set_pairs (pairs, n); + return *this != save; } frange &