From 64b9fabc0f31c661bb72029440227fe319566654 Mon Sep 17 00:00:00 2001 From: Aldy Hernandez 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