https://gcc.gnu.org/g:47c73130063c86f3625e6d0060db06e5e781ebdb
commit r17-5682-g47c73130063c86f3625e6d0060db06e5e781ebdb Author: Andrew MacLeod <[email protected]> Date: Tue Oct 13 15:00:57 2026 -0400 Store and retrieve prange in global tables Only non-nullness was stored until now in the ptr_info_def structure. This completes saving and restoring a full prange object in the global tables. gcc/ * gimple-pretty-print.cc (dump_ssaname_info): Do not print VARYING pointer ranges. * ipa-prop.cc (ipa_set_jfunc_vr): Remove points to info from pointers as necessary. * tree-ssanames.cc (set_range_info): Handle prange. * value-query.cc (get_ssa_name_range_info): Likewise. (gimple_range_global): Likewise. gcc/testsuite/ * gcc.dg/ipa/ipa-prange-local-addr-1.c: New. * gcc.dg/tree-ssa/prange-global-1.c: New Diff: --- gcc/gimple-pretty-print.cc | 14 ++++++--- gcc/ipa-prop.cc | 25 +++++++++++++++ gcc/testsuite/gcc.dg/ipa/ipa-prange-local-addr-1.c | 32 +++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/prange-global-1.c | 18 +++++++++++ gcc/tree-ssanames.cc | 33 ++++++++++---------- gcc/value-query.cc | 36 ++++++++++------------ 6 files changed, 117 insertions(+), 41 deletions(-) diff --git a/gcc/gimple-pretty-print.cc b/gcc/gimple-pretty-print.cc index b36e50b0fd48..ecbd02c92da7 100644 --- a/gcc/gimple-pretty-print.cc +++ b/gcc/gimple-pretty-print.cc @@ -2415,14 +2415,18 @@ dump_ssaname_info (pretty_printer *pp, tree node, int spc) } } - if (!POINTER_TYPE_P (TREE_TYPE (node)) - && SSA_NAME_RANGE_INFO (node)) + if (SSA_NAME_RANGE_INFO (node)) { value_range r (TREE_TYPE (node)); get_global_range_query ()->range_of_expr (r, node); - pp_string (pp, "# RANGE "); - pp_vrange (pp, &r); - newline_and_indent (pp, spc); + /* A pointer has storage as soon as it has aliasing info, so do not + print the VARYING that results. */ + if (!r.varying_p ()) + { + pp_string (pp, "# RANGE "); + pp_vrange (pp, &r); + newline_and_indent (pp, spc); + } } } diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index c614ddccbbb0..8cc031570de8 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -2395,6 +2395,31 @@ ipa_get_value_range (const vrange &tmp) static void ipa_set_jfunc_vr (ipa_jump_func *jf, const vrange &tmp) { + /* A points-to that names something only invariant within the caller -- + the address of one of its locals, say -- must not travel to the callee. + Same restriction as ipa_record_return_value_range_1; see PR125857. + Drop just the points-to rather than the whole range, as the bounds and + the bitmask remain valid. */ + if (is_a <prange> (tmp)) + { + const prange &pr = as_a <prange> (tmp); + 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)) + { + fprintf (dump_file, "Dropping non ipa invariant points-to from "); + tmp.dump (dump_file); + fprintf (dump_file, "\n"); + } + prange stripped = pr; + stripped.set_pt_unknown (); + jf->m_vr = ipa_get_value_range (stripped); + return; + } + } jf->m_vr = ipa_get_value_range (tmp); } diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-prange-local-addr-1.c b/gcc/testsuite/gcc.dg/ipa/ipa-prange-local-addr-1.c new file mode 100644 index 000000000000..baad06d1ca7e --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/ipa-prange-local-addr-1.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-ipa-cp-details" } */ + +/* A prange can carry the address of an object. The address of an automatic + is gimple_min_invariant inside its own function but not ip-invariant, so + it must not reach a callee through a jump function. This test confirms the + equivalent fix for PR125857 for globals and params is present. */ + +int sink; + +static __attribute__((noinline)) int +walk (int x, int *flagp) +{ + if (x > 10) { *flagp = 1; return 1; } + if (x < -10) { *flagp = 2; return 2; } + return 0; +} + +int +top (int a, int b) +{ + int flag = 0; + int r = walk (a, &flag); + if (r) + return r; + r = walk (b, &flag); + if (r) + return r; + return flag; +} + +/* { dg-final { scan-ipa-dump "Dropping non ipa invariant points-to" "cp" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prange-global-1.c b/gcc/testsuite/gcc.dg/tree-ssa/prange-global-1.c new file mode 100644 index 000000000000..fbc04b14c651 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/prange-global-1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized-alias" } */ + +/* A pointer's global range used to be a single non-null bit. + With pranges properly stored, we should pick up the mask. */ + +extern void g (void *); + +long * +f (long *q) +{ + if ((__UINTPTR_TYPE__) q & 15) + __builtin_unreachable (); + g (q); + return q; +} + +/* { dg-final { scan-tree-dump "prange.* MASK " "optimized" } } */ diff --git a/gcc/tree-ssanames.cc b/gcc/tree-ssanames.cc index 2dab3fe947cb..9f0cddfb38ab 100644 --- a/gcc/tree-ssanames.cc +++ b/gcc/tree-ssanames.cc @@ -444,28 +444,27 @@ set_range_info (tree name, const vrange &r) // Pick up the current range, or VARYING if none. tree type = TREE_TYPE (name); + value_range tmp (type); + if (range_info_p (name)) + range_info_get_range (name, tmp); + else + tmp.set_varying (type); + + // If the result doesn't change, or is undefined, return false. + if (!tmp.intersect (r) || tmp.undefined_p ()) + return false; + if (POINTER_TYPE_P (type)) { - struct ptr_info_def *pi = get_ptr_info (name); // If R is nonnull and pi is not, set nonnull. - if (!r.contains_zero_p () && (!pi || pi->pt.null)) + struct ptr_info_def *pi = get_ptr_info (name); + if (!tmp.contains_zero_p () && pi->pt.null) set_ptr_nonnull (name); - else - return false; - } - else - { - value_range tmp (type); - if (range_info_p (name)) - range_info_get_range (name, tmp); - else - tmp.set_varying (type); - // If the result doesn't change, or is undefined, return false. - if (!tmp.intersect (r) || tmp.undefined_p ()) - return false; - if (!range_info_set_range (name, tmp)) - return false; } + + if (!range_info_set_range (name, tmp)) + return false; + if (dump_file) { value_range tmp (type); diff --git a/gcc/value-query.cc b/gcc/value-query.cc index a623d5f83bad..3e64f431fd2c 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -582,7 +582,6 @@ static inline void get_ssa_name_range_info (vrange &r, const_tree name) { tree type = TREE_TYPE (name); - gcc_checking_assert (!POINTER_TYPE_P (type)); gcc_checking_assert (TREE_CODE (name) == SSA_NAME); vrange_storage *ri = SSA_NAME_RANGE_INFO (name); @@ -633,21 +632,20 @@ gimple_range_global (vrange &r, tree name, struct function *fun) // Use a range from an SSA_NAME's available range. if (TREE_CODE (sym) == PARM_DECL) { - // Try to use the "nonnull" attribute to create ~[0, 0] - // anti-ranges for pointers. Note that this is only valid with - // default definitions of PARM_DECLs. + get_ssa_name_range_info (r, name); + if (r.undefined_p ()) + r.set_varying (type); + // Try to use the "nonnull" attribute to refine a pointer to + // ~[0, 0]. Note that this is only valid with default definitions + // of PARM_DECLs if (POINTER_TYPE_P (type) && ((cfun && fun == cfun && nonnull_arg_p (sym)) || get_ssa_name_ptr_info_nonnull (name))) - r.set_nonzero (type); - else if (!POINTER_TYPE_P (type)) { - get_ssa_name_range_info (r, name); - if (r.undefined_p ()) - r.set_varying (type); + prange nz (type); + nz.set_nonzero (type); + r.intersect (nz); } - else - r.set_varying (type); } // If this is a local automatic with no definition, use undefined. else if (TREE_CODE (sym) != RESULT_DECL) @@ -655,18 +653,18 @@ gimple_range_global (vrange &r, tree name, struct function *fun) else r.set_varying (type); } - else if (!POINTER_TYPE_P (type) && SSA_NAME_RANGE_INFO (name)) + else if (SSA_NAME_RANGE_INFO (name)) { get_ssa_name_range_info (r, name); if (r.undefined_p ()) r.set_varying (type); - } - else if (POINTER_TYPE_P (type) && SSA_NAME_PTR_INFO (name)) - { - if (get_ssa_name_ptr_info_nonnull (name)) - r.set_nonzero (type); - else - r.set_varying (type); + // pt.null may still carry non-nullness the stored range does not. + if (POINTER_TYPE_P (type) && get_ssa_name_ptr_info_nonnull (name)) + { + prange nz (type); + nz.set_nonzero (type); + r.intersect (nz); + } } else r.set_varying (type);
