Hi, one of common cases why we lose track on SSA name in modref propagation is the situation where name is passed to funtion call and we then thus continue by propagating through return value.
This patch adds simple logic to track arguments that does not escape to return value. On cc1plus the improvement in PTA disambiguation is about 1.8% that is not too great, but it is easy enough to discover and often simplifies the propagation. I suppose this can be also useful for tree-ssa-structalias itself since it may also prevent args from escaping to return values. Bootstrapped/regtested x86_64-linux, OK? Honza * ipa-modref.c (dump_eaf_flags): Add EAF_NOT_RETURNED. (modref_lattice::init): Add EAF_NOT_RETURNED. (merge_call_lhs_flags): Do nothing for EAF_NOT_RETURNED args. (analyze_ssa_name_flags): Clear EAF_NOT_RETURNED on return; add EAF_NOT_RETURNED to call flags. (modref_merge_call_site_flags): Add EAF_NOT_RETURNED. * tree-core.h (EAF_NOT_RETURNED): New flags. diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c index 7f673675d1d..155bf59fc53 100644 --- a/gcc/ipa-modref.c +++ b/gcc/ipa-modref.c @@ -153,6 +153,8 @@ dump_eaf_flags (FILE *out, int flags, bool newline = true) fprintf (out, " noescape"); if (flags & EAF_UNUSED) fprintf (out, " unused"); + if (flags & EAF_NOT_RETURNED) + fprintf (out, " not_returned"); if (newline) fprintf (out, "\n"); } @@ -1361,7 +1363,8 @@ public: void modref_lattice::init () { - flags = EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE | EAF_UNUSED; + flags = EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE | EAF_UNUSED + | EAF_NOT_RETURNED; open = true; known = false; } @@ -1531,6 +1534,9 @@ merge_call_lhs_flags (gcall *call, int arg, int index, bool deref, && (flags & ERF_RETURN_ARG_MASK) != arg) return; + if (gimple_call_arg_flags (call, arg) & EAF_NOT_RETURNED) + return; + /* If return value is SSA name determine its flags. */ if (TREE_CODE (gimple_call_lhs (call)) == SSA_NAME) { @@ -1601,11 +1607,17 @@ analyze_ssa_name_flags (tree name, vec<modref_lattice> &lattice, int depth, bool print_gimple_stmt (dump_file, use_stmt, 0); } - /* Gimple return may load the return value. */ + /* Gimple return may load the return value. + and clears EAF_NOT_RETURNED flag. */ if (greturn *ret = dyn_cast <greturn *> (use_stmt)) { if (memory_access_to (gimple_return_retval (ret), name)) - lattice [index].merge_direct_load (); + { + lattice[index].merge_direct_load (); + lattice[index].merge (~EAF_NOT_RETURNED); + } + else if (gimple_return_retval (ret) == name) + lattice[index].merge (~EAF_NOT_RETURNED); } /* Account for LHS store, arg loads and flags from callee function. */ else if (gcall *call = dyn_cast <gcall *> (use_stmt)) @@ -1645,7 +1657,8 @@ analyze_ssa_name_flags (tree name, vec<modref_lattice> &lattice, int depth, bool { if (!(ecf_flags & (ECF_CONST | ECF_NOVOPS))) { - int call_flags = gimple_call_arg_flags (call, i); + int call_flags = gimple_call_arg_flags (call, i) + | EAF_NOT_RETURNED; if (ignore_stores) call_flags |= EAF_NOCLOBBER | EAF_NOESCAPE; @@ -1666,8 +1679,9 @@ analyze_ssa_name_flags (tree name, vec<modref_lattice> &lattice, int depth, bool lattice[index].merge_direct_load (); else { - int call_flags = deref_flags (gimple_call_arg_flags (call, i), - ignore_stores); + int call_flags = deref_flags + (gimple_call_arg_flags (call, i), + ignore_stores) | EAF_NOT_RETURNED; if (!record_ipa) lattice[index].merge (call_flags); if (record_ipa) @@ -3612,8 +3626,9 @@ modref_merge_call_site_flags (escape_summary *sum, flags |= EAF_NOESCAPE | EAF_NOCLOBBER; flags_lto |= EAF_NOESCAPE | EAF_NOCLOBBER; } - flags |= ee->min_flags; - flags_lto |= ee->min_flags; + /* Returning the value is already accounted to at local propagation. */ + flags |= ee->min_flags | EAF_NOT_RETURNED; + flags_lto |= ee->min_flags | EAF_NOT_RETURNED; if (cur_summary && ee->parm_index < cur_summary->arg_flags.length ()) { int f = cur_summary->arg_flags[ee->parm_index]; diff --git a/gcc/tree-core.h b/gcc/tree-core.h index c9280a8d3b1..3e9455a553b 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -110,6 +110,9 @@ struct die_struct; /* Nonzero if the argument is not used by the function. */ #define EAF_UNUSED (1 << 3) +/* Nonzero if the argument does not escape to return value. */ +#define EAF_NOT_RETURNED (1 << 4) + /* Call return flags. */ /* Mask for the argument number that is returned. Lower two bits of the return flags, encodes argument slots zero to three. */