Im not sure if this actually fixes the PR, but I think its the cause, or at least contributes to it and needs to be fixed anyway.

When a prange is compared for equality, we also compare the points-to field.  The problem is IPA unshares all the points-to fields, so 2 different pranges which point to the same object may have 2 different pointers.   This is fixed in this patch by calling vrp_operand_eqial_p () in the comparison which gives us the desired behaviour when comparing ranges.

Internally, IPA is using the prange_storage object. This object is frequently cached in a hash table, and as such we need to be able to distinguish between different prange_storage objects.  In this case, equality remains based on the physical pointer value. The storage object are really just hunks of memory, and this retains that view.     If we try to use the vrp_operand_equal_p, the hash table verification routines trap because you can get 2 different hash values for objects that compare the same.  This behaviour has not changed, I just added a comment to make it clearer that it is on purpose.

Bootstrapped on x86_64-pc-linux-gnu with no regressions. pushed.

Andrew
From abce0bfa12f489f715545f36ca5d6d658d71a411 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <[email protected]>
Date: Fri, 17 Jul 2026 11:53:51 -0400
Subject: [PATCH 3/3] use vrp_operand_equal_p in points to comparisons.

IPA iunshares points-to info for prange storage objects. This means they
may point to the same logical object, but have different physical pointer
values.

A prange_storage object is a hunk of memory, and it will continue to use
raw pointer comparisons for equality.  Otherwise things like hash table
lookups will think there are different hashs for the same item.

Prange however should use vrp_operand_equal_p for comparisons.  This will
prevent two prange objects from comparing unequal due to tree unsharing.

	PR tree-optimization/126222
	* value-range.h (prange::pt_equal_p): Use vrp_operand_equal_p.
---
 gcc/value-range-storage.cc | 1 +
 gcc/value-range.h          | 6 +++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc
index 6a7ce4ceed3..837c40bb72e 100644
--- a/gcc/value-range-storage.cc
+++ b/gcc/value-range-storage.cc
@@ -817,6 +817,7 @@ prange_storage::equal_p (const prange &r) const
 
   if (m_pt != r.m_pt)
     return false;
+  // Storage objects are only equal If they point to the same memory.
   if (m_points_to_p != r.m_points_to_p)
     return false;
 
diff --git a/gcc/value-range.h b/gcc/value-range.h
index e6dc59eb706..307779b37ef 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -1519,7 +1519,11 @@ prange::pt_unknown_p () const
 inline bool
 prange::pt_equal_p (const prange &p) const
 {
-  return (m_points_to_p == p.m_points_to_p && m_pt == p.m_pt);
+  // A prange object invokes vrp_operand_equal_p as we want ranges to compare
+  // equal to each other if they refer to the same object, even if the
+  // tree has become unshared.
+  return (m_points_to_p == p.m_points_to_p
+	  && vrp_operand_equal_p (m_pt, p.m_pt));
 }
 
 inline bool
-- 
2.45.0

Reply via email to