From: Jan Hubicka Date: Sun, 31 Oct 2021 22:14:29 +0000 (+0100) Subject: Improve handling of return slot in ipa-pure-const and modref. X-Git-Tag: basepoints/gcc-13~3499 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ca84f39399fda80c770306465276ffd66d3766ed;p=thirdparty%2Fgcc.git Improve handling of return slot in ipa-pure-const and modref. while preparing testcase for return slot tracking I noticed that both ipa-pure-const and modref treat return slot writes as non-local which prevents detecting functions as pure or not modifying global state. Fixed by making points_to_local_or_readonly_memory_p to special case return slot. This is bit of a side case, but presently at all uses of points_to_local_or_readonly_memory_p we want to handle return slot this way. I also noticed that we handle gimple copy unnecesarily pesimistically. This does not make difference right now since we do no not track non-scalars, but I fixed it anyway. Bootstrapped/regtested x86_64-linux, comitted. gcc/ChangeLog: * ipa-fnsummary.c: Include tree-dfa.h. (points_to_local_or_readonly_memory_p): Return true on return slot writes. * ipa-modref.c (analyze_ssa_name_flags): Fix handling of copy statement. gcc/testsuite/ChangeLog: * g++.dg/ipa/modref-1.C: New test. --- diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c index 311999194053..ac6eec30af88 100644 --- a/gcc/ipa-fnsummary.c +++ b/gcc/ipa-fnsummary.c @@ -86,6 +86,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-into-ssa.h" #include "symtab-clones.h" #include "gimple-range.h" +#include "tree-dfa.h" /* Summaries. */ fast_function_summary *ipa_fn_summaries; @@ -2569,7 +2570,20 @@ points_to_local_or_readonly_memory_p (tree t) if (integer_zerop (t)) return flag_delete_null_pointer_checks; if (TREE_CODE (t) == SSA_NAME) - return !ptr_deref_may_alias_global_p (t); + { + /* For IPA passes we can consinder accesses to return slot local + even if it is not local in the sense that memory is dead by + the end of founction. + The outer function will see a store in the call assignment + and thus this will do right thing for all uses of this + function in the current IPA passes (modref, pure/const discovery + and inlining heuristics). */ + if (DECL_RESULT (current_function_decl) + && DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)) + && t == ssa_default_def (cfun, DECL_RESULT (current_function_decl))) + return true; + return !ptr_deref_may_alias_global_p (t); + } if (TREE_CODE (t) == ADDR_EXPR) return refs_local_or_readonly_memory_p (TREE_OPERAND (t, 0)); return false; diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c index 3539cb43d11a..d866d9ed6b3b 100644 --- a/gcc/ipa-modref.c +++ b/gcc/ipa-modref.c @@ -1841,7 +1841,7 @@ analyze_ssa_name_flags (tree name, vec &lattice, int depth, We do not track memory locations, so assume that value is used arbitrarily. */ if (memory_access_to (gimple_assign_rhs1 (assign), name)) - lattice[index].merge (0); + lattice[index].merge (deref_flags (0, false)); /* Handle *name = *exp. */ else if (memory_access_to (gimple_assign_lhs (assign), name)) lattice[index].merge_direct_store (); diff --git a/gcc/testsuite/g++.dg/ipa/modref-1.C b/gcc/testsuite/g++.dg/ipa/modref-1.C new file mode 100644 index 000000000000..1de9e1d06a57 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/modref-1.C @@ -0,0 +1,35 @@ +/* { dg-do link } */ +/* { dg-options "-O2 -fdump-tree-local-pure-const1 -fdump-tree-modref1 -std=gnu++2a" } */ +namespace { +struct B { + int b; + struct B *bptr; + B() {b=1; } + B(B &src) + { + b=src.b; + bptr=0; + } + __attribute__ ((noinline)) + static struct B genB() + { + struct B b; + b.b=2; + b.bptr = 0; + return b; + } +}; +} +void linker_error (); +int main() +{ + struct B b1 = B::genB(); + b1.b = 1; + struct B b2 = B::genB(); + if (b1.b != 1 || b2.bptr == &b2) + linker_error (); + return 0; +} +/* { dg-final { scan-ipa-dump "Function found to be const: {anonymous}::B::genB" "local-pure-const1" } } */ +/* { dg-final { scan-ipa-dump "Retslot flags: direct noescape nodirectescape not_returned noread" "modref1" } } */ +