On Mon, 1 Nov 2021, Jan Hubicka wrote: > Hi, > this patch adds EAF_NOT_RETURNED_DIRECTLY which works similarly as > EAF_NODIRECTESCAPE. Values pointed to by a given argument may be returned but > not the argument itself. This helps PTA quite noticeably because we mostly > care about tracking points to which given memory location can escape. > > I think this is about last reasonable improvement we can get to EAF > flags. > > cc1plus disambiguation counts change from: > > Alias oracle query stats: > refs_may_alias_p: 77976088 disambiguations, 98744590 queries > ref_maybe_used_by_call_p: 572845 disambiguations, 79014622 queries > call_may_clobber_ref_p: 340823 disambiguations, 344823 queries > nonoverlapping_component_refs_p: 0 disambiguations, 26590 queries > nonoverlapping_refs_since_match_p: 31626 disambiguations, 65379 must > overlaps, 97963 queries > aliasing_component_refs_p: 57414 disambiguations, 11434878 queries > TBAA oracle: 27749649 disambiguations 91624184 queries > 14733408 are in alias set 0 > 8847139 queries asked about the same object > 139 queries asked about the same alias set > 0 access volatile > 38412201 are dependent in the DAG > 1881648 are aritificially in conflict with void * > > Modref stats: > modref use: 23785 disambiguations, 702425 queries > modref clobber: 2296391 disambiguations, 22690531 queries > 5260226 tbaa queries (0.231825 per modref query) > 731741 base compares (0.032249 per modref query) > > PTA query stats: > pt_solution_includes: 12580233 disambiguations, 35854408 queries > pt_solutions_intersect: 1409041 disambiguations, 13496899 queries > > To: > > Alias oracle query stats: > refs_may_alias_p: 78304485 disambiguations, 98830913 queries > ref_maybe_used_by_call_p: 630360 disambiguations, 79308222 queries > call_may_clobber_ref_p: 381549 disambiguations, 384627 queries > nonoverlapping_component_refs_p: 0 disambiguations, 26299 queries > nonoverlapping_refs_since_match_p: 29919 disambiguations, 64917 must > overlaps, 95781 queries > aliasing_component_refs_p: 57250 disambiguations, 11336880 queries > TBAA oracle: 27835747 disambiguations 91534430 queries > 14884868 are in alias set 0 > 8933627 queries asked about the same object > 123 queries asked about the same alias set > 0 access volatile > 37974723 are dependent in the DAG > 1905342 are aritificially in conflict with void * > > Modref stats: > modref use: 24929 disambiguations, 756294 queries > modref clobber: 2334910 disambiguations, 23414495 queries > 5359212 tbaa queries (0.228884 per modref query) > 754642 base compares (0.032230 per modref query) > > PTA query stats: > pt_solution_includes: 13262256 disambiguations, 36306509 queries > pt_solutions_intersect: 1574672 disambiguations, 13638933 queries > > So about 5% more pt_solution_includes and 11% more pt_solutions_intersect > disambiguations. > > Bootstrapped/regtested x86_64-linux, OK?
OK. Thanks, Richard. > Honza > > gcc/ChangeLog: > > * tree-core.h (EAF_NOT_RETURNED_DIRECTLY): New flag. > (EAF_NOREAD): Renumber. > * ipa-modref.c (dump_eaf_flags): Dump EAF_NOT_RETURNED_DIRECTLY. > (remove_useless_eaf_flags): Handle EAF_NOT_RETURNED_DIRECTLY > (deref_flags): Likewise. > (modref_lattice::init): Likewise. > (modref_lattice::merge): Likewise. > (merge_call_lhs_flags): Likewise. > (analyze_ssa_name_flags): Likewise. > (modref_merge_call_site_flags): Likewise. > * tree-ssa-structalias.c (handle_call_arg): Likewise. > > gcc/testsuite/ChangeLog: > > * gcc.dg/ipa/modref-3.c: New test. > * gcc.dg/tree-ssa/modref-10.c: New test. > > diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c > index d866d9ed6b3..c0aae084dbd 100644 > --- a/gcc/ipa-modref.c > +++ b/gcc/ipa-modref.c > @@ -160,6 +160,8 @@ dump_eaf_flags (FILE *out, int flags, bool newline = true) > fprintf (out, " unused"); > if (flags & EAF_NOT_RETURNED) > fprintf (out, " not_returned"); > + if (flags & EAF_NOT_RETURNED_DIRECTLY) > + fprintf (out, " not_returned_directly"); > if (flags & EAF_NOREAD) > fprintf (out, " noread"); > if (newline) > @@ -295,7 +297,7 @@ remove_useless_eaf_flags (int eaf_flags, int ecf_flags, > bool returns_void) > else if (ecf_flags & ECF_PURE) > eaf_flags &= ~implicit_pure_eaf_flags; > else if ((ecf_flags & ECF_NORETURN) || returns_void) > - eaf_flags &= ~EAF_NOT_RETURNED; > + eaf_flags &= ~(EAF_NOT_RETURNED | EAF_NOT_RETURNED_DIRECTLY); > return eaf_flags; > } > > @@ -1373,7 +1375,7 @@ memory_access_to (tree op, tree ssa_name) > static int > deref_flags (int flags, bool ignore_stores) > { > - int ret = EAF_NODIRECTESCAPE; > + int ret = EAF_NODIRECTESCAPE | EAF_NOT_RETURNED_DIRECTLY; > /* If argument is unused just account for > the read involved in dereference. */ > if (flags & EAF_UNUSED) > @@ -1458,7 +1460,8 @@ modref_lattice::init () > { > /* All flags we track. */ > int f = EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE | EAF_UNUSED > - | EAF_NODIRECTESCAPE | EAF_NOT_RETURNED | EAF_NOREAD; > + | EAF_NODIRECTESCAPE | EAF_NOT_RETURNED | > + EAF_NOT_RETURNED_DIRECTLY | EAF_NOREAD; > flags = f; > /* Check that eaf_flags_t is wide enough to hold all flags. */ > gcc_checking_assert (f == flags); > @@ -1540,6 +1543,8 @@ modref_lattice::merge (int f) > Fnspec machinery does set both so compensate for this. */ > if (f & EAF_NOESCAPE) > f |= EAF_NODIRECTESCAPE; > + if (f & EAF_NOT_RETURNED) > + f |= EAF_NOT_RETURNED_DIRECTLY; > if ((flags & f) != flags) > { > flags &= f; > @@ -1647,7 +1652,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 | EAF_UNUSED)) > + int eaf_flags = gimple_call_arg_flags (call, arg); > + > + if (eaf_flags & (EAF_NOT_RETURNED | EAF_UNUSED)) > return; > > /* If return value is SSA name determine its flags. */ > @@ -1655,12 +1662,14 @@ merge_call_lhs_flags (gcall *call, int arg, int > index, bool deref, > { > tree lhs = gimple_call_lhs (call); > analyze_ssa_name_flags (lhs, lattice, depth + 1, ipa); > - if (deref) > + if (deref || (eaf_flags & EAF_NOT_RETURNED_DIRECTLY)) > lattice[index].merge_deref (lattice[SSA_NAME_VERSION (lhs)], false); > else > lattice[index].merge (lattice[SSA_NAME_VERSION (lhs)]); > } > /* In the case of memory store we can do nothing. */ > + else if (eaf_flags & EAF_NOT_RETURNED_DIRECTLY) > + lattice[index].merge (deref_flags (0, false)); > else > lattice[index].merge (0); > } > @@ -1731,11 +1740,13 @@ analyze_ssa_name_flags (tree name, > vec<modref_lattice> &lattice, int depth, > && DECL_BY_REFERENCE (DECL_RESULT (current_function_decl))) > ; > else if (gimple_return_retval (ret) == name) > - lattice[index].merge (~(EAF_UNUSED | EAF_NOT_RETURNED)); > + lattice[index].merge (~(EAF_UNUSED | EAF_NOT_RETURNED > + | EAF_NOT_RETURNED_DIRECTLY)); > else if (memory_access_to (gimple_return_retval (ret), name)) > { > lattice[index].merge_direct_load (); > - lattice[index].merge (~(EAF_UNUSED | EAF_NOT_RETURNED)); > + lattice[index].merge (~(EAF_UNUSED | EAF_NOT_RETURNED > + | EAF_NOT_RETURNED_DIRECTLY)); > } > } > /* Account for LHS store, arg loads and flags from callee function. */ > @@ -1794,7 +1805,8 @@ analyze_ssa_name_flags (tree name, vec<modref_lattice> > &lattice, int depth, > if (!(ecf_flags & (ECF_CONST | ECF_NOVOPS))) > { > int call_flags = gimple_call_arg_flags (call, i) > - | EAF_NOT_RETURNED; > + | EAF_NOT_RETURNED > + | EAF_NOT_RETURNED_DIRECTLY; > if (ignore_stores) > call_flags |= ignore_stores_eaf_flags; > > @@ -1817,7 +1829,8 @@ analyze_ssa_name_flags (tree name, vec<modref_lattice> > &lattice, int depth, > { > int call_flags = deref_flags > (gimple_call_arg_flags (call, i) > - | EAF_NOT_RETURNED, ignore_stores); > + | EAF_NOT_RETURNED > + | EAF_NOT_RETURNED_DIRECTLY, ignore_stores); > if (!record_ipa) > lattice[index].merge (call_flags); > else > @@ -3858,14 +3871,18 @@ modref_merge_call_site_flags (escape_summary *sum, > flags_lto |= ignore_stores_eaf_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; > + flags |= ee->min_flags | EAF_NOT_RETURNED | EAF_NOT_RETURNED_DIRECTLY; > + flags_lto |= ee->min_flags | EAF_NOT_RETURNED | > EAF_NOT_RETURNED_DIRECTLY; > /* Noescape implies that value also does not escape directly. > Fnspec machinery does set both so compensate for this. */ > if (flags & EAF_NOESCAPE) > flags |= EAF_NODIRECTESCAPE; > if (flags_lto & EAF_NOESCAPE) > flags_lto |= EAF_NODIRECTESCAPE; > + if (flags & EAF_NOT_RETURNED) > + flags |= EAF_NOT_RETURNED_DIRECTLY; > + if (flags_lto & EAF_NOT_RETURNED) > + flags_lto |= EAF_NOT_RETURNED_DIRECTLY; > if (!(flags & EAF_UNUSED) > && cur_summary && ee->parm_index < (int)cur_summary->arg_flags.length > ()) > { > 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..c90683bc962 > --- /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/testsuite/gcc.dg/tree-ssa/modref-10.c > b/gcc/testsuite/gcc.dg/tree-ssa/modref-10.c > new file mode 100644 > index 00000000000..c608408809d > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-10.c > @@ -0,0 +1,20 @@ > +/* { dg-do link } */ > +/* { dg-options "-O2 -fdump-tree-modref1" } */ > +void linker_error (); > +__attribute__((noinline)) > +int * > +test (int **a) > +{ > + return *a; > +} > +int > +main() > +{ > + int val; > + int *a=&val; > + int *b = test (&a); > + if (b == (int *)&a) > + linker_error (); > + return 0; > +} > +/* { dg-final { scan-tree-dump "parm 0 flags: noclobber noescape > nodirectescape not_returned_directly" "modref1"} } */ > diff --git a/gcc/tree-core.h b/gcc/tree-core.h > index d3d2a8d812f..8a55db2b3f5 100644 > --- a/gcc/tree-core.h > +++ b/gcc/tree-core.h > @@ -117,8 +117,12 @@ struct die_struct; > /* Nonzero if the argument does not escape to return value. */ > #define EAF_NOT_RETURNED (1 << 5) > > +/* Nonzero if the argument argument itself does not escape > + to return value but memory referenced by it may escape. */ > +#define EAF_NOT_RETURNED_DIRECTLY (1 << 6) > + > /* Nonzero if the argument is not read. */ > -#define EAF_NOREAD (1 << 6) > +#define EAF_NOREAD (1 << 7) > > /* Call return flags. */ > /* Mask for the argument number that is returned. Lower two bits of > diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c > index 99072df0768..5f24c0171f0 100644 > --- a/gcc/tree-ssa-structalias.c > +++ b/gcc/tree-ssa-structalias.c > @@ -4082,8 +4082,16 @@ handle_call_arg (gcall *stmt, tree arg, vec<ce_s> > *results, int flags, > { > struct constraint_expr cexpr; > cexpr.var = tem->id; > - cexpr.type = SCALAR; > - cexpr.offset = 0; > + if (flags & EAF_NOT_RETURNED_DIRECTLY) > + { > + cexpr.type = DEREF; > + cexpr.offset = UNKNOWN_OFFSET; > + } > + else > + { > + cexpr.type = SCALAR; > + cexpr.offset = 0; > + } > results->safe_push (cexpr); > } > > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Ivo Totev; HRB 36809 (AG Nuernberg)