Hello,
Le 17/06/2026 à 02:29, Andrew MacLeod a écrit :
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 9dea0f64836..bae94dfa44b 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -1210,14 +1257,27 @@ fold_using_range::range_of_phi (vrange &r, gphi *phi,
fur_source &src)
if (single_arg)
src.register_relation (phi, VREL_EQ, phi_def, single_arg);
}
- else if (src.get_operand (arg_range, single_arg)
- && arg_range.singleton_p ())
+ else if (src.get_operand (arg_range, single_arg))
{
+ // Check if the single argument points to a specific object.
+ if (is_a <prange> (arg_range))
+ {
+ prange &ptr = as_a <prange> (arg_range);
+ // If it doesn't already point at something, set points to.
+ if (!ptr.pt_unknown_p ()
+ && TREE_CODE (single_arg) == ADDR_EXPR)
Shouldn't it be instead:
if (ptr.pt_unknown_p () && ...)
? (without the negation)
+ ptr.set_pt (single_arg, true);
+ r = ptr;
+ return true;
+ }
// Numerical arguments that are a constant can be returned as
// the constant. This can help fold later cases where even this
// constant might have been UNDEFINED via an unreachable edge.
- r = arg_range;
- return true;
+ if (arg_range.singleton_p ())
+ {
+ r = arg_range;
+ return true;
+ }
}
}
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index fa17dd276af..488feb5ca0f 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -690,6 +803,21 @@ prange::intersect (const vrange &v)
set_undefined ();
else if (!m_bitmask.intersect (r.m_bitmask))
set_undefined ();
+ // If only one object points to something, that is the intersection.
+ else if (pt_unknown_p () && !r.pt_unknown_p ())
+ set_pt (r);
+ else if (!pt_unknown_p () && !r.pt_unknown_p ())
+ {
+ // If both point to something, we want to be careful. Without aliasing
+ // 2 different values can point to the same thing, so UNDEFINED is
+ // not appropriate, but we want to keep the rule that intersection
+ // never becomes larger.
+ // If the other object points to something specific, and this one does
+ // not, use the specific one. Otherwise leave the range as is.
+ if (pt_invariant_away () && r.pt_invariant ())
+ set_pt (r);
One can also set undefined in case they point to and away from the same
thing, I suppose?
+ }
+
if (varying_compatible_p ())
{
set_varying (type ());
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 35421914a71..0ab67303009 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -1379,7 +1424,7 @@ prange::contains_p (tree cst) const
inline bool
prange::zero_p () const
{
- return m_kind == VR_RANGE && m_min == 0 && m_max == 0;
+ return m_kind == VR_RANGE && m_min == 0 && m_max == 0 && pt_unknown_p ();
Isn't it possible to have a range that contains only nullptr with the
points-to info set to away from something?
I'm thinking of code doing:
if (ptr == &foo)
...
else if (ptr == nullptr)
{
// range of ptr here ?
}
zero_p should return true here, shouldn't it?
}
inline bool
@@ -1428,6 +1473,100 @@ prange::fits_p (const vrange &) const
return true;
}
(...)
+
+inline bool
+prange::pt_invariant_p (const prange &r) const
+{
+ if (m_pt && m_points_to_p && vrp_operand_equal_p (r.m_pt, m_pt)
+ && m_points_to_p == r.m_points_to_p)
+ return m_pt;
+ return NULL_TREE;
+}
+
+inline bool
+prange::pt_invariant_away_p (const prange &r) const
+{
+ if (m_pt && !m_points_to_p && vrp_operand_equal_p (r.m_pt, m_pt)
+ && m_points_to_p == r.m_points_to_p)
+ return m_pt;
+ return NULL_TREE;
+}
This is a nit, but one could just as well return true and false (instead
of a tree implicitly converted) for these two.