https://gcc.gnu.org/g:5f978cc72944757f573e82b6dd511d029202a42b

commit r17-5683-g5f978cc72944757f573e82b6dd511d029202a42b
Author: Andrew MacLeod <[email protected]>
Date:   Tue Oct 13 16:31:45 2026 -0400

    Handle points_away in prange::operator equal and not_equal.
    
    == and != should produce a points-away if the result is not equal and one
    object has a points-to field.
    Also adjust ipa_record_return_value_range_1 to bail if a points-away
    field is present.
    
            gcc/
            * ipa-prop.cc (ipa_record_return_value_range_1): Also check for
            points-away.
            * range-op-ptr.cc (operator_equal::op1_range): Produce points-away
            when appropriate.
            (operator_not_equal::op1_range): Likewise.
    
            gcc/testsuite/
            * gcc.dg/tree-ssa/prange-points-away-1.c: New.

Diff:
---
 gcc/ipa-prop.cc                                      |  2 ++
 gcc/range-op-ptr.cc                                  | 18 ++++++++++++++----
 gcc/testsuite/gcc.dg/tree-ssa/prange-points-away-1.c | 20 ++++++++++++++++++++
 3 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
index 8cc031570de8..209dd1d4c0bf 100644
--- a/gcc/ipa-prop.cc
+++ b/gcc/ipa-prop.cc
@@ -6039,6 +6039,8 @@ ipa_record_return_value_range_1 (cgraph_node *n, 
value_range val)
     {
       const prange &pr = as_a <prange> (val);
       tree t = pr.pt_invariant ();
+      if (!t)
+       t = pr.pt_invariant_away ();
       if (t && !is_gimple_ip_invariant (t))
         {
          if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 8113d67f62e0..8dfcceb64fa9 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -947,7 +947,7 @@ operator_equal::op1_range (prange &r, tree type,
 
     case BRS_FALSE:
       // If the result is false, the only time we know anything is
-      // if OP2 is a constant.
+      // if OP2 is a constant, or refers to a known object.
       if (!op2.undefined_p ()
          && wi::eq_p (op2.lower_bound(), op2.upper_bound()))
        {
@@ -956,7 +956,12 @@ operator_equal::op1_range (prange &r, tree type,
            return false;
        }
       else
-       r.set_varying (type);
+       {
+         r.set_varying (type);
+         // OP2 refers to OBJ, so OP1 does not refer to OBJ.
+         if (tree obj = op2.pt_invariant ())
+           r.set_pt (obj, false);
+       }
       break;
 
     default:
@@ -1047,7 +1052,7 @@ operator_not_equal::op1_range (prange &r, tree type,
     {
     case BRS_TRUE:
       // If the result is true, the only time we know anything is if
-      // OP2 is a constant.
+      // OP2 is a constant, or refers to a known object.
       if (!op2.undefined_p ()
          && wi::eq_p (op2.lower_bound(), op2.upper_bound()))
        {
@@ -1056,7 +1061,12 @@ operator_not_equal::op1_range (prange &r, tree type,
            return false;
        }
       else
-       r.set_varying (type);
+       {
+         r.set_varying (type);
+         // Check if op1 is known not to refer to op2 points to object.
+         if (tree obj = op2.pt_invariant ())
+           r.set_pt (obj, false);
+       }
       break;
 
     case BRS_FALSE:
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prange-points-away-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/prange-points-away-1.c
new file mode 100644
index 000000000000..c3eee9229066
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/prange-points-away-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized-alias" } */
+
+int gv, *a, **b = &a;
+
+int *
+d (int *p)
+{
+  if (p == &gv)
+    __builtin_unreachable ();
+  return p;
+}
+
+int
+main ()
+{
+  *b = d (a);
+}
+
+/* { dg-final { scan-tree-dump "! -> &gv" "optimized" } } */

Reply via email to