On Fri, 21 Mar 2025, Jakub Jelinek wrote: > Hi! > > As discussed in the PR, some packages fail to build because they use > musttail attribute on calls in functions which we inline, and if they > are inlined into a middle of the function, that results in an error > because we have a musttail call in the middle of a function and so it > can't be tail called there. > > Now, guess the primary intent of the musttail attribute is ensuring > we don't get an extra stack frame in the backtrace. Inlining itself > removes one extra stack frame from the backtrace as well (sure, not > counting virtual backtraces in gdb), so I think erroring out on that > is unnecessary. > > Except when we are inlining a musttail call which has musttail calls > in it, in that case we are being asked to remove 2 stack frames from > the backtrace, inlining removes one, so we need to keep musttail > on the calls so that another stack frame is removed through a tail call. > > The following patch implements that, keeping previous behavior when > id->call_stmt is NULL (i.e. when versioning/cloning etc.). > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK. Thanks, Richard. > 2025-03-20 Jakub Jelinek <ja...@redhat.com> > > PR ipa/119376 > * tree-inline.cc (remap_gimple_stmt): Silently clear > gimple_call_must_tail_p on inlined call stmts if id->call_stmt > is a call without that flag set. > > * c-c++-common/musttail26.c: New test. > > --- gcc/tree-inline.cc.jj 2025-01-20 17:58:39.244480277 +0100 > +++ gcc/tree-inline.cc 2025-03-20 12:08:42.957453514 +0100 > @@ -1892,6 +1892,15 @@ remap_gimple_stmt (gimple *stmt, copy_bo > gimple_call_set_tail (call_stmt, false); > if (gimple_call_from_thunk_p (call_stmt)) > gimple_call_set_from_thunk (call_stmt, false); > + /* Silently clear musttail flag when inlining a function > + with must tail call from a non-musttail call. The inlining > + removes one frame so acts like musttail's intent, and we > + can be inlining a function with musttail calls in the middle > + of caller where musttail will always error. */ > + if (gimple_call_must_tail_p (call_stmt) > + && id->call_stmt > + && !gimple_call_must_tail_p (id->call_stmt)) > + gimple_call_set_must_tail (call_stmt, false); > if (gimple_call_internal_p (call_stmt)) > switch (gimple_call_internal_fn (call_stmt)) > { > --- gcc/testsuite/c-c++-common/musttail26.c.jj 2025-03-20 > 12:47:53.443730606 +0100 > +++ gcc/testsuite/c-c++-common/musttail26.c 2025-03-20 12:53:26.110082182 > +0100 > @@ -0,0 +1,33 @@ > +/* PR ipa/119376 */ > +/* { dg-do compile { target musttail } } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > +/* { dg-final { scan-tree-dump-times " \[^\n\r]* = foo \\\(3, > \[^\n\r]*\\\); \\\[tail call\\\] \\\[must tail call\\\]" 1 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times " \[^\n\r]* = foo \\\(4, > \[^\n\r]*\\\); \\\[tail call\\\] \\\[must tail call\\\]" 1 "optimized" } } */ > +/* { dg-final { scan-tree-dump-not " foo \\\(\[12], \[^\n\r]*\\\); \\\[tail > call\\\]" "optimized" } } */ > + > +int foo (int, int); > +int v, w[10]; > + > +static inline __attribute__((always_inline)) int > +bar (int x, int y) > +{ > + [[gnu::musttail]] return foo (x, y); > +} > + > +static int > +baz (int x, int y) > +{ > + [[gnu::musttail]] return foo (x, x + y + (v | y) * (v & y)); > +} > + > +int > +qux (int x, int y) > +{ > + w[0] = bar (1, x + y); > + w[1] = baz (2, x + y); > + if (x == 42) > + [[gnu::musttail]] return bar (3, x + y); > + if (x == -42) > + [[gnu::musttail]] return baz (4, x + y); > + return 0; > +} > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)