[COMMITTED] Provide cleaner set_nan(), clear_nan(), and update_nan() methods.

Message ID 20220914150852.1244397-2-aldyh@redhat.com
State New, archived
Headers
Series [COMMITTED] Provide cleaner set_nan(), clear_nan(), and update_nan() methods. |

Commit Message

Aldy Hernandez Sept. 14, 2022, 3:08 p.m. UTC
  set_* has a very specific meaning for irange's and friends.  Methods
prefixed with set_* are setters clobbering the existing range.  As
such, the current set_nan() method is confusing in that it's not
actually setting a range to a NAN, but twiddling the NAN flags for an
existing frange.

This patch replaces set_nan() with an update_nan() to set the flag,
and clear_nan() to clear it.  This makes the code clearer, and though
the confusing tristate is still there, it will be removed in upcoming
patches.

Also, there is now an actual set_nan() method to set the range to a
NAN.  This replaces two out of class functions doing the same thing.
In future patches I will also add the ability to create a NAN with a
specific sign, but doing so now would be confusing because we're not
tracking NAN signs.

We should also submit set_signbit to the same fate, but it's about to
get removed.

No functional changes.

Regstrapped on x86-64 Linux, plus I ran selftests for
-ffinite-math-only.

gcc/ChangeLog:

	* range-op-float.cc (frange_set_nan): Remove.
	(build_lt): Use set_nan, update_nan, clear_nan.
	(build_gt): Same.
	(foperator_equal::op1_range): Same.
	(foperator_not_equal::op1_range): Same.
	(foperator_lt::op1_range): Same.
	(foperator_lt::op2_range): Same.
	(foperator_le::op1_range): Same.
	(foperator_le::op2_range): Same.
	(foperator_gt::op1_range): Same.
	(foperator_gt::op2_range): Same.
	(foperator_ge::op1_range): Same.
	(foperator_ge::op2_range): Same.
	(foperator_unordered::op1_range): Same.
	(foperator_ordered::op1_range): Same.
	* value-query.cc (range_query::get_tree_range): Same.
	* value-range.cc (frange::set_nan): Same.
	(frange::update_nan): Same.
	(frange::union_): Same.
	(frange::intersect): Same.
	(range_tests_nan): Same.
	(range_tests_signed_zeros): Same.
	(range_tests_signbit): Same.
	(range_tests_floats): Same.
	* value-range.h (class frange): Add update_nan and clear_nan.
	(frange::set_nan): New.
---
 gcc/range-op-float.cc | 46 ++++++++++++++------------------------
 gcc/value-query.cc    |  4 ++--
 gcc/value-range.cc    | 52 +++++++++++++++++++++----------------------
 gcc/value-range.h     | 11 ++++-----
 4 files changed, 51 insertions(+), 62 deletions(-)
  

Patch

diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index 0f928b6c098..f979ca597cb 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -150,18 +150,6 @@  range_operator_float::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) cons
   return VREL_VARYING;
 }
 
-// Set R to [NAN, NAN].
-
-static inline void
-frange_set_nan (frange &r, tree type)
-{
-  REAL_VALUE_TYPE rv;
-  bool res = real_nan (&rv, "", 1, TYPE_MODE (type));
-  if (flag_checking)
-    gcc_assert (res);
-  r.set (type, rv, rv);
-}
-
 // Return TRUE if OP1 is known to be free of NANs.
 
 static inline bool
@@ -248,7 +236,7 @@  build_lt (frange &r, tree type, const REAL_VALUE_TYPE &val)
   if (real_isinf (&val, 1))
     {
       if (HONOR_NANS (type))
-	frange_set_nan (r, type);
+	r.set_nan (type);
       else
 	r.set_undefined ();
       return false;
@@ -286,7 +274,7 @@  build_gt (frange &r, tree type, const REAL_VALUE_TYPE &val)
   if (real_isinf (&val, 0))
     {
       if (HONOR_NANS (type))
-	frange_set_nan (r, type);
+	r.set_nan (type);
       else
 	r.set_undefined ();
       return false;
@@ -392,14 +380,14 @@  foperator_equal::op1_range (frange &r, tree type,
       if (HONOR_SIGNED_ZEROS (type) && r.contains_p (build_zero_cst (type)))
 	r.set_signbit (fp_prop::VARYING);
       // The TRUE side of op1 == op2 implies op1 is !NAN.
-      r.set_nan (fp_prop::NO);
+      r.clear_nan ();
       break;
 
     case BRS_FALSE:
       r.set_varying (type);
       // The FALSE side of op1 == op1 implies op1 is a NAN.
       if (rel == VREL_EQ)
-	frange_set_nan (r, type);
+	r.set_nan (type);
       // If the result is false, the only time we know anything is
       // if OP2 is a constant.
       else if (op2.singleton_p ()
@@ -496,7 +484,7 @@  foperator_not_equal::op1_range (frange &r, tree type,
       if (HONOR_SIGNED_ZEROS (type) && r.contains_p (build_zero_cst (type)))
 	r.set_signbit (fp_prop::VARYING);
       // The FALSE side of op1 != op2 implies op1 is !NAN.
-      r.set_nan (fp_prop::NO);
+      r.clear_nan ();
       break;
 
     default:
@@ -563,7 +551,7 @@  foperator_lt::op1_range (frange &r,
     case BRS_TRUE:
       if (build_lt (r, type, op2.upper_bound ()))
 	{
-	  r.set_nan (fp_prop::NO);
+	  r.clear_nan ();
 	  // x < y implies x is not +INF.
 	  frange_drop_inf (r, type);
 	}
@@ -591,7 +579,7 @@  foperator_lt::op2_range (frange &r,
     case BRS_TRUE:
       if (build_gt (r, type, op1.lower_bound ()))
 	{
-	  r.set_nan (fp_prop::NO);
+	  r.clear_nan ();
 	  // x < y implies y is not -INF.
 	  frange_drop_ninf (r, type);
 	}
@@ -664,7 +652,7 @@  foperator_le::op1_range (frange &r,
     {
     case BRS_TRUE:
       if (build_le (r, type, op2.upper_bound ()))
-	r.set_nan (fp_prop::NO);
+	r.clear_nan ();
       break;
 
     case BRS_FALSE:
@@ -688,7 +676,7 @@  foperator_le::op2_range (frange &r,
     {
     case BRS_TRUE:
       if (build_ge (r, type, op1.lower_bound ()))
-	r.set_nan (fp_prop::NO);
+	r.clear_nan ();
       break;
 
     case BRS_FALSE:
@@ -759,7 +747,7 @@  foperator_gt::op1_range (frange &r,
     case BRS_TRUE:
       if (build_gt (r, type, op2.lower_bound ()))
 	{
-	  r.set_nan (fp_prop::NO);
+	  r.clear_nan ();
 	  // x > y implies x is not -INF.
 	  frange_drop_ninf (r, type);
 	}
@@ -787,7 +775,7 @@  foperator_gt::op2_range (frange &r,
     case BRS_TRUE:
       if (build_lt (r, type, op1.upper_bound ()))
 	{
-	  r.set_nan (fp_prop::NO);
+	  r.clear_nan ();
 	  // x > y implies y is not +INF.
 	  frange_drop_inf (r, type);
 	}
@@ -860,7 +848,7 @@  foperator_ge::op1_range (frange &r,
     {
     case BRS_TRUE:
       build_ge (r, type, op2.lower_bound ());
-      r.set_nan (fp_prop::NO);
+      r.clear_nan ();
       break;
 
     case BRS_FALSE:
@@ -887,7 +875,7 @@  foperator_ge::op2_range (frange &r, tree type,
 
     case BRS_TRUE:
       build_le (r, type, op1.upper_bound ());
-      r.set_nan (fp_prop::NO);
+      r.clear_nan ();
       break;
 
     default:
@@ -948,13 +936,13 @@  foperator_unordered::op1_range (frange &r, tree type,
       // Since at least one operand must be NAN, if one of them is
       // not, the other must be.
       if (!op2.maybe_nan ())
-	frange_set_nan (r, type);
+	r.set_nan (type);
       break;
 
     case BRS_FALSE:
       r.set_varying (type);
       // A false UNORDERED means both operands are !NAN.
-      r.set_nan (fp_prop::NO);
+      r.clear_nan ();
       break;
 
     default:
@@ -1011,14 +999,14 @@  foperator_ordered::op1_range (frange &r, tree type,
     case BRS_TRUE:
       r.set_varying (type);
       // The TRUE side of op1 ORDERED op2 implies op1 is !NAN.
-      r.set_nan (fp_prop::NO);
+      r.clear_nan ();
       break;
 
     case BRS_FALSE:
       r.set_varying (type);
       // The FALSE side of op1 ORDERED op1 implies op1 is !NAN.
       if (rel == VREL_EQ)
-	r.set_nan (fp_prop::NO);
+	r.clear_nan ();
       break;
 
     default:
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index de83f469be4..ea6e4b979ad 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -223,9 +223,9 @@  range_query::get_tree_range (vrange &r, tree expr, gimple *stmt)
 	// Singletons from the tree world have known properties.
 	REAL_VALUE_TYPE *rv = TREE_REAL_CST_PTR (expr);
 	if (real_isnan (rv))
-	  f.set_nan (fp_prop::YES);
+	  f.update_nan (fp_prop::YES);
 	else
-	  f.set_nan (fp_prop::NO);
+	  f.clear_nan ();
 	if (real_isneg (rv))
 	  f.set_signbit (fp_prop::YES);
 	else
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index d40a4ebf657..dd827421aca 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -270,7 +270,7 @@  tree_compare (tree_code code, tree op1, tree op2)
 // Set the NAN property.  Adjust the range if appopriate.
 
 void
-frange::set_nan (fp_prop::kind k)
+frange::update_nan (fp_prop::kind k)
 {
   if (k == fp_prop::YES)
     {
@@ -280,7 +280,7 @@  frange::set_nan (fp_prop::kind k)
 	  return;
 	}
       gcc_checking_assert (!undefined_p ());
-      *this = frange_nan (m_type);
+      set_nan (m_type);
       return;
     }
 
@@ -474,7 +474,7 @@  frange::union_ (const vrange &v)
       *this = r;
       m_props = save;
       m_props.union_ (r.m_props);
-      set_nan (fp_prop::VARYING);
+      update_nan (fp_prop::VARYING);
       if (flag_checking)
 	verify_range ();
       return true;
@@ -482,7 +482,7 @@  frange::union_ (const vrange &v)
   if (r.known_nan ())
     {
       m_props.union_ (r.m_props);
-      set_nan (fp_prop::VARYING);
+      update_nan (fp_prop::VARYING);
       if (flag_checking)
 	verify_range ();
       return true;
@@ -531,7 +531,7 @@  frange::intersect (const vrange &v)
       if (m_props == r.m_props)
 	return false;
 
-      *this = frange_nan (m_type);
+      set_nan (m_type);
       return true;
     }
   // ?? Perhaps the intersection of a NAN and anything is a NAN ??.
@@ -3634,14 +3634,14 @@  range_tests_nan ()
       r1 = frange_float ("10", "12");
       r0 = r1;
       ASSERT_EQ (r0, r1);
-      r0.set_nan (fp_prop::NO);
+      r0.clear_nan ();
       ASSERT_NE (r0, r1);
-      r0.set_nan (fp_prop::YES);
+      r0.clear_nan ();
       ASSERT_NE (r0, r1);
     }
 
   // NAN ranges are not equal to each other.
-  r0 = frange_nan (float_type_node);
+  r0.set_nan (float_type_node);
   r1 = r0;
   ASSERT_FALSE (r0 == r1);
   ASSERT_FALSE (r0 == r0);
@@ -3649,8 +3649,8 @@  range_tests_nan ()
 
   // [5,6] U NAN = [5,6] NAN.
   r0 = frange_float ("5", "6");
-  r0.set_nan (fp_prop::NO);
-  r1 = frange_nan (float_type_node);
+  r0.clear_nan ();
+  r1.set_nan (float_type_node);
   r0.union_ (r1);
   real_from_string (&q, "5");
   real_from_string (&r, "6");
@@ -3659,34 +3659,34 @@  range_tests_nan ()
   ASSERT_TRUE (r0.maybe_nan ());
 
   // NAN U NAN = NAN
-  r0 = frange_nan (float_type_node);
-  r1 = frange_nan (float_type_node);
+  r0.set_nan (float_type_node);
+  r1.set_nan (float_type_node);
   r0.union_ (r1);
   ASSERT_TRUE (real_isnan (&r0.lower_bound ()));
   ASSERT_TRUE (real_isnan (&r1.upper_bound ()));
   ASSERT_TRUE (r0.known_nan ());
 
   // [INF, INF] ^ NAN = VARYING
-  r0 = frange_nan (float_type_node);
+  r0.set_nan (float_type_node);
   r1 = frange_float ("+Inf", "+Inf");
   r0.intersect (r1);
   ASSERT_TRUE (r0.varying_p ());
 
   // NAN ^ NAN = NAN
-  r0 = frange_nan (float_type_node);
-  r1 = frange_nan (float_type_node);
+  r0.set_nan (float_type_node);
+  r1.set_nan (float_type_node);
   r0.intersect (r1);
   ASSERT_TRUE (r0.known_nan ());
 
   // VARYING ^ NAN = NAN.
-  r0 = frange_nan (float_type_node);
+  r0.set_nan (float_type_node);
   r1.set_varying (float_type_node);
   r0.intersect (r1);
   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);
+  r0.update_nan (fp_prop::YES);
   ASSERT_TRUE (r0.known_nan ());
   ASSERT_TRUE (real_isnan (&r0.lower_bound ()));
   ASSERT_TRUE (real_isnan (&r0.upper_bound ()));
@@ -3736,7 +3736,7 @@  range_tests_signed_zeros ()
   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);
+  r0.set_nan (float_type_node);
   r1 = frange_float ("5", "6");
   r0.union_ (r1);
   real_from_string (&q, "5");
@@ -3762,7 +3762,7 @@  range_tests_signbit ()
   // the signbit property set.
   r0 = frange_float ("-5", "10");
   r0.set_signbit (fp_prop::YES);
-  r0.set_nan (fp_prop::NO);
+  r0.clear_nan ();
   ASSERT_TRUE (r0.known_signbit (signbit) && signbit);
   r1 = frange_float ("-5", "0");
   ASSERT_TRUE (real_identical (&r0.lower_bound (), &r1.lower_bound ()));
@@ -3770,20 +3770,20 @@  range_tests_signbit ()
 
   // Negative numbers should have the SIGNBIT set.
   r0 = frange_float ("-5", "-1");
-  r0.set_nan (fp_prop::NO);
+  r0.clear_nan ();
   ASSERT_TRUE (r0.known_signbit (signbit) && signbit);
   // Positive numbers should have the SIGNBIT clear.
   r0 = frange_float ("1", "10");
-  r0.set_nan (fp_prop::NO);
+  r0.clear_nan ();
   ASSERT_TRUE (r0.known_signbit (signbit) && !signbit);
   // Numbers containing zero should have an unknown SIGNBIT.
   r0 = frange_float ("0", "10");
-  r0.set_nan (fp_prop::NO);
+  r0.clear_nan ();
   ASSERT_TRUE (!r0.known_signbit (signbit));
   // Numbers spanning both positive and negative should have an
   // unknown SIGNBIT.
   r0 = frange_float ("-10", "10");
-  r0.set_nan (fp_prop::NO);
+  r0.clear_nan ();
   ASSERT_TRUE (!r0.known_signbit (signbit));
   r0.set_varying (float_type_node);
   ASSERT_TRUE (!r0.known_signbit (signbit));
@@ -3791,12 +3791,12 @@  range_tests_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.clear_nan ();
   r0.set_signbit (fp_prop::VARYING);
   ASSERT_TRUE (r0.known_signbit (signbit) && !signbit);
   r0 = frange_float ("-5", "-1");
   r0.set_signbit (fp_prop::NO);
-  r0.set_nan (fp_prop::NO);
+  r0.clear_nan ();
   ASSERT_TRUE (r0.undefined_p ());
 }
 
@@ -3817,7 +3817,7 @@  range_tests_floats ()
   if (r0.maybe_nan ())
     ASSERT_TRUE (r0.varying_p ());
   // ...unless it has some special property...
-  r0.set_nan (fp_prop::NO);
+  r0.clear_nan ();
   ASSERT_FALSE (r0.varying_p ());
 
   // The endpoints of a VARYING are +-INF.
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 0ba0193bc1f..6e896eb9ab5 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -348,6 +348,7 @@  public:
   virtual void set (tree, tree, value_range_kind = VR_RANGE) override;
   void set (tree type, const REAL_VALUE_TYPE &, const REAL_VALUE_TYPE &,
 	    value_range_kind = VR_RANGE);
+  void set_nan (tree type);
   virtual void set_varying (tree type) override;
   virtual void set_undefined () override;
   virtual bool union_ (const vrange &) override;
@@ -376,7 +377,8 @@  public:
   bool known_signbit (bool &signbit) const;
 
   // Accessors for FP properties.
-  void set_nan (fp_prop::kind f);
+  void update_nan (fp_prop::kind f);
+  void clear_nan () { update_nan (fp_prop::NO); }
   void set_signbit (fp_prop::kind);
 private:
   fp_prop get_nan () const { return m_props.get_nan (); }
@@ -1186,13 +1188,12 @@  real_min_representable (REAL_VALUE_TYPE *r, tree type)
 
 // Build a NAN of type TYPE.
 
-inline frange
-frange_nan (tree type)
+inline void
+frange::set_nan (tree type)
 {
   REAL_VALUE_TYPE r;
-
   gcc_assert (real_nan (&r, "", 1, TYPE_MODE (type)));
-  return frange (type, r, r);
+  set (type, r, r);
 }
 
 // Return TRUE if range is known to be finite.