On Mon, Mar 24, 2025 at 09:50:26AM -0700, Andi Kleen wrote:
> gcc/ChangeLog:
> 
>       PR gcov-profile/118442
>       * cfg-flags.def (MUSTTAIL):
>       * profile.cc (branch_prob):
>       * tree-cfg.cc (gimple_flow_call_edges_add):

Descriptions missing.

> --- 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
>  
>  /*

Why?  The flag looks like overkill to me.

> --- /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" } */

I don't see how this could have worked, it is invalid syntax in dejagnu.
&& or || can only have 2 arguments and one needs to use {}s around if one
needs more.

Furthermore, dg-require-profile was missing.

So what about the following patch instead (so far just lightly tested on
the testcase and nothing else)?

2025-03-25  Jakub Jelinek  <ja...@redhat.com>
            Andi Kleen  <a...@gcc.gnu.org>

        PR gcov-profile/118442
        * profile.cc (branch_prob): Ignore EDGE_FAKE edges from musttail calls
        to EXIT.

        * c-c++-common/pr118442.c: New test.

--- gcc/profile.cc.jj   2025-01-02 11:23:16.458517673 +0100
+++ gcc/profile.cc      2025-03-25 09:57:21.860398601 +0100
@@ -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
--- gcc/testsuite/c-c++-common/pr118442.c.jj    2025-03-25 09:45:31.754100696 
+0100
+++ gcc/testsuite/c-c++-common/pr118442.c       2025-03-25 09:47:20.960608623 
+0100
@@ -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);
+}


        Jakub

Reply via email to