https://gcc.gnu.org/g:33e4cfbd9495a23ffe4639c217442a5459b9e400

commit r17-1816-g33e4cfbd9495a23ffe4639c217442a5459b9e400
Author: Andrew MacLeod <[email protected]>
Date:   Tue Jun 23 16:11:16 2026 -0400

    prange zero_p() should never have points to.
    
    Intersection sometimes produced a [0, 0] range with a points to field.
    
            PR tree-optimization/125910
            gcc/
            * value-range.cc (prange::set_pt): Do not set PT when zero.
            (prange::intersect): If the result is zero_p, clear PT.
            (prange::verify_range): Verify points-to range is valid.
            * value-range.h (zero_p): Do not assert, move to verify range.
            (prange::set_pt): Only set PT when the range valid.
    
            gcc/testsuite/
            * gcc.dg/pr125910.c: New.

Diff:
---
 gcc/testsuite/gcc.dg/pr125910.c | 15 +++++++++++++++
 gcc/value-range.cc              | 14 ++++++++++++++
 gcc/value-range.h               |  6 ++++--
 3 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/pr125910.c b/gcc/testsuite/gcc.dg/pr125910.c
new file mode 100644
index 000000000000..88ec139f9795
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr125910.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-delete-null-pointer-checks" } */
+
+void a();
+extern int b;
+int *c;
+void d() {
+  int *e = c;
+  if (e)
+    a();
+  if (e == &b)
+    a();
+  if (e)
+    a();
+}
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 86eb2f507fb7..722eca9abca7 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -539,6 +539,10 @@ prange::set_pt (tree expr, bool points_to_p)
   m_pt = NULL_TREE;
   m_points_to_p = false;
 
+  // A zero range means no points-to info.
+  if (zero_p ())
+    return;
+
   // No points to initially may make this VARYING.
   if (varying_compatible_p ())
     set_varying (type ());
@@ -825,6 +829,10 @@ prange::intersect (const vrange &v)
        set_pt (r);
     }
 
+  //  If this evolves to zero, clear all points-to info.
+  if (zero_p () && !pt_unknown_p ())
+    set_pt_unknown ();
+
   if (varying_compatible_p ())
     {
       set_varying (type ());
@@ -931,6 +939,12 @@ prange::verify_range () const
     }
   gcc_checking_assert (!varying_compatible_p ());
   gcc_checking_assert (m_kind == VR_RANGE);
+  if (!pt_unknown_p ())
+    {
+      gcc_checking_assert (!varying_p ());
+      gcc_checking_assert (!undefined_p ());
+      gcc_checking_assert (!zero_p ());
+    }
 }
 
 void
diff --git a/gcc/value-range.h b/gcc/value-range.h
index d5588faefb41..e6dc59eb7066 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -1429,8 +1429,6 @@ inline bool
 prange::zero_p () const
 {
   bool ret = m_kind == VR_RANGE && m_min == 0 && m_max == 0;
-  // if zero_p is true, there should be no points to info.
-  gcc_checking_assert (!ret || pt_unknown_p ());
   return ret;
 }
 
@@ -1486,6 +1484,10 @@ prange::fits_p (const vrange &) const
 inline void
 prange::set_pt (const prange &r)
 {
+  // Do not set points-to info if this is zero or undefined.
+  if (!r.pt_unknown_p () && (undefined_p () || zero_p()))
+    return;
+
   m_pt = r.m_pt;
   m_points_to_p = r.m_points_to_p;

Reply via email to