From f9ff6fa58217294d63f255dd02abfcc8a074f509 Mon Sep 17 00:00:00 2001 From: Aldy Hernandez Date: Mon, 21 Aug 2023 13:27:08 +0200 Subject: [PATCH] [frange] Return false if nothing changed in union_nans(). When one operand is a known NAN, we always return TRUE from union_nans(), even if no change occurred. This patch fixes the oversight. gcc/ChangeLog: * value-range.cc (frange::union_nans): Return false if nothing changed. (range_tests_floats): New test. --- gcc/value-range.cc | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/gcc/value-range.cc b/gcc/value-range.cc index 76f88d91046..60180c80e55 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -540,16 +540,26 @@ frange::union_nans (const frange &r) { gcc_checking_assert (known_isnan () || r.known_isnan ()); - if (known_isnan ()) + bool changed = false; + if (known_isnan () && m_kind != r.m_kind) { m_kind = r.m_kind; m_min = r.m_min; m_max = r.m_max; + changed = true; } - m_pos_nan |= r.m_pos_nan; - m_neg_nan |= r.m_neg_nan; - normalize_kind (); - return true; + 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; + } + if (changed) + { + normalize_kind (); + return true; + } + return false; } bool @@ -2715,6 +2725,22 @@ range_tests_nan () ASSERT_TRUE (real_identical (&r, &r0.upper_bound ())); ASSERT_TRUE (!r0.signbit_p (signbit)); ASSERT_TRUE (r0.maybe_isnan ()); + + // NAN U NAN shouldn't change anything. + r0.set_nan (float_type_node); + r1.set_nan (float_type_node); + ASSERT_FALSE (r0.union_ (r1)); + + // [3,5] NAN U NAN shouldn't change anything. + r0 = frange_float ("3", "5"); + r1.set_nan (float_type_node); + ASSERT_FALSE (r0.union_ (r1)); + + // [3,5] U NAN *does* trigger a change. + r0 = frange_float ("3", "5"); + r0.clear_nan (); + r1.set_nan (float_type_node); + ASSERT_TRUE (r0.union_ (r1)); } static void