On Thu, Mar 20, 2025 at 05:28:48PM +0100, Jakub Jelinek wrote: > On Thu, Mar 20, 2025 at 09:19:02AM -0700, Andi Kleen wrote: > > The inlining was just one of the issue, there are some related to > > different semantics of escaped locals. gcc always errors out while > > LLVM declares it undefined. > > > > But maybe we can fix that one too. > > I have 3 patches to be tested, the inline one, fnsplit one and ipa-icf one. > For the escaped locals, I guess we need to decide if [[clang::musttail]] > will be something different from [[gnu::musttail]] in GCC or not (and if > yes, what __attribute__((musttail)) will be).
There were more differences. clang is better to handle various cases with structs at -O0 and then there are some target specific differences too (e.g. some of our targets always reject externs) But maybe it's good enough. I don't think multiple flavors of musttail are a good idea because it will be confusing to users. I guess we should just match what clang does even for gnu::musttail. Since they were the pioneer they get to chose the semantics. > The current difference in behavior is on > int foo (void); > void bar (int *); > int > baz (void) > { > int a; > bar (&a); > [[clang::musttail]] return foo (); > } > Clang makes the attribute not just a request to tail call it or fail, > but also changes behavior and says if the code ever accesses a from the > above during foo () (which without the attribute is completely valid), then > it is UB. So it could be as simple as that patch? It solves your test case at least for x86. diff --git a/gcc/tree-tailcall.cc b/gcc/tree-tailcall.cc index f97df31eb3cf..b87a92e95e3d 100644 --- a/gcc/tree-tailcall.cc +++ b/gcc/tree-tailcall.cc @@ -722,8 +722,9 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail, { if (local_live_vars) BITMAP_FREE (local_live_vars); - maybe_error_musttail (call, - _("call invocation refers to locals")); + /* Allow this for musttail to match clang semantics of musttail. */ + if (gimple_call_must_tail_p (call)) + continue; return; } else @@ -732,8 +733,9 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail, if (bitmap_bit_p (local_live_vars, *v)) { BITMAP_FREE (local_live_vars); - maybe_error_musttail (call, - _("call invocation refers to locals")); + /* Allow this for musttail to match clang semantics of musttail. */ + if (gimple_call_must_tail_p (call)) + continue; return; } }