aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/profile.cc14
-rw-r--r--gcc/testsuite/c-c++-common/pr118442.c17
2 files changed, 31 insertions, 0 deletions
diff --git a/gcc/profile.cc b/gcc/profile.cc
index acc0ae0..76fed35 100644
--- a/gcc/profile.cc
+++ b/gcc/profile.cc
@@ -1340,6 +1340,20 @@ branch_prob (bool thunk)
EDGE_INFO (e)->ignore = 1;
ignored_edges++;
}
+ /* Ignore fake edges after musttail calls. */
+ if ((e->flags & EDGE_FAKE)
+ && e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
+ {
+ gimple_stmt_iterator gsi = gsi_last_bb (e->src);
+ gimple *stmt = gsi_stmt (gsi);
+ if (stmt
+ && is_gimple_call (stmt)
+ && gimple_call_must_tail_p (as_a <const gcall *> (stmt)))
+ {
+ 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 0000000..2472aa6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr118442.c
@@ -0,0 +1,17 @@
+/* PR118442 */
+/* { dg-do compile { target { struct_musttail && { external_musttail && { c || c++11 } } } } } */
+/* { dg-options "-fprofile-generate -O2" } */
+/* { dg-require-profiling "-fprofile-generate" } */
+
+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);
+}