https://gcc.gnu.org/g:9231e36eeff6ec576e99f4c7c4b30e9fced44cd1

commit r17-3026-g9231e36eeff6ec576e99f4c7c4b30e9fced44cd1
Author: Aldy Hernandez <[email protected]>
Date:   Wed Aug 5 08:39:43 2026 +0000

    Add contains_zero_p to the vrange hierarchy.
    
    Introduce a contains_zero_p() predicate on vrange and company,
    returning whether the range contains zero.  It is a clearer
    replacement for nonzero_p(), which only holds for the exact ~[0,0]
    range.
    
    Tested on ppc64le Linux.
    
    gcc/ChangeLog:
    
            * value-range.h (vrange::contains_zero_p): New pure virtual.
            (unsupported_range::contains_zero_p): Declare.
            (irange::contains_zero_p): Declare and define.
            (prange::contains_zero_p): Declare and define.
            (frange::contains_zero_p): Declare.
            (Value_Range::contains_zero_p): New.
            * value-range.cc (unsupported_range::contains_zero_p): Define.
            (frange::contains_zero_p): Define.

Diff:
---
 gcc/value-range.cc | 14 ++++++++++++++
 gcc/value-range.h  | 28 ++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 69d89f342272..f2dfda148319 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -297,6 +297,12 @@ unsupported_range::nonzero_p () const
   return false;
 }
 
+bool
+unsupported_range::contains_zero_p () const
+{
+  return varying_p ();
+}
+
 void
 unsupported_range::set_nonzero (tree type)
 {
@@ -1716,6 +1722,14 @@ frange::nonzero_p () const
   return tmp == nz;
 }
 
+// Return TRUE if the range contains zero (+0.0 or -0.0).
+
+bool
+frange::contains_zero_p () const
+{
+  return contains_p (dconst0) || contains_p (dconstm0);
+}
+
 // Set range to [+0.0, +0.0] if honoring signed zeros, or [0.0, 0.0]
 // otherwise.
 
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 585120dda44c..1d138ab1828c 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -103,6 +103,9 @@ public:
   virtual bool contains_p (tree cst) const = 0;
   virtual bool zero_p () const = 0;
   virtual bool nonzero_p () const = 0;
+  // True if val == 0 may hold for some value in the range; for a float
+  // range that means +0.0 or -0.0.
+  virtual bool contains_zero_p () const = 0;
   virtual void set_nonzero (tree type) = 0;
   virtual void set_zero (tree type) = 0;
   virtual void set_nonnegative (tree type) = 0;
@@ -315,6 +318,7 @@ public:
   // Predicates.
   virtual bool zero_p () const override;
   virtual bool nonzero_p () const override;
+  virtual bool contains_zero_p () const override;
   virtual bool singleton_p (tree *result = NULL) const override;
   bool singleton_p (wide_int &) const;
   bool contains_p (const wide_int &) const;
@@ -422,6 +426,7 @@ public:
   virtual bool singleton_p (tree *result = NULL) const final override;
   virtual bool zero_p () const final override;
   virtual bool nonzero_p () const final override;
+  virtual bool contains_zero_p () const final override;
   virtual void set (tree, tree, value_range_kind = VR_RANGE) final override;
   virtual tree type () const final override;
   virtual bool union_ (const vrange &v) final override;
@@ -522,6 +527,7 @@ public:
   bool contains_p (tree) const final override;
   bool zero_p () const final override;
   bool nonzero_p () const final override;
+  bool contains_zero_p () const final override;
   void set_nonzero (tree type) final override;
   void set_zero (tree type) final override;
   void set_nonnegative (tree type) final override;
@@ -634,6 +640,7 @@ public:
   virtual void accept (const vrange_visitor &v) const override;
   virtual bool zero_p () const override;
   virtual bool nonzero_p () const override;
+  virtual bool contains_zero_p () const override;
   virtual void set_nonzero (tree type) override;
   virtual void set_zero (tree type) override;
   virtual void set_nonnegative (tree type) override;
@@ -886,6 +893,7 @@ public:
   void set_nonzero (tree type)
     { init (type); return m_vrange->set_nonzero (type); }
   bool nonzero_p () const { return m_vrange->nonzero_p (); }
+  bool contains_zero_p () const { return m_vrange->contains_zero_p (); }
   bool zero_p () const { return m_vrange->zero_p (); }
   tree lbound () const { return m_vrange->lbound (); }
   tree ubound () const { return m_vrange->ubound (); }
@@ -1137,6 +1145,16 @@ irange::nonzero_p () const
   return *this == int_range<2> (type (), zero, zero, VR_ANTI_RANGE);
 }
 
+inline bool
+irange::contains_zero_p () const
+{
+  if (undefined_p ())
+    return false;
+
+  wide_int zero = wi::zero (TYPE_PRECISION (type ()));
+  return contains_p (zero);
+}
+
 inline bool
 irange::supports_p (const_tree type)
 {
@@ -1470,6 +1488,16 @@ prange::nonzero_p () const
   return m_kind == VR_RANGE && m_min == 1 && m_max == -1;
 }
 
+inline bool
+prange::contains_zero_p () const
+{
+  if (undefined_p ())
+    return false;
+
+  wide_int zero = wi::zero (TYPE_PRECISION (type ()));
+  return contains_p (zero);
+}
+
 inline tree
 prange::type () const
 {

Reply via email to