aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2021-10-31 23:14:29 +0100
committerJan Hubicka <hubicka@ucw.cz>2021-10-31 23:14:29 +0100
commitca84f39399fda80c770306465276ffd66d3766ed (patch)
tree6bb38a6cd317c43716c251388b7aa9b10c5302b8 /gcc
parentd41092ec52f46d2f4b08fff8d1519e50354331b0 (diff)
downloadgcc-ca84f39399fda80c770306465276ffd66d3766ed.zip
gcc-ca84f39399fda80c770306465276ffd66d3766ed.tar.gz
gcc-ca84f39399fda80c770306465276ffd66d3766ed.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ipa-fnsummary.c16
-rw-r--r--gcc/ipa-modref.c2
-rw-r--r--gcc/testsuite/g++.dg/ipa/modref-1.C35
3 files changed, 51 insertions, 2 deletions
diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c
index 3119991..ac6eec3 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_summary *, va_gc> *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 3539cb4..d866d9e 100644
--- a/gcc/ipa-modref.c
+++ b/gcc/ipa-modref.c
@@ -1841,7 +1841,7 @@ analyze_ssa_name_flags (tree name, vec<modref_lattice> &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 0000000..1de9e1d
--- /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" } } */
+