To prepare for holding more than one sub-range, move the endpoints
m_min/m_max into a one-element array.
While here, pick the low-hanging multi-range fruit so the follow-up
patches stay small: consumers that walk every sub-range now loop over
m_num_ranges, and the inherently single-range ones (normalize_kind,
singleton_p, etc) gain an m_num_ranges == 1 guard. The hard cases
(union_/intersect, etc) are left with FIXMEs for later.
No change to functionality as MAX_PAIRS is 1. I'll bump this to 2 in
a subequent patch, and implement union/intersect and all the other
little things.
Tested on ppc64le Linux. No change to assembly over the LAPACK
preprocessed-Fortran corpus; LAPACK and GCC tests pass.
p.s. I'll give folks a few days to comment, and if nothing comes up,
I'll commit at the end of the week. We're still in the relatively
trivial parts of the set. The hard part comes next.
gcc/ChangeLog:
* value-range.h (struct frange_pair): New.
(class frange): Replace m_min and m_max with m_pairs[MAX_PAIRS]
and m_num_ranges. Add MAX_PAIRS, num_pairs, and the indexed
lower_bound and upper_bound. Have canonicalize_zeros take an
frange_pair.
(frange::lower_bound, frange::upper_bound): Adjust.
(frange::set_varying, frange::set_undefined, frange::set_nan)
(frange::known_isfinite, frange::known_isnormal)
(frange::known_isdenormal_or_zero, frange::maybe_isinf)
(frange::known_isinf, frange::signbit_p): Adjust.
* value-range.cc (frange::flush_denormals_to_zero): Adjust.
(frange::canonicalize_zeros): Take an frange_pair.
(frange::set, frange::normalize_kind, frange::union_nans)
(frange::union_, frange::intersect, frange::operator=)
(frange::operator==, frange::contains_p)
(frange::internal_singleton_p, frange::singleton_p)
(frange::verify_range, frange::zero_p): Adjust.
* value-range-storage.h (class frange_storage): Replace m_min
and m_max with m_pairs and m_num_ranges.
* value-range-storage.cc (frange_storage::set_frange): Adjust.
(frange_storage::get_frange): Adjust.
---
gcc/value-range-storage.cc | 17 ++--
gcc/value-range-storage.h | 4 +-
gcc/value-range.cc | 175 ++++++++++++++++++++++---------------
gcc/value-range.h | 84 +++++++++++++-----
4 files changed, 175 insertions(+), 105 deletions(-)
diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc
index 837c40bb72e..6f8b53814a8 100644
--- a/gcc/value-range-storage.cc
+++ b/gcc/value-range-storage.cc
@@ -524,8 +524,9 @@ frange_storage::set_frange (const frange &r)
gcc_checking_assert (fits_p (r));
m_kind = r.m_kind;
- m_min = r.m_min;
- m_max = r.m_max;
+ m_num_ranges = r.m_num_ranges;
+ for (unsigned i = 0; i < r.m_num_ranges; ++i)
+ m_pairs[i] = r.m_pairs[i];
m_pos_nan = r.m_pos_nan;
m_neg_nan = r.m_neg_nan;
}
@@ -555,13 +556,11 @@ frange_storage::get_frange (frange &r, tree type) const
return;
}
- // We use the constructor to create the new range instead of writing
- // out the bits into the frange directly, because the global range
- // being read may be being inlined into a function with different
- // restrictions as when it was originally written. We want to make
- // sure the resulting range is canonicalized correctly for the new
- // consumer.
- r = frange (type, m_min, m_max, m_kind);
+ // FIXME: Rewrite for sub-ranges. This only reconstructs the first pair.
+ // Eventually do it piecewise like irange_storage::get_irange: start
+ // undefined and union each sub-range built through the constructor (so
+ // every piece is re-canonicalized).
+ r = frange (type, m_pairs[0].min, m_pairs[0].max, m_kind);
// The constructor will set the NAN bits for HONOR_NANS, but we must
// make sure to set the NAN sign if known.
diff --git a/gcc/value-range-storage.h b/gcc/value-range-storage.h
index e289765cfe0..a7369d1eb0f 100644
--- a/gcc/value-range-storage.h
+++ b/gcc/value-range-storage.h
@@ -167,8 +167,8 @@ class GTY((tag ("VR_FRANGE"))) frange_storage : public
vrange_storage
DISABLE_COPY_AND_ASSIGN (frange_storage);
enum value_range_kind m_kind;
- REAL_VALUE_TYPE m_min;
- REAL_VALUE_TYPE m_max;
+ frange_pair m_pairs[frange::MAX_PAIRS];
+ unsigned char m_num_ranges;
bool m_pos_nan;
bool m_neg_nan;
};
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 4e1be3b0ed6..09381e62602 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -1023,6 +1023,7 @@ frange::flush_denormals_to_zero ()
machine_mode mode = TYPE_MODE (type ());
+ // FIXME: Rewrite for sub-ranges.
// Flush a denormal endpoint to a zero of the same sign: a +denormal lower
// bound to +0.0, and a -denormal upper bound to -0.0. Then call
// canonicalize_zeros to rewrite the sign to whatever the flags make
@@ -1033,15 +1034,15 @@ frange::flush_denormals_to_zero ()
//
// keeping contains_p (-0.0) true; under HONOR_SIGNED_ZEROS the sign stands
and
// it stays [ +0.0, 5.0 ].
- if (real_isdenormal (&m_max, mode) && real_isneg (&m_max))
- m_max = dconstm0;
- if (real_isdenormal (&m_min, mode) && !real_isneg (&m_min))
- m_min = dconst0;
- canonicalize_zeros (m_min, m_max);
+ if (real_isdenormal (&m_pairs[0].max, mode) && real_isneg (&m_pairs[0].max))
+ m_pairs[0].max = dconstm0;
+ if (real_isdenormal (&m_pairs[0].min, mode) && !real_isneg (&m_pairs[0].min))
+ m_pairs[0].min = dconst0;
+ canonicalize_zeros (m_pairs[0]);
}
-// Canonicalize the signed zeros of the endpoints MIN and MAX according with
what
-// the target and flags want:
+// Canonicalize the signed zeros of a sub-range according with what the target
+// and flags want:
//
// !MODE_HAS_SIGNED_ZEROS: the mode has no signed zero, so any zero is +0.0.
//
@@ -1051,21 +1052,21 @@ frange::flush_denormals_to_zero ()
// Otherwise the sign is a real distinction, and we keep it.
void
-frange::canonicalize_zeros (REAL_VALUE_TYPE &min, REAL_VALUE_TYPE &max)
+frange::canonicalize_zeros (frange_pair &p)
{
if (!MODE_HAS_SIGNED_ZEROS (TYPE_MODE (m_type)))
{
- if (real_iszero (&min, 1))
- min.sign = 0;
- if (real_iszero (&max, 1))
- max.sign = 0;
+ if (real_iszero (&p.min, 1))
+ p.min.sign = 0;
+ if (real_iszero (&p.max, 1))
+ p.max.sign = 0;
}
else if (!HONOR_SIGNED_ZEROS (m_type))
{
- if (real_iszero (&max, 1))
- max.sign = 0;
- if (real_iszero (&min, 0))
- min.sign = 1;
+ if (real_iszero (&p.max, 1))
+ p.max.sign = 0;
+ if (real_iszero (&p.min, 0))
+ p.min.sign = 1;
}
}
@@ -1095,8 +1096,9 @@ frange::set (tree type,
m_kind = kind;
m_type = type;
- m_min = min;
- m_max = max;
+ m_num_ranges = 1;
+ m_pairs[0].min = min;
+ m_pairs[0].max = max;
if (HONOR_NANS (m_type))
{
m_pos_nan = nan.pos_p ();
@@ -1108,7 +1110,7 @@ frange::set (tree type,
m_neg_nan = false;
}
- canonicalize_zeros (m_min, m_max);
+ canonicalize_zeros (m_pairs[0]);
// For -ffinite-math-only we can drop ranges outside the
// representable numbers to min/max for the type.
@@ -1116,14 +1118,14 @@ frange::set (tree type,
{
REAL_VALUE_TYPE min_repr = frange_val_min (m_type);
REAL_VALUE_TYPE max_repr = frange_val_max (m_type);
- if (real_less (&m_min, &min_repr))
- m_min = min_repr;
- else if (real_less (&max_repr, &m_min))
- m_min = max_repr;
- if (real_less (&max_repr, &m_max))
- m_max = max_repr;
- else if (real_less (&m_max, &min_repr))
- m_max = min_repr;
+ if (real_less (&m_pairs[0].min, &min_repr))
+ m_pairs[0].min = min_repr;
+ else if (real_less (&max_repr, &m_pairs[0].min))
+ m_pairs[0].min = max_repr;
+ if (real_less (&max_repr, &m_pairs[0].max))
+ m_pairs[0].max = max_repr;
+ else if (real_less (&m_pairs[0].max, &min_repr))
+ m_pairs[0].max = min_repr;
}
// Check for swapped ranges.
@@ -1162,8 +1164,9 @@ bool
frange::normalize_kind ()
{
if (m_kind == VR_RANGE
- && frange_val_is_min (m_min, m_type)
- && frange_val_is_max (m_max, m_type))
+ && m_num_ranges == 1
+ && frange_val_is_min (m_pairs[0].min, m_type)
+ && frange_val_is_max (m_pairs[0].max, m_type))
{
if (!HONOR_NANS (m_type) || (m_pos_nan && m_neg_nan))
{
@@ -1176,8 +1179,9 @@ frange::normalize_kind ()
if (HONOR_NANS (m_type) && (!m_pos_nan || !m_neg_nan))
{
m_kind = VR_RANGE;
- m_min = frange_val_min (m_type);
- m_max = frange_val_max (m_type);
+ m_num_ranges = 1;
+ m_pairs[0].min = frange_val_min (m_type);
+ m_pairs[0].max = frange_val_max (m_type);
if (flag_checking)
verify_range ();
return true;
@@ -1199,8 +1203,9 @@ frange::union_nans (const frange &r)
if (known_isnan () && m_kind != r.m_kind)
{
m_kind = r.m_kind;
- m_min = r.m_min;
- m_max = r.m_max;
+ m_num_ranges = r.m_num_ranges;
+ for (unsigned i = 0; i < r.m_num_ranges; ++i)
+ m_pairs[i] = r.m_pairs[i];
changed = true;
}
if (m_pos_nan != r.m_pos_nan || m_neg_nan != r.m_neg_nan)
@@ -1241,15 +1246,16 @@ frange::union_ (const vrange &v)
changed = true;
}
- // Combine endpoints.
- if (frange_cmp (r.m_min, m_min) < 0)
+ // 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_min = r.m_min;
+ m_pairs[0].min = r.m_pairs[0].min;
changed = true;
}
- if (frange_cmp (m_max, r.m_max) < 0)
+ if (frange_cmp (m_pairs[0].max, r.m_pairs[0].max) < 0)
{
- m_max = r.m_max;
+ m_pairs[0].max = r.m_pairs[0].max;
changed = true;
}
@@ -1304,21 +1310,23 @@ frange::intersect (const vrange &v)
changed = true;
}
+ // FIXME: Rewrite for sub-ranges.
// Combine endpoints.
- if (frange_cmp (m_min, r.m_min) < 0)
+ if (frange_cmp (m_pairs[0].min, r.m_pairs[0].min) < 0)
{
- m_min = r.m_min;
+ m_pairs[0].min = r.m_pairs[0].min;
changed = true;
}
- if (frange_cmp (r.m_max, m_max) < 0)
+ if (frange_cmp (r.m_pairs[0].max, m_pairs[0].max) < 0)
{
- m_max = r.m_max;
+ m_pairs[0].max = r.m_pairs[0].max;
changed = true;
}
+ // 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_max, m_min) < 0)
+ if (frange_cmp (m_pairs[0].max, m_pairs[0].min) < 0)
{
if (maybe_isnan ())
m_kind = VR_NAN;
@@ -1338,8 +1346,9 @@ frange::operator= (const frange &src)
{
m_kind = src.m_kind;
m_type = src.m_type;
- m_min = src.m_min;
- m_max = src.m_max;
+ m_num_ranges = src.m_num_ranges;
+ for (unsigned i = 0; i < src.m_num_ranges; ++i)
+ m_pairs[i] = src.m_pairs[i];
m_pos_nan = src.m_pos_nan;
m_neg_nan = src.m_neg_nan;
@@ -1369,9 +1378,14 @@ frange::operator== (const frange &src) const
return false;
}
- return (real_identical (&m_min, &src.m_min)
- && real_identical (&m_max, &src.m_max)
- && m_pos_nan == src.m_pos_nan
+ if (m_num_ranges != src.m_num_ranges)
+ return false;
+ for (unsigned i = 0; i < m_num_ranges; ++i)
+ if (!real_identical (&m_pairs[i].min, &src.m_pairs[i].min)
+ || !real_identical (&m_pairs[i].max, &src.m_pairs[i].max))
+ return false;
+
+ return (m_pos_nan == src.m_pos_nan
&& m_neg_nan == src.m_neg_nan
&& types_compatible_p (m_type, src.m_type));
}
@@ -1404,7 +1418,12 @@ frange::contains_p (const REAL_VALUE_TYPE &r) const
if (known_isnan ())
return false;
- return frange_cmp (r, m_min) >= 0 && frange_cmp (r, m_max) <= 0;
+ for (unsigned i = 0; i < m_num_ranges; ++i)
+ if (frange_cmp (r, m_pairs[i].min) >= 0
+ && frange_cmp (r, m_pairs[i].max) <= 0)
+ return true;
+
+ return false;
}
// If range is a singleton, place it in RESULT and return TRUE. If
@@ -1415,7 +1434,9 @@ frange::contains_p (const REAL_VALUE_TYPE &r) const
bool
frange::internal_singleton_p (REAL_VALUE_TYPE *result) const
{
- if (m_kind == VR_RANGE && real_identical (&m_min, &m_max))
+ if (m_kind == VR_RANGE
+ && m_num_ranges == 1
+ && real_identical (&m_pairs[0].min, &m_pairs[0].max))
{
// Return false for any singleton that may be a NAN.
if (HONOR_NANS (m_type) && maybe_isnan ())
@@ -1428,16 +1449,16 @@ frange::internal_singleton_p (REAL_VALUE_TYPE *result)
const
// or -0.0. Since this means there is more than one way to
// represent a value, return false to avoid propagating it.
// See libgcc/config/rs6000/ibm-ldouble-format for details.
- if (real_isinf (&m_min))
+ if (real_isinf (&m_pairs[0].min))
return false;
REAL_VALUE_TYPE r;
- real_convert (&r, DFmode, &m_min);
- if (real_identical (&r, &m_min))
+ real_convert (&r, DFmode, &m_pairs[0].min);
+ if (real_identical (&r, &m_pairs[0].min))
return false;
}
if (result)
- *result = m_min;
+ *result = m_pairs[0].min;
return true;
}
return false;
@@ -1449,7 +1470,7 @@ frange::singleton_p (tree *result) const
if (internal_singleton_p ())
{
if (result)
- *result = build_real (m_type, m_min);
+ *result = build_real (m_type, m_pairs[0].min);
return true;
}
return false;
@@ -1479,8 +1500,9 @@ frange::verify_range () const
return;
case VR_VARYING:
gcc_checking_assert (m_type);
- gcc_checking_assert (frange_val_is_min (m_min, m_type));
- gcc_checking_assert (frange_val_is_max (m_max, m_type));
+ gcc_checking_assert (m_num_ranges == 1);
+ gcc_checking_assert (frange_val_is_min (m_pairs[0].min, m_type));
+ gcc_checking_assert (frange_val_is_max (m_pairs[0].max, m_type));
if (HONOR_NANS (m_type))
gcc_checking_assert (m_pos_nan && m_neg_nan);
else
@@ -1497,24 +1519,32 @@ frange::verify_range () const
gcc_unreachable ();
}
- // NANs cannot appear in the endpoints of a range.
- gcc_checking_assert (!real_isnan (&m_min) && !real_isnan (&m_max));
+ for (unsigned i = 0; i < m_num_ranges; ++i)
+ {
+ // NANs cannot appear in the endpoints of a range.
+ gcc_checking_assert (!real_isnan (&m_pairs[i].min)
+ && !real_isnan (&m_pairs[i].max));
- // Make sure we don't have swapped ranges. This also catches [ +0.0, -0.0].
- gcc_checking_assert (frange_cmp (m_min, m_max) <= 0);
+ // Make sure we don't have swapped ranges.
+ // This also catches [ +0.0, -0.0].
+ gcc_checking_assert (frange_cmp (m_pairs[i].min, m_pairs[i].max) <= 0);
- // A zero endpoint must carry its canonical sign. Every producer runs
- // canonicalize_zeros, so a zero bound can only descend from a canonical one.
- if (!MODE_HAS_SIGNED_ZEROS (TYPE_MODE (m_type)))
- gcc_checking_assert (!real_iszero (&m_min, 1) && !real_iszero (&m_max, 1));
- else if (!HONOR_SIGNED_ZEROS (m_type))
- gcc_checking_assert (!real_iszero (&m_min, 0) && !real_iszero (&m_max, 1));
+ // A zero endpoint must carry its canonical sign. Every producer runs
+ // canonicalize_zeros, so a zero bound can only descend from a canonical
+ // one.
+ if (!MODE_HAS_SIGNED_ZEROS (TYPE_MODE (m_type)))
+ gcc_checking_assert (!real_iszero (&m_pairs[i].min, 1)
+ && !real_iszero (&m_pairs[i].max, 1));
+ else if (!HONOR_SIGNED_ZEROS (m_type))
+ gcc_checking_assert (!real_iszero (&m_pairs[i].min, 0)
+ && !real_iszero (&m_pairs[i].max, 1));
+ }
// If all the properties are clear, we better not span the entire
// domain, because that would make us varying.
- if (m_pos_nan && m_neg_nan)
- gcc_checking_assert (!frange_val_is_min (m_min, m_type)
- || !frange_val_is_max (m_max, m_type));
+ if (m_num_ranges == 1 && m_pos_nan && m_neg_nan)
+ gcc_checking_assert (!frange_val_is_min (m_pairs[0].min, m_type)
+ || !frange_val_is_max (m_pairs[0].max, m_type));
}
// We can't do much with nonzeros yet.
@@ -1552,8 +1582,9 @@ bool
frange::zero_p () const
{
return (m_kind == VR_RANGE
- && real_iszero (&m_min)
- && real_iszero (&m_max));
+ && m_num_ranges == 1
+ && real_iszero (&m_pairs[0].min)
+ && real_iszero (&m_pairs[0].max));
}
// Set the range to non-negative numbers, that is [+0.0, +INF].
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 5bea3cbc9d4..2ea0006ba9f 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -584,10 +584,18 @@ nan_state::neg_p () const
return m_neg_nan;
}
+// A sub-range in an frange.
+
+struct frange_pair
+{
+ REAL_VALUE_TYPE min;
+ REAL_VALUE_TYPE max;
+};
+
// A subset of possible values for a floating point type.
//
-// The representation is a type with a couple of endpoints, unioned
-// with a subset of { -NaN, +NaN }.
+// The representation is a single interval, unioned with a subset of
+// { -NaN, +NaN }.
class frange final : public vrange
{
@@ -657,6 +665,11 @@ public:
bool known_isnormal () const;
bool known_isdenormal_or_zero () const;
virtual void verify_range () const override;
+
+ static const unsigned int MAX_PAIRS = 1;
+ unsigned num_pairs () const { return m_num_ranges; }
+ const REAL_VALUE_TYPE &lower_bound (unsigned pair) const;
+ const REAL_VALUE_TYPE &upper_bound (unsigned pair) const;
protected:
virtual bool contains_p (tree cst) const override;
virtual void set (tree, tree, value_range_kind = VR_RANGE) override;
@@ -666,11 +679,11 @@ private:
bool normalize_kind ();
bool union_nans (const frange &);
bool intersect_nans (const frange &);
- void canonicalize_zeros (REAL_VALUE_TYPE &, REAL_VALUE_TYPE &);
+ void canonicalize_zeros (frange_pair &);
tree m_type;
- REAL_VALUE_TYPE m_min;
- REAL_VALUE_TYPE m_max;
+ frange_pair m_pairs[MAX_PAIRS];
+ unsigned char m_num_ranges;
bool m_pos_nan;
bool m_neg_nan;
};
@@ -679,14 +692,30 @@ inline const REAL_VALUE_TYPE &
frange::lower_bound () const
{
gcc_checking_assert (!undefined_p () && !known_isnan ());
- return m_min;
+ return m_pairs[0].min;
}
inline const REAL_VALUE_TYPE &
frange::upper_bound () const
{
gcc_checking_assert (!undefined_p () && !known_isnan ());
- return m_max;
+ return m_pairs[m_num_ranges - 1].max;
+}
+
+inline const REAL_VALUE_TYPE &
+frange::lower_bound (unsigned pair) const
+{
+ gcc_checking_assert (!undefined_p () && !known_isnan ());
+ gcc_checking_assert (pair < m_num_ranges);
+ return m_pairs[pair].min;
+}
+
+inline const REAL_VALUE_TYPE &
+frange::upper_bound (unsigned pair) const
+{
+ gcc_checking_assert (!undefined_p () && !known_isnan ());
+ gcc_checking_assert (pair < m_num_ranges);
+ return m_pairs[pair].max;
}
// Return the NAN state.
@@ -1634,8 +1663,9 @@ frange::set_varying (tree type)
{
m_kind = VR_VARYING;
m_type = type;
- m_min = frange_val_min (type);
- m_max = frange_val_max (type);
+ m_num_ranges = 1;
+ m_pairs[0].min = frange_val_min (type);
+ m_pairs[0].max = frange_val_max (type);
if (HONOR_NANS (m_type))
{
m_pos_nan = true;
@@ -1653,9 +1683,10 @@ frange::set_undefined ()
{
m_kind = VR_UNDEFINED;
m_type = NULL;
+ m_num_ranges = 1;
m_pos_nan = false;
m_neg_nan = false;
- // m_min and m_min are uninitialized as they are REAL_VALUE_TYPE ??.
+ // Leave the rest undefined; as it speeds up initializing undefined ranges.
if (flag_checking)
verify_range ();
}
@@ -1789,6 +1820,7 @@ frange::set_nan (tree type, const nan_state &nan)
{
m_kind = VR_NAN;
m_type = type;
+ m_num_ranges = 1;
m_neg_nan = nan.neg_p ();
m_pos_nan = nan.pos_p ();
if (flag_checking)
@@ -1823,7 +1855,9 @@ frange::known_isfinite () const
{
if (undefined_p () || varying_p () || m_kind == VR_ANTI_RANGE)
return false;
- return (!maybe_isnan () && !real_isinf (&m_min) && !real_isinf (&m_max));
+ return (!maybe_isnan ()
+ && !real_isinf (&lower_bound ())
+ && !real_isinf (&upper_bound ()));
}
// Return TRUE if range is known to be normal.
@@ -1835,9 +1869,11 @@ frange::known_isnormal () const
return false;
machine_mode mode = TYPE_MODE (type ());
- return (!real_isdenormal (&m_min, mode) && !real_isdenormal (&m_max, mode)
- && !real_iszero (&m_min) && !real_iszero (&m_max)
- && (!real_isneg (&m_min) || real_isneg (&m_max)));
+ const REAL_VALUE_TYPE &min = lower_bound ();
+ const REAL_VALUE_TYPE &max = upper_bound ();
+ return (!real_isdenormal (&min, mode) && !real_isdenormal (&max, mode)
+ && !real_iszero (&min) && !real_iszero (&max)
+ && (!real_isneg (&min) || real_isneg (&max)));
}
// Return TRUE if range is known to be denormal.
@@ -1849,8 +1885,10 @@ frange::known_isdenormal_or_zero () const
return false;
machine_mode mode = TYPE_MODE (type ());
- return ((real_isdenormal (&m_min, mode) || real_iszero (&m_min))
- && (real_isdenormal (&m_max, mode) || real_iszero (&m_max)));
+ const REAL_VALUE_TYPE &min = lower_bound ();
+ const REAL_VALUE_TYPE &max = upper_bound ();
+ return ((real_isdenormal (&min, mode) || real_iszero (&min))
+ && (real_isdenormal (&max, mode) || real_iszero (&max)));
}
// Return TRUE if range may be infinite.
@@ -1862,7 +1900,7 @@ frange::maybe_isinf () const
return false;
if (varying_p ())
return true;
- return real_isinf (&m_min) || real_isinf (&m_max);
+ return real_isinf (&lower_bound ()) || real_isinf (&upper_bound ());
}
// Return TRUE if range is known to be the [-INF,-INF] or [+INF,+INF].
@@ -1871,9 +1909,10 @@ inline bool
frange::known_isinf () const
{
return (m_kind == VR_RANGE
+ && m_num_ranges == 1
&& !maybe_isnan ()
- && real_identical (&m_min, &m_max)
- && real_isinf (&m_min));
+ && real_identical (&m_pairs[0].min, &m_pairs[0].max)
+ && real_isinf (&m_pairs[0].min));
}
// Return TRUE if range is possibly a NAN.
@@ -1921,9 +1960,9 @@ frange::signbit_p (bool &signbit) const
// No NAN.
if (!m_pos_nan && !m_neg_nan)
{
- if (m_min.sign == m_max.sign)
+ if (lower_bound ().sign == upper_bound ().sign)
{
- signbit = m_min.sign;
+ signbit = lower_bound ().sign;
return true;
}
return false;
@@ -1931,7 +1970,8 @@ frange::signbit_p (bool &signbit) const
// NAN with known sign.
bool nan_sign = m_neg_nan;
if (known_isnan ()
- || (nan_sign == m_min.sign && nan_sign == m_max.sign))
+ || (nan_sign == lower_bound ().sign
+ && nan_sign == upper_bound ().sign))
{
signbit = nan_sign;
return true;
--
2.47.3