diff options
-rw-r--r-- | gcc/ipa-fnsummary.cc | 15 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/musttail32.c | 23 |
2 files changed, 38 insertions, 0 deletions
diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc index 48343a7..924a54b 100644 --- a/gcc/ipa-fnsummary.cc +++ b/gcc/ipa-fnsummary.cc @@ -3421,6 +3421,21 @@ compute_fn_summary (struct cgraph_node *node, bool early) 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. */ diff --git a/gcc/testsuite/c-c++-common/musttail32.c b/gcc/testsuite/c-c++-common/musttail32.c new file mode 100644 index 0000000..f1b7052 --- /dev/null +++ b/gcc/testsuite/c-c++-common/musttail32.c @@ -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); +} |