diff options
author | Jakub Jelinek <jakub@redhat.com> | 2025-03-21 12:17:01 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2025-03-21 12:17:01 +0100 |
commit | 37ae2e055687a22974d7bcb9e618f258fa49ab1a (patch) | |
tree | fb7da6a776f583036214286f8c3335a4be1cfdcc /gcc/tree-inline.cc | |
parent | 778c28c70f8573f8256c810ff0d9e143ff75dec3 (diff) | |
download | gcc-37ae2e055687a22974d7bcb9e618f258fa49ab1a.zip gcc-37ae2e055687a22974d7bcb9e618f258fa49ab1a.tar.gz gcc-37ae2e055687a22974d7bcb9e618f258fa49ab1a.tar.bz2 |
inliner: Silently drop musttail flag on calls during inlining unless the inlined routine was musttail called [PR119376]
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.).
2025-03-21 Jakub Jelinek <jakub@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.
Diffstat (limited to 'gcc/tree-inline.cc')
-rw-r--r-- | gcc/tree-inline.cc | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc index 5b35390..05843b8 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -1892,6 +1892,15 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id) 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)) { |