aboutsummaryrefslogtreecommitdiff
path: root/gcc/value-range.cc
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2022-09-08 08:11:43 +0200
committerAldy Hernandez <aldyh@redhat.com>2022-09-08 12:56:16 +0200
commit672632317ac901f369b65b25f2147b3e7790ecca (patch)
treecaeeeee430d82a2e4122005babb4c0a96224810c /gcc/value-range.cc
parenta7852bd30a19d29ff7986869453786d460d17877 (diff)
downloadgcc-672632317ac901f369b65b25f2147b3e7790ecca.zip
gcc-672632317ac901f369b65b25f2147b3e7790ecca.tar.gz
gcc-672632317ac901f369b65b25f2147b3e7790ecca.tar.bz2
Implement known/maybe fpclassify like API for frange.
gcc/ChangeLog: * gimple-range-fold.cc (fold_using_range::range_of_builtin_int_call): Use fpclassify like API. * range-op-float.cc (finite_operand_p): Same. (finite_operands_p): Same. (foperator_lt::fold_range): Same. (foperator_le::fold_range): Same. (foperator_gt::fold_range): Same. (foperator_ge::fold_range): Same. (foperator_unordered::fold_range): Same. (foperator_unordered::op1_range): Same. (foperator_ordered::fold_range): Same. * value-range.cc (frange::set_nan): Same. (frange::set_signbit): Same. (frange::union_): Same. (frange::intersect): Same. (frange::operator==): Same. (frange::singleton_p): Same. (frange::verify_range): Same. (range_tests_nan): Same. (range_tests_floats): Same. * value-range.h(frange::known_finite): New. (frange::maybe_inf): New. (frange::known_inf): New. (frange::maybe_nan): New. (frange::known_nan): New. (frange::known_signbit): New.
Diffstat (limited to 'gcc/value-range.cc')
-rw-r--r--gcc/value-range.cc126
1 files changed, 73 insertions, 53 deletions
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index c3f668a..adcaaa2 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -274,7 +274,7 @@ frange::set_nan (fp_prop::kind k)
{
if (k == fp_prop::YES)
{
- if (get_nan ().no_p ())
+ if (!maybe_nan ())
{
set_undefined ();
return;
@@ -284,7 +284,7 @@ frange::set_nan (fp_prop::kind k)
return;
}
- if (k == fp_prop::NO && get_nan ().yes_p ())
+ if (k == fp_prop::NO && known_nan ())
{
set_undefined ();
return;
@@ -308,21 +308,18 @@ frange::set_signbit (fp_prop::kind k)
gcc_checking_assert (m_type);
// No additional adjustments are needed for a NAN.
- if (get_nan ().yes_p ())
+ if (known_nan ())
{
m_props.set_signbit (k);
return;
}
// Ignore sign changes when they're set correctly.
- if (real_less (&m_max, &dconst0))
- {
- gcc_checking_assert (get_signbit ().yes_p ());
- return;
- }
- if (real_less (&dconst0, &m_min))
+ if (!maybe_nan ())
{
- gcc_checking_assert (get_signbit ().no_p ());
- return;
+ if (real_less (&m_max, &dconst0))
+ return;
+ if (real_less (&dconst0, &m_min))
+ return;
}
// Adjust the range depending on the sign bit.
if (k == fp_prop::YES)
@@ -330,17 +327,22 @@ frange::set_signbit (fp_prop::kind k)
// Crop the range to [-INF, 0].
frange crop (m_type, dconstninf, dconst0);
intersect (crop);
- m_props.set_signbit (fp_prop::YES);
+ if (!undefined_p ())
+ m_props.set_signbit (fp_prop::YES);
}
else if (k == fp_prop::NO)
{
// Crop the range to [0, +INF].
frange crop (m_type, dconst0, dconstinf);
intersect (crop);
- m_props.set_signbit (fp_prop::NO);
+ if (!undefined_p ())
+ m_props.set_signbit (fp_prop::NO);
}
else
- m_props.set_signbit (fp_prop::VARYING);
+ {
+ m_props.set_signbit (fp_prop::VARYING);
+ normalize_kind ();
+ }
if (flag_checking)
verify_range ();
@@ -467,7 +469,7 @@ frange::union_ (const vrange &v)
// If one side has a NAN, the union is the other side, plus the union
// of the properties and the possibility of a NAN.
- if (get_nan ().yes_p ())
+ if (known_nan ())
{
frange_props save = m_props;
*this = r;
@@ -478,7 +480,7 @@ frange::union_ (const vrange &v)
verify_range ();
return true;
}
- if (r.get_nan ().yes_p ())
+ if (r.known_nan ())
{
m_props.union_ (r.m_props);
set_nan (fp_prop::VARYING);
@@ -525,7 +527,7 @@ frange::intersect (const vrange &v)
// If two NANs are not exactly the same, drop to an unknown NAN,
// otherwise there's nothing to do.
- if (get_nan ().yes_p () && r.get_nan ().yes_p ())
+ if (known_nan () && r.known_nan ())
{
if (m_props == r.m_props)
return false;
@@ -534,7 +536,7 @@ frange::intersect (const vrange &v)
return true;
}
// ?? Perhaps the intersection of a NAN and anything is a NAN ??.
- if (get_nan ().yes_p () || r.get_nan ().yes_p ())
+ if (known_nan () || r.known_nan ())
{
set_varying (m_type);
return true;
@@ -590,8 +592,7 @@ frange::operator== (const frange &src) const
if (varying_p ())
return types_compatible_p (m_type, src.m_type);
- if (m_props.get_nan ().yes_p ()
- || src.m_props.get_nan ().yes_p ())
+ if (known_nan () || src.known_nan ())
return false;
return (real_identical (&m_min, &src.m_min)
@@ -621,6 +622,9 @@ frange::contains_p (tree cst) const
{
if (HONOR_SIGNED_ZEROS (m_type) && real_iszero (rv))
{
+ // FIXME: This is still using get_signbit() instead of
+ // known_signbit() because the latter bails on possible NANs
+ // (for now).
if (get_signbit ().yes_p ())
return real_isneg (rv);
else if (get_signbit ().no_p ())
@@ -644,22 +648,25 @@ frange::singleton_p (tree *result) const
if (m_kind == VR_RANGE && real_identical (&m_min, &m_max))
{
// Return false for any singleton that may be a NAN.
- if (HONOR_NANS (m_type) && !get_nan ().no_p ())
+ if (HONOR_NANS (m_type) && maybe_nan ())
return false;
// Return the appropriate zero if known.
if (HONOR_SIGNED_ZEROS (m_type) && zero_p ())
{
- if (get_signbit ().no_p ())
+ bool signbit;
+ if (known_signbit (signbit))
{
- if (result)
- *result = build_real (m_type, dconst0);
- return true;
- }
- if (get_signbit ().yes_p ())
- {
- if (result)
- *result = build_real (m_type, real_value_negate (&dconst0));
+ if (signbit)
+ {
+ if (result)
+ *result = build_real (m_type, real_value_negate (&dconst0));
+ }
+ else
+ {
+ if (result)
+ *result = build_real (m_type, dconst0);
+ }
return true;
}
return false;
@@ -701,7 +708,7 @@ frange::verify_range ()
{
// If either is a NAN, both must be a NAN.
gcc_checking_assert (real_identical (&m_min, &m_max));
- gcc_checking_assert (get_nan ().yes_p ());
+ gcc_checking_assert (known_nan ());
}
else
// Make sure we don't have swapped ranges.
@@ -710,7 +717,7 @@ frange::verify_range ()
// If we're absolutely sure we have a NAN, the endpoints should
// reflect this, otherwise we'd have more than one way to represent
// a NAN.
- if (m_props.get_nan ().yes_p ())
+ if (known_nan ())
{
gcc_checking_assert (real_isnan (&m_min));
gcc_checking_assert (real_isnan (&m_max));
@@ -718,10 +725,14 @@ frange::verify_range ()
else
{
// Make sure the signbit and range agree.
- if (m_props.get_signbit ().yes_p ())
- gcc_checking_assert (real_compare (LE_EXPR, &m_max, &dconst0));
- else if (m_props.get_signbit ().no_p ())
- gcc_checking_assert (real_compare (GE_EXPR, &m_min, &dconst0));
+ bool signbit;
+ if (known_signbit (signbit))
+ {
+ if (signbit)
+ gcc_checking_assert (real_compare (LE_EXPR, &m_max, &dconst0));
+ else
+ gcc_checking_assert (real_compare (GE_EXPR, &m_min, &dconst0));
+ }
}
// If all the properties are clear, we better not span the entire
@@ -3637,7 +3648,7 @@ range_tests_nan ()
ASSERT_FALSE (r0 == r0);
ASSERT_TRUE (r0 != r0);
- // [5,6] U NAN is [5,6] with an unknown NAN bit.
+ // [5,6] U NAN.
r0 = frange_float ("5", "6");
r0.set_nan (fp_prop::NO);
r1 = frange_nan (float_type_node);
@@ -3646,7 +3657,7 @@ range_tests_nan ()
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 ());
+ ASSERT_TRUE (r0.maybe_nan ());
// NAN U NAN = NAN
r0 = frange_nan (float_type_node);
@@ -3654,7 +3665,7 @@ range_tests_nan ()
r0.union_ (r1);
ASSERT_TRUE (real_isnan (&r0.lower_bound ()));
ASSERT_TRUE (real_isnan (&r1.upper_bound ()));
- ASSERT_TRUE (r0.get_nan ().yes_p ());
+ ASSERT_TRUE (r0.known_nan ());
// [INF, INF] ^ NAN = VARYING
r0 = frange_nan (float_type_node);
@@ -3666,18 +3677,18 @@ range_tests_nan ()
r0 = frange_nan (float_type_node);
r1 = frange_nan (float_type_node);
r0.intersect (r1);
- ASSERT_TRUE (r0.get_nan ().yes_p ());
+ ASSERT_TRUE (r0.known_nan ());
// VARYING ^ NAN = NAN.
r0 = frange_nan (float_type_node);
r1.set_varying (float_type_node);
r0.intersect (r1);
- ASSERT_TRUE (r0.get_nan ().yes_p ());
+ ASSERT_TRUE (r0.known_nan ());
// Setting the NAN bit to yes, forces to range to [NAN, NAN].
r0.set_varying (float_type_node);
r0.set_nan (fp_prop::YES);
- ASSERT_TRUE (r0.get_nan ().yes_p ());
+ ASSERT_TRUE (r0.known_nan ());
ASSERT_TRUE (real_isnan (&r0.lower_bound ()));
ASSERT_TRUE (real_isnan (&r0.upper_bound ()));
}
@@ -3689,6 +3700,7 @@ range_tests_signed_zeros ()
tree neg_zero = fold_build1 (NEGATE_EXPR, float_type_node, zero);
REAL_VALUE_TYPE q, r;
frange r0, r1;
+ bool signbit;
// Since -0.0 == +0.0, a range of [-0.0, -0.0] should contain +0.0
// and vice versa.
@@ -3722,7 +3734,7 @@ range_tests_signed_zeros ()
r1 = frange (zero, zero);
r1.set_signbit (fp_prop::YES);
r0.union_ (r1);
- ASSERT_TRUE (r0.zero_p () && r0.get_signbit ().varying_p ());
+ ASSERT_TRUE (r0.zero_p () && !r0.known_signbit (signbit));
// NAN U [5,6] should be [5,6] with no sign info.
r0 = frange_nan (float_type_node);
@@ -3732,13 +3744,14 @@ range_tests_signed_zeros ()
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_signbit ().varying_p ());
+ ASSERT_TRUE (!r0.known_signbit (signbit));
}
static void
range_tests_signbit ()
{
frange r0, r1;
+ bool signbit;
// Setting the signbit drops the range to [-INF, 0].
r0.set_varying (float_type_node);
@@ -3750,35 +3763,42 @@ range_tests_signbit ()
// the signbit property set.
r0 = frange_float ("-5", "10");
r0.set_signbit (fp_prop::YES);
- ASSERT_TRUE (r0.get_signbit ().yes_p ());
+ r0.set_nan (fp_prop::NO);
+ ASSERT_TRUE (r0.known_signbit (signbit) && signbit);
r1 = frange_float ("-5", "0");
ASSERT_TRUE (real_identical (&r0.lower_bound (), &r1.lower_bound ()));
ASSERT_TRUE (real_identical (&r0.upper_bound (), &r1.upper_bound ()));
// Negative numbers should have the SIGNBIT set.
r0 = frange_float ("-5", "-1");
- ASSERT_TRUE (r0.get_signbit ().yes_p ());
+ r0.set_nan (fp_prop::NO);
+ ASSERT_TRUE (r0.known_signbit (signbit) && signbit);
// Positive numbers should have the SIGNBIT clear.
r0 = frange_float ("1", "10");
- ASSERT_TRUE (r0.get_signbit ().no_p ());
+ r0.set_nan (fp_prop::NO);
+ ASSERT_TRUE (r0.known_signbit (signbit) && !signbit);
// Numbers containing zero should have an unknown SIGNBIT.
r0 = frange_float ("0", "10");
- ASSERT_TRUE (r0.get_signbit ().varying_p ());
+ r0.set_nan (fp_prop::NO);
+ ASSERT_TRUE (!r0.known_signbit (signbit));
// Numbers spanning both positive and negative should have an
// unknown SIGNBIT.
r0 = frange_float ("-10", "10");
- ASSERT_TRUE (r0.get_signbit ().varying_p ());
+ r0.set_nan (fp_prop::NO);
+ ASSERT_TRUE (!r0.known_signbit (signbit));
r0.set_varying (float_type_node);
- ASSERT_TRUE (r0.get_signbit ().varying_p ());
+ ASSERT_TRUE (!r0.known_signbit (signbit));
// Ignore signbit changes when the sign bit is obviously known from
// the range.
r0 = frange_float ("5", "10");
+ r0.set_nan (fp_prop::NO);
r0.set_signbit (fp_prop::VARYING);
- ASSERT_TRUE (r0.get_signbit ().no_p ());
+ ASSERT_TRUE (r0.known_signbit (signbit) && !signbit);
r0 = frange_float ("-5", "-1");
r0.set_signbit (fp_prop::NO);
- ASSERT_TRUE (r0.get_signbit ().yes_p ());
+ r0.set_nan (fp_prop::NO);
+ ASSERT_TRUE (r0.undefined_p ());
}
static void
@@ -3795,7 +3815,7 @@ range_tests_floats ()
// A range of [-INF,+INF] is actually VARYING if no other properties
// are set.
r0 = frange_float ("-Inf", "+Inf");
- if (r0.get_nan ().varying_p ())
+ if (r0.maybe_nan ())
ASSERT_TRUE (r0.varying_p ());
// ...unless it has some special property...
r0.set_nan (fp_prop::NO);