On Mon, 1 Nov 2021, Jan Hubicka wrote: > Hi, > this is patchs teaches ipa-modref about the static chain that is, like > retslot, a hiden argument. The patch is pretty much symemtric to what > was done for retslot handling and I verified it does the intended job > for Ada LTO bootstrap. > > Bootstrapped/regtested x86_64-linux, OK?
OK. Thanks, Richard. > Honza > > gcc/ChangeLog: > > * gimple.c (gimple_call_static_chain_flags): New function. > * gimple.h (gimple_call_static_chain_flags): Declare > * ipa-modref.c (modref_summary::modref_summary): Initialize > static_chain_flags. > (modref_summary_lto::modref_summary_lto): Likewise. > (modref_summary::useful_p): Test static_chain_flags. > (modref_summary_lto::useful_p): Likewise. > (struct modref_summary_lto): Add static_chain_flags. > (modref_summary::dump): Dump static_chain_flags. > (modref_summary_lto::dump): Likewise. > (struct escape_point): Add static_cahin_arg. > (analyze_ssa_name_flags): Use gimple_call_static_chain_flags. > (analyze_parms): Handle static chains. > (modref_summaries::duplicate): Duplicate static_chain_flags. > (modref_summaries_lto::duplicate): Likewise. > (modref_write): Stream static_chain_flags. > (read_section): Likewise. > (modref_merge_call_site_flags): Handle static_chain_flags. > * ipa-modref.h (struct modref_summary): Add static_chain_flags. > * tree-ssa-structalias.c (handle_rhs_call): Use > * gimple_static_chain_flags. > > gcc/testsuite/ChangeLog: > > * gcc.dg/ipa/modref-3.c: New test. > > diff --git a/gcc/gimple.c b/gcc/gimple.c > index 22dd6417d19..ef07d9385c5 100644 > --- a/gcc/gimple.c > +++ b/gcc/gimple.c > @@ -1647,6 +1647,33 @@ gimple_call_retslot_flags (const gcall *stmt) > return flags; > } > > +/* Detects argument flags for static chain on call STMT. */ > + > +int > +gimple_call_static_chain_flags (const gcall *stmt) > +{ > + int flags = 0; > + > + tree callee = gimple_call_fndecl (stmt); > + if (callee) > + { > + cgraph_node *node = cgraph_node::get (callee); > + modref_summary *summary = node ? get_modref_function_summary (node) > + : NULL; > + > + if (summary) > + { > + int modref_flags = summary->static_chain_flags; > + > + /* We have possibly optimized out load. Be conservative here. */ > + gcc_checking_assert (node->binds_to_current_def_p ()); > + if (dbg_cnt (ipa_mod_ref_pta)) > + flags |= modref_flags; > + } > + } > + return flags; > +} > + > /* Detects return flags for the call STMT. */ > > int > diff --git a/gcc/gimple.h b/gcc/gimple.h > index 23a124ec769..3cde3cde7fe 100644 > --- a/gcc/gimple.h > +++ b/gcc/gimple.h > @@ -1590,6 +1590,7 @@ bool gimple_call_same_target_p (const gimple *, const > gimple *); > int gimple_call_flags (const gimple *); > int gimple_call_arg_flags (const gcall *, unsigned); > int gimple_call_retslot_flags (const gcall *); > +int gimple_call_static_chain_flags (const gcall *); > int gimple_call_return_flags (const gcall *); > bool gimple_call_nonnull_result_p (gcall *); > tree gimple_call_nonnull_arg (gcall *); > diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c > index d866d9ed6b3..ae8ed53b396 100644 > --- a/gcc/ipa-modref.c > +++ b/gcc/ipa-modref.c > @@ -270,7 +270,8 @@ static GTY(()) fast_function_summary <modref_summary_lto > *, va_gc> > /* Summary for a single function which this pass produces. */ > > modref_summary::modref_summary () > - : loads (NULL), stores (NULL), retslot_flags (0), writes_errno (false) > + : loads (NULL), stores (NULL), retslot_flags (0), static_chain_flags (0), > + writes_errno (false) > { > } > > @@ -325,6 +326,9 @@ modref_summary::useful_p (int ecf_flags, bool check_flags) > arg_flags.release (); > if (check_flags && remove_useless_eaf_flags (retslot_flags, ecf_flags, > false)) > return true; > + if (check_flags > + && remove_useless_eaf_flags (static_chain_flags, ecf_flags, false)) > + return true; > if (ecf_flags & ECF_CONST) > return false; > if (loads && !loads->every_base) > @@ -367,6 +371,7 @@ struct GTY(()) modref_summary_lto > modref_records_lto *stores; > auto_vec<eaf_flags_t> GTY((skip)) arg_flags; > eaf_flags_t retslot_flags; > + eaf_flags_t static_chain_flags; > bool writes_errno; > > modref_summary_lto (); > @@ -378,7 +383,8 @@ struct GTY(()) modref_summary_lto > /* Summary for a single function which this pass produces. */ > > modref_summary_lto::modref_summary_lto () > - : loads (NULL), stores (NULL), retslot_flags (0), writes_errno (false) > + : loads (NULL), stores (NULL), retslot_flags (0), static_chain_flags (0), > + writes_errno (false) > { > } > > @@ -406,6 +412,9 @@ modref_summary_lto::useful_p (int ecf_flags, bool > check_flags) > arg_flags.release (); > if (check_flags && remove_useless_eaf_flags (retslot_flags, ecf_flags, > false)) > return true; > + if (check_flags > + && remove_useless_eaf_flags (static_chain_flags, ecf_flags, false)) > + return true; > if (ecf_flags & ECF_CONST) > return false; > if (loads && !loads->every_base) > @@ -619,6 +628,11 @@ modref_summary::dump (FILE *out) > fprintf (out, " Retslot flags:"); > dump_eaf_flags (out, retslot_flags); > } > + if (static_chain_flags) > + { > + fprintf (out, " Static chain flags:"); > + dump_eaf_flags (out, static_chain_flags); > + } > } > > /* Dump summary. */ > @@ -646,6 +660,11 @@ modref_summary_lto::dump (FILE *out) > fprintf (out, " Retslot flags:"); > dump_eaf_flags (out, retslot_flags); > } > + if (static_chain_flags) > + { > + fprintf (out, " Static chain flags:"); > + dump_eaf_flags (out, static_chain_flags); > + } > } > > /* Get function summary for FUNC if it exists, return NULL otherwise. */ > @@ -1415,7 +1434,8 @@ struct escape_point > /* Extra hidden args we keep track of. */ > enum hidden_args > { > - retslot_arg = -1 > + retslot_arg = -1, > + static_chain_arg = -2 > }; > /* Value escapes to this call. */ > gcall *call; > @@ -1776,11 +1796,9 @@ analyze_ssa_name_flags (tree name, vec<modref_lattice> > &lattice, int depth, > lattice[index].merge (gimple_call_retslot_flags (call)); > } > > - /* We do not track accesses to the static chain (we could) > - so give up. */ > if (gimple_call_chain (call) > && (gimple_call_chain (call) == name)) > - lattice[index].merge (0); > + lattice[index].merge (gimple_call_static_chain_flags (call)); > > /* Process internal functions and right away. */ > bool record_ipa = ipa && !gimple_call_internal_p (call); > @@ -1970,6 +1988,7 @@ analyze_parms (modref_summary *summary, > modref_summary_lto *summary_lto, > unsigned int count = 0; > int ecf_flags = flags_from_decl_or_type (current_function_decl); > tree retslot = NULL; > + tree static_chain = NULL; > > /* For novops functions we have nothing to gain by EAF flags. */ > if (ecf_flags & ECF_NOVOPS) > @@ -1979,12 +1998,14 @@ analyze_parms (modref_summary *summary, > modref_summary_lto *summary_lto, > if (DECL_RESULT (current_function_decl) > && DECL_BY_REFERENCE (DECL_RESULT (current_function_decl))) > retslot = ssa_default_def (cfun, DECL_RESULT (current_function_decl)); > + if (cfun->static_chain_decl) > + static_chain = ssa_default_def (cfun, cfun->static_chain_decl); > > for (tree parm = DECL_ARGUMENTS (current_function_decl); parm; > parm = TREE_CHAIN (parm)) > count++; > > - if (!count && !retslot) > + if (!count && !retslot && !static_chain) > return; > > auto_vec<modref_lattice> lattice; > @@ -2058,6 +2079,22 @@ analyze_parms (modref_summary *summary, > modref_summary_lto *summary_lto, > escape_point::retslot_arg, flags); > } > } > + if (static_chain) > + { > + analyze_ssa_name_flags (static_chain, lattice, 0, ipa); > + int flags = lattice[SSA_NAME_VERSION (static_chain)].flags; > + > + flags = remove_useless_eaf_flags (flags, ecf_flags, false); > + if (flags) > + { > + if (summary) > + summary->static_chain_flags = flags; > + if (summary_lto) > + summary_lto->static_chain_flags = flags; > + record_escape_points (lattice[SSA_NAME_VERSION (static_chain)], > + escape_point::static_chain_arg, flags); > + } > + } > if (ipa) > for (unsigned int i = 0; i < num_ssa_names; i++) > lattice[i].release (); > @@ -2342,6 +2379,7 @@ modref_summaries::duplicate (cgraph_node *, cgraph_node > *dst, > if (src_data->arg_flags.length ()) > dst_data->arg_flags = src_data->arg_flags.copy (); > dst_data->retslot_flags = src_data->retslot_flags; > + dst_data->static_chain_flags = src_data->static_chain_flags; > } > > /* Called when new clone is inserted to callgraph late. */ > @@ -2368,6 +2406,7 @@ modref_summaries_lto::duplicate (cgraph_node *, > cgraph_node *, > if (src_data->arg_flags.length ()) > dst_data->arg_flags = src_data->arg_flags.copy (); > dst_data->retslot_flags = src_data->retslot_flags; > + dst_data->static_chain_flags = src_data->static_chain_flags; > } > > namespace > @@ -2685,6 +2724,7 @@ modref_write () > for (unsigned int i = 0; i < r->arg_flags.length (); i++) > streamer_write_uhwi (ob, r->arg_flags[i]); > streamer_write_uhwi (ob, r->retslot_flags); > + streamer_write_uhwi (ob, r->static_chain_flags); > > write_modref_records (r->loads, ob); > write_modref_records (r->stores, ob); > @@ -2786,6 +2826,13 @@ read_section (struct lto_file_decl_data *file_data, > const char *data, > modref_sum->retslot_flags = flags; > if (modref_sum_lto) > modref_sum_lto->retslot_flags = flags; > + > + flags = streamer_read_uhwi (&ib); > + if (modref_sum) > + modref_sum->static_chain_flags = flags; > + if (modref_sum_lto) > + modref_sum_lto->static_chain_flags = flags; > + > read_modref_records (&ib, data_in, > modref_sum ? &modref_sum->loads : NULL, > modref_sum_lto ? &modref_sum_lto->loads : NULL); > @@ -3871,6 +3918,8 @@ modref_merge_call_site_flags (escape_summary *sum, > { > eaf_flags_t &f = ee->parm_index == escape_point::retslot_arg > ? cur_summary->retslot_flags > + : ee->parm_index == escape_point::static_chain_arg > + ? cur_summary->static_chain_flags > : cur_summary->arg_flags[ee->parm_index]; > if ((f & flags) != f) > { > @@ -3886,6 +3935,8 @@ modref_merge_call_site_flags (escape_summary *sum, > { > eaf_flags_t &f = ee->parm_index == escape_point::retslot_arg > ? cur_summary_lto->retslot_flags > + : ee->parm_index == escape_point::static_chain_arg > + ? cur_summary_lto->static_chain_flags > : cur_summary_lto->arg_flags[ee->parm_index]; > if ((f & flags_lto) != f) > { > diff --git a/gcc/ipa-modref.h b/gcc/ipa-modref.h > index a4db27471eb..ddc86869069 100644 > --- a/gcc/ipa-modref.h > +++ b/gcc/ipa-modref.h > @@ -32,6 +32,7 @@ struct GTY(()) modref_summary > modref_records *stores; > auto_vec<eaf_flags_t> GTY((skip)) arg_flags; > eaf_flags_t retslot_flags; > + eaf_flags_t static_chain_flags; > bool writes_errno; > > modref_summary (); > diff --git a/gcc/testsuite/gcc.dg/ipa/modref-3.c > b/gcc/testsuite/gcc.dg/ipa/modref-3.c > new file mode 100644 > index 00000000000..84013541ce8 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/ipa/modref-3.c > @@ -0,0 +1,20 @@ > +/* { dg-options "-O2 -fdump-ipa-modref" } */ > +/* { dg-do link } */ > +int *ptr; > +void linker_error (); > +int > +main () > +{ > + int a; > + __attribute__((noinline)) int test2 () > + { > + ptr = 0; > + return a; > + } > + a = 1; > + test2 (); > + if (a != 1) > + linker_error (); > + return 0; > +} > +/* { dg-final { scan-ipa-dump "Static chain flags: noclobber noescape > nodirectescape" "modref" } } */ > diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c > index 99072df0768..d2a955dafeb 100644 > --- a/gcc/tree-ssa-structalias.c > +++ b/gcc/tree-ssa-structalias.c > @@ -4246,7 +4246,8 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results, > /* The static chain escapes as well. */ > if (gimple_call_chain (stmt)) > handle_call_arg (stmt, gimple_call_chain (stmt), results, > - implicit_eaf_flags, > + implicit_eaf_flags > + | gimple_call_static_chain_flags (stmt), > callescape->id, writes_global_memory); > > /* And if we applied NRV the address of the return slot escapes as well. > */ > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Ivo Totev; HRB 36809 (AG Nuernberg)