Hi! As the following testcase shows e.g. on ia32, letting IPA opts change signature of functions which have [[{gnu,clang}::musttail]] calls can turn programs that would be compiled normally into something that is rejected because the caller has fewer argument stack slots than the function being tail called.
The following patch prevents signature changes for such functions. It is perhaps too big hammer in some cases, but it might be hard to try to figure out what signature changes are still acceptable and which are not at IPA time. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/15.2? 2025-07-11 Jakub Jelinek <ja...@redhat.com> Martin Jambor <mjam...@suse.cz> PR ipa/121023 * ipa-fnsummary.cc (compute_fn_summary): Disallow signature changes on cfun->has_musttail functions. * c-c++-common/musttail32.c: New test. --- gcc/ipa-fnsummary.cc.jj 2025-07-04 09:01:47.507516910 +0200 +++ gcc/ipa-fnsummary.cc 2025-07-10 14:00:19.488185173 +0200 @@ -3421,6 +3421,21 @@ compute_fn_summary (struct cgraph_node * info->inlinable = tree_inlinable_function_p (node->decl); bool no_signature = false; + + /* Don't allow signature changes for functions which have + [[gnu::musttail]] or [[clang::musttail]] calls. Sometimes + (more often on targets which pass everything on the stack) + signature changes can result in tail calls being impossible + even when without the signature changes they would be ok. + See PR121023. */ + if (cfun->has_musttail) + { + if (dump_file) + fprintf (dump_file, "No signature change:" + " function has calls with musttail attribute.\n"); + no_signature = true; + } + /* Type attributes can use parameter indices to describe them. Special case fn spec since we can safely preserve them in modref summaries. */ --- gcc/testsuite/c-c++-common/musttail32.c.jj 2025-07-10 14:00:56.760698477 +0200 +++ gcc/testsuite/c-c++-common/musttail32.c 2025-07-10 14:02:21.945586151 +0200 @@ -0,0 +1,23 @@ +/* PR ipa/121023 */ +/* { dg-do compile { target musttail } } */ +/* { dg-options "-O2" } */ + +struct S { int a, b; }; + +[[gnu::noipa]] int +foo (struct S x, int y, int z) +{ + return x.a + y + z; +} + +[[gnu::noinline]] static int +bar (struct S x, int y, int z) +{ + [[gnu::musttail]] return foo ((struct S) { x.a, 0 }, y, 1); +} + +int +baz (int x) +{ + return bar ((struct S) { 1, 2 }, x, 2) + bar ((struct S) { 2, 3 }, x + 1, 2); +} Jakub