]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Improve handling of return slot in ipa-pure-const and modref.
authorJan Hubicka <hubicka@ucw.cz>
Sun, 31 Oct 2021 22:14:29 +0000 (23:14 +0100)
committerJan Hubicka <hubicka@ucw.cz>
Sun, 31 Oct 2021 22:14:29 +0000 (23:14 +0100)
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.

gcc/ipa-fnsummary.c
gcc/ipa-modref.c
gcc/testsuite/g++.dg/ipa/modref-1.C [new file with mode: 0644]

index 3119991940537baca5d0986aab094ff27c7bb683..ac6eec30af88998f1c67ee727a2a6cf0d4d8ed27 100644 (file)
@@ -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;
index 3539cb43d11a21798b72bc265326876fc4d444b3..d866d9ed6b3b768f0506619d40b5923fba951d8a 100644 (file)
@@ -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 (file)
index 0000000..1de9e1d
--- /dev/null
@@ -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" } } */
+