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.

Reply via email to