I put the assert in zero_p() to trigger if it returned true but had a
points to. I figured it would trigger evenually.. sooner than later
apparently :-)
Intersection is where it i smost liekly to happen, but I also ensdure it
cant be set accidentally via the set_pt () routines. I moved the assert
from zero_p() as it is possible that a range under construction might
check zero_p () before it has finalized. It is now in verify_range()
which is the proper place.
Turned out there were a few combinations in intersect which resulted in
a points to field in a zero_p() range, so after we do all the building,
simply do a final check that if the range evolved to zero.. clear any
points to fields that may have been set along the way. This turned out
to be much simpler than trying to detect all the possible combinations.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
From 800dfdb176bcf657703e79ef730d722a88d2048a Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <[email protected]>
Date: Tue, 23 Jun 2026 16:11:16 -0400
Subject: [PATCH 3/3] 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: New.
---
gcc/testsuite/gcc.dg/pr125910.c | 15 +++++++++++++++
gcc/value-range.cc | 14 ++++++++++++++
gcc/value-range.h | 6 ++++--
3 files changed, 33 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/pr125910.c
diff --git a/gcc/testsuite/gcc.dg/pr125910.c b/gcc/testsuite/gcc.dg/pr125910.c
new file mode 100644
index 00000000000..88ec139f979
--- /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 86eb2f507fb..722eca9abca 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 d5588faefb4..e6dc59eb706 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;
--
2.45.0