[COMMITTED] Improve union of ranges containing NAN.
Aldy Hernandez
aldyh@redhat.com
Tue Aug 30 15:43:01 GMT 2022
Previously [5,6] U NAN would just drop to VARYING. With this patch,
the resulting range becomes [5,6] with the NAN bit set to unknown.
[I still have yet to decide what to do with intersections. ISTM, the
intersection of a known NAN with anything else should be a NAN, but it
could also be undefined (the empty set). I'll have to run some tests
and see. Currently, we drop to VARYING cause well... it's always safe
to give up;-).]
gcc/ChangeLog:
* value-range.cc (early_nan_resolve): Change comment.
(frange::union_): Handle union when one side is a NAN.
(range_tests_nan): Add tests for NAN union.
---
gcc/value-range.cc | 44 ++++++++++++++++++++++++++++++++++----------
1 file changed, 34 insertions(+), 10 deletions(-)
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index b6d6c62c06c..473139c6dbd 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -403,7 +403,7 @@ early_nan_resolve (frange &r, const frange &other)
// There's nothing to do for both NANs.
if (r.get_nan ().yes_p () == other.get_nan ().yes_p ())
return false;
- // But only one NAN complicates things.
+ // ?? Perhaps the intersection of a NAN and anything is a NAN ??.
r.set_varying (r.type ());
return true;
}
@@ -420,10 +420,22 @@ frange::union_ (const vrange &v)
*this = r;
return true;
}
- // ?? We could do better here. [5,6] U NAN should be [5,6] with the
- // NAN maybe bits set. For now, this is conservatively correct.
- if (get_nan ().yes_p () || r.get_nan ().yes_p ())
- return early_nan_resolve (*this, r);
+
+ // If one side has a NAN, the union is just the other side plus the
+ // NAN bit.
+ if (get_nan ().yes_p ())
+ {
+ *this = r;
+ // NOP if NAN already set.
+ set_nan (fp_prop::VARYING);
+ return true;
+ }
+ if (r.get_nan ().yes_p ())
+ {
+ // NOP if NAN already set.
+ set_nan (fp_prop::VARYING);
+ return true;
+ }
bool changed = m_props.union_ (r.m_props);
@@ -3520,6 +3532,7 @@ static void
range_tests_nan ()
{
frange r0, r1;
+ REAL_VALUE_TYPE q, r;
// Equal ranges but with differing NAN bits are not equal.
r1 = frange_float ("10", "12");
@@ -3537,13 +3550,24 @@ range_tests_nan ()
ASSERT_FALSE (r0 == r0);
ASSERT_TRUE (r0 != r0);
- // Make sure that combining NAN and INF doesn't give any crazy results.
+ // [5,6] U NAN is [5,6] with an unknown NAN bit.
+ r0 = frange_float ("5", "6");
+ r0.set_nan (fp_prop::NO);
+ r1 = frange_nan (float_type_node);
+ r0.union_ (r1);
+ real_from_string (&q, "5");
+ real_from_string (&r, "6");
+ ASSERT_TRUE (real_identical (&q, &r0.lower_bound ()));
+ ASSERT_TRUE (real_identical (&r, &r0.upper_bound ()));
+ ASSERT_TRUE (r0.get_nan ().varying_p ());
+
+ // NAN U NAN = NAN
r0 = frange_nan (float_type_node);
- ASSERT_TRUE (r0.get_nan ().yes_p ());
- r1 = frange_float ("+Inf", "+Inf");
+ r1 = frange_nan (float_type_node);
r0.union_ (r1);
- // [INF, INF] U NAN = VARYING
- ASSERT_TRUE (r0.varying_p ());
+ ASSERT_TRUE (real_isnan (&r0.lower_bound ()));
+ ASSERT_TRUE (real_isnan (&r1.upper_bound ()));
+ ASSERT_TRUE (r0.get_nan ().yes_p ());
// [INF, INF] ^ NAN = VARYING
r0 = frange_nan (float_type_node);
--
2.37.1
More information about the Gcc-patches
mailing list