[PATCH 3/4] Implement the exact nonzero-set test without nonzero_p.

Aldy Hernandez <[email protected]> Wed, 5 Aug 2026 16:17:24 +0200
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
The prange storage encoding and the get_legacy_range function use
nonzero_p () for its exact meaning: is this range exactly ~[0,0]?
Before removing nonzero_p (), test that directly instead of using
nonzero_p.

Tested on ppc64le Linux.

gcc/ChangeLog:

	* value-range.cc (get_legacy_range): Compare against a set_nonzero
	prange instead of calling nonzero_p.
	* value-range-storage.cc (nonzero_range_p): New.
	(prange_storage::prange_format): Use it instead of nonzero_p.
	(prange_storage::equal_p): Likewise.
---
 gcc/value-range-storage.cc | 21 +++++++++++++++++++--
 gcc/value-range.cc         |  5 ++++-
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc
index c1b9d8ec2f6..827a5260a19 100644
--- a/gcc/value-range-storage.cc
+++ b/gcc/value-range-storage.cc
@@ -646,6 +646,23 @@ prange_storage::prange_storage (const prange &r) : vrange_storage (VR_PRANGE)
   set_prange (r);
 }
 
+// Return TRUE if R is exactly the nonzero set [1, MAX], which prange_storage
+// encodes compactly as PR_NONZERO.
+//
+// Compare the bounds against a fresh set_nonzero () rather than using
+// prange::operator==, because operator== also compares the bitmask and
+// points-to info, which are stored separately here, so a non-null pointer that
+// also carries e.g. an alignment bitmask still belongs in PR_NONZERO.
+
+static inline bool
+nonzero_range_p (const prange &r)
+{
+  prange nonzero (r.type ());
+  nonzero.set_nonzero (r.type ());
+  return (r.lower_bound () == nonzero.lower_bound ()
+	  && r.upper_bound () == nonzero.upper_bound ());
+}
+
 // Return the prange_kind for range R, and the number of words of storage
 // it requires in NUM_WORDS.
 
@@ -664,7 +681,7 @@ prange_storage::prange_format (const prange &r, unsigned &num_words)
 
   enum prange_kind kind = PR_NONZERO;
 
-  if (!r.nonzero_p ())
+  if (!nonzero_range_p (r))
     {
       prange tmp (r.type ());
       if (r.lower_bound () == tmp.lower_bound ()
@@ -803,7 +820,7 @@ prange_storage::equal_p (const prange &r) const
 	return r.zero_p ();
 
       case PR_NONZERO:
-	if (!r.nonzero_p ())
+	if (!nonzero_range_p (r))
 	  return false;
 	break;
 
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index f2dfda14831..d45c3649582 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -1871,7 +1871,10 @@ get_legacy_range (const prange &r, tree &min, tree &max)
       min = max = r.lbound ();
       return VR_RANGE;
     }
-  if (r.nonzero_p ())
+  prange nonzero (type);
+  nonzero.set_nonzero (type);
+  if (r.lower_bound () == nonzero.lower_bound ()
+      && r.upper_bound () == nonzero.upper_bound ())
     {
       min = max = build_zero_cst (type);
       return VR_ANTI_RANGE;
-- 
2.47.3