When -fprofile-generate is used musttail often fails because the
compiler adds instrumentation after the tail calls.

This patch prevents adding exit extra edges after musttail because for a
tail call the execution leaves the function and can never come back
even on a unwind or exception.

This is only done for musttail. In principle it could be done
for any tail calls, but the problem is that there might be other reasons
why the tail fails later, and then the edge might be still needed.

[v3 version uses an edge flag to pass the musttail information to profile.cc]

gcc/ChangeLog:

        PR gcov-profile/118442
        * cfg-flags.def (MUSTTAIL):
        * profile.cc (branch_prob):
        * tree-cfg.cc (gimple_flow_call_edges_add):

gcc/testsuite/ChangeLog:

        * c-c++-common/pr118442.c: New test.
---
 gcc/cfg-flags.def                     |  3 +++
 gcc/profile.cc                        |  6 ++++++
 gcc/testsuite/c-c++-common/pr118442.c | 15 +++++++++++++++
 gcc/tree-cfg.cc                       |  3 +++
 4 files changed, 27 insertions(+)
 create mode 100644 gcc/testsuite/c-c++-common/pr118442.c

diff --git a/gcc/cfg-flags.def b/gcc/cfg-flags.def
index 84f5324a295d..b01e4ccc9ef4 100644
--- a/gcc/cfg-flags.def
+++ b/gcc/cfg-flags.def
@@ -182,6 +182,9 @@ DEF_EDGE_FLAG(TM_ABORT, 16)
    of any pass.  */
 DEF_EDGE_FLAG(IGNORE, 17)
 
+/* An edge from a musttail call to the exit.  */
+DEF_EDGE_FLAG(MUSTTAIL, 18)
+
 #endif
 
 /*
diff --git a/gcc/profile.cc b/gcc/profile.cc
index acc0ae0cc201..54280621e685 100644
--- a/gcc/profile.cc
+++ b/gcc/profile.cc
@@ -1340,6 +1340,12 @@ branch_prob (bool thunk)
          EDGE_INFO (e)->ignore = 1;
          ignored_edges++;
        }
+      if (e->flags & EDGE_MUSTTAIL)
+       {
+         EDGE_INFO (e)->ignore = 1;
+         ignored_edges++;
+       }
+
     }
 
   /* Create spanning tree from basic block graph, mark each edge that is
diff --git a/gcc/testsuite/c-c++-common/pr118442.c 
b/gcc/testsuite/c-c++-common/pr118442.c
new file mode 100644
index 000000000000..0108185d7b0a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr118442.c
@@ -0,0 +1,15 @@
+/* PR118442 */
+/* { dg-do compile { target { struct_musttail && external_musttail && { c || 
c++11 } } } } */
+/* { dg-options "-fprofile-generate -O2" } */
+
+struct Span {
+    int test[5];
+};
+
+extern void resolveToBufferSlow(struct Span *buffer);
+
+void resolveToBuffer(struct Span *buffer)
+{
+    buffer->test[0] = 4;
+    [[clang::musttail]] return resolveToBufferSlow(buffer);
+}
diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
index 2fa5678051ad..979d8acce2e7 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -9002,6 +9002,9 @@ gimple_flow_call_edges_add (sbitmap blocks)
                    }
                  e = make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FAKE);
                  e->probability = profile_probability::guessed_never ();
+                 if (is_gimple_call (stmt)
+                     && gimple_call_must_tail_p (as_a <const gcall *> (stmt)))
+                   e->flags |= EDGE_MUSTTAIL;
                }
              gsi_prev (&gsi);
            }
-- 
2.48.1

Reply via email to