[PATCH 1/4] Add contains_zero_p to the vrange hierarchy.

Aldy Hernandez <[email protected]> Wed, 5 Aug 2026 16:17:21 +0200
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
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.
---
 gcc/value-range.cc | 14 ++++++++++++++
 gcc/value-range.h  | 26 ++++++++++++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 69d89f34227..f2dfda14831 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 585120dda44..260f822c8ea 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -103,6 +103,7 @@ public:
   virtual bool contains_p (tree cst) const = 0;
   virtual bool zero_p () const = 0;
   virtual bool nonzero_p () const = 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 +316,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 +424,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 +525,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 +638,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 +891,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 +1143,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 +1486,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
 {
-- 
2.47.3