On 6/17/26 08:40, Mikael Morin wrote:
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)


Indeed, thanks.



+        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?

Presumably one could do that yes.  I'll try adding that as well.

Brings up a question..   currently

ptr.pt_invariant_p (r)   returns true if r and ptr point to the same thing.

ptr.pt_invariant_away_p (r) return true if r and ptr *both* point away from the same thing...    Im thinking maybe it should be changed to return true if one element points to an object and the other points away?      That seems more useful in general.... ? and possibly more the expected behaviour?


+    }
+
   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?

yes, zero_p () will return true, and we drop all points to information, either to or away for zero_p.    zero_p() implies it points away from &foo, and everything else already.

At least that is the way things stand at the moment.   I should probably change that to assert that pt_uknown_p is true.


 }

 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.

No, thats suppose to be  true and false..  a remnant from the earlier version of the API :-P

Thanks for paying attention :-)

Andrew



Reply via email to