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" } } */
