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;
}
}