On 3/21/23 14:56, Jakub Jelinek wrote:
On Tue, Mar 21, 2023 at 02:49:49PM +0100, Aldy Hernandez wrote:
So, this?

frange::set (tree type,
        const REAL_VALUE_TYPE &min,
        const REAL_VALUE_TYPE &max,
        const nan_state &,
        value_range_kind kind = VR_RANGE)

If so, I'll start poking at it.

Yes.

        Jakub


Tested on x86-64 Linux.

OK?
Aldy
From 64b9fabc0f31c661bb72029440227fe319566654 Mon Sep 17 00:00:00 2001
From: Aldy Hernandez <al...@redhat.com>
Date: Wed, 8 Mar 2023 10:58:01 +0100
Subject: [PATCH] frange: Implement nan_state class [PR109008]

This patch implements a nan_state class, that allows us to query or
pass around the NANness of an frange.  We can store +NAN, -NAN, +-NAN,
or not-a-NAN with it.

I tried to touch as little as possible, leaving other cleanups to the
next release.  For example, we should replace the m_*_nan fields in
frange with nan_state, and provide relevant accessors to nan_state
(isnan, etc).

gcc/ChangeLog:

	* value-range.cc (frange::set): Add nan_state argument.
	* value-range.h (class nan_state): New.
	(frange::get_nan_state): New.
---
 gcc/value-range.cc | 18 +++++++++++---
 gcc/value-range.h  | 62 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index a535337c47a..f71554b7d7c 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -284,7 +284,7 @@ frange::flush_denormals_to_zero ()
 void
 frange::set (tree type,
 	     const REAL_VALUE_TYPE &min, const REAL_VALUE_TYPE &max,
-	     value_range_kind kind)
+	     const nan_state &nan, value_range_kind kind)
 {
   switch (kind)
     {
@@ -316,8 +316,8 @@ frange::set (tree type,
   m_max = max;
   if (HONOR_NANS (m_type))
     {
-      m_pos_nan = true;
-      m_neg_nan = true;
+      m_pos_nan = nan.pos_p ();
+      m_neg_nan = nan.neg_p ();
     }
   else
     {
@@ -367,6 +367,18 @@ frange::set (tree type,
     verify_range ();
 }
 
+// Setter for an frange defaulting the NAN possibility to +-NAN when
+// HONOR_NANS.
+
+void
+frange::set (tree type,
+	     const REAL_VALUE_TYPE &min, const REAL_VALUE_TYPE &max,
+	     value_range_kind kind)
+{
+  nan_state nan;
+  set (type, min, max, nan, kind);
+}
+
 void
 frange::set (tree min, tree max, value_range_kind kind)
 {
diff --git a/gcc/value-range.h b/gcc/value-range.h
index f4ac73b499f..ec50346826c 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -268,6 +268,56 @@ public:
   virtual void accept (const vrange_visitor &v) const override;
 };
 
+// The NAN state as an opaque object.  The default constructor is +-NAN.
+
+class nan_state
+{
+public:
+  nan_state ();
+  nan_state (bool pos_nan, bool neg_nan);
+  bool neg_p () const;
+  bool pos_p () const;
+private:
+  bool m_pos_nan;
+  bool m_neg_nan;
+};
+
+// Default constructor initializing the object to +-NAN.
+
+inline
+nan_state::nan_state ()
+{
+  m_pos_nan = true;
+  m_neg_nan = true;
+}
+
+// Constructor initializing the object to +NAN if POS_NAN is set, -NAN
+// if NEG_NAN is set, or +-NAN if both are set.  Otherwise POS_NAN and
+// NEG_NAN are clear, and the object cannot be a NAN.
+
+inline
+nan_state::nan_state (bool pos_nan, bool neg_nan)
+{
+  m_pos_nan = pos_nan;
+  m_neg_nan = neg_nan;
+}
+
+// Return if +NAN is possible.
+
+inline bool
+nan_state::pos_p () const
+{
+  return m_pos_nan;
+}
+
+// Return if -NAN is possible.
+
+inline bool
+nan_state::neg_p () const
+{
+  return m_neg_nan;
+}
+
 // A floating point range.
 //
 // The representation is a type with a couple of endpoints, unioned
@@ -295,6 +345,8 @@ 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 (tree type, const REAL_VALUE_TYPE &, const REAL_VALUE_TYPE &,
+	    const nan_state &, value_range_kind = VR_RANGE);
   void set_nan (tree type);
   void set_nan (tree type, bool sign);
   virtual void set_varying (tree type) override;
@@ -315,9 +367,11 @@ public:
   bool operator!= (const frange &r) const { return !(*this == r); }
   const REAL_VALUE_TYPE &lower_bound () const;
   const REAL_VALUE_TYPE &upper_bound () const;
+  nan_state get_nan_state () const;
   void update_nan ();
   void update_nan (bool sign);
   void update_nan (tree) = delete; // Disallow silent conversion to bool.
+  void update_nan (const nan_state &);
   void clear_nan ();
 
   // fpclassify like API
@@ -358,6 +412,14 @@ frange::upper_bound () const
   return m_max;
 }
 
+// Return the NAN state.
+
+inline nan_state
+frange::get_nan_state () const
+{
+  return nan_state (m_pos_nan, m_neg_nan);
+}
+
 // is_a<> and as_a<> implementation for vrange.
 
 // Anything we haven't specialized is a hard fail.
-- 
2.39.2

Reply via email to