https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119718

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to lucier from comment #3)
> Originally I understood musttail to be "It's crucial that this call be
> optimized, fail and tell me why if you can't do it", without changing
> whether a call is optimized.  (This is always assuming the presence of
> -foptimize-sibling-calls.)
> 
> It seems that having musttail change which tail calls are optimized is (a) a
> recent change (it didn't seem to happen a month ago) and (b) makes it hard
> to debug problems without looking at stack backtraces in gdb.
> 
> So the position I'm trying to take is that this is not a good thing.

It is a recent change.  The problem is that clang implemented the attribute a
few years ago with this kind of documented behavior and not following that
results in actually gcc not being able to compile various real-world projects
which do use the attribute already (firefox, protobuf, skia, ...), so we don't
really had the possibility to do something different.  The behavior is
documented and there are warnings which warn if people use musttail attribute
with addresses local vars passed to the tail call or another when the addresses
could have escaped (so when normal tail call can't be done but musttail call
can).

There are other cases where musttail can be tail-called and without it can't.

One are calls to noreturn functions (explicitly so declared or implicitly
determined), we intentionally don't tail call those because it makes debugging
harder (e.g. when calls to abort etc. are tail called), but with musttail just
honor what user requested.

Another are the various instrumentations, e.g. -fprofile-generate, -pg, etc.,
those normally add instrumentation after calls and thus will prevent tail
calls, with musttail that is skipped.

Yet another thing are IPA optimizations, if some function returns a singleton
range (always the same integral/pointer/floating point constant), optimizations
can replace the return value of calls with the returned constant.  This can
break calls and we have code to virtually undo that.  But, IPA optimizations
can also optimize the called clone to actually not return the return value at
all because nothing needs it.  Such optimization is generally desirable and we
don't know at that point if calls are in tail call positions or not and if they
could be tail call optimized or not.  So, currently we avoid the changing of
return types from non-void to void if there is at least one musttail call.

Another one (but this one is temporary, for GCC 15, will be changed for GCC 16)
is that sometimes EH cleanups happen too late and prevent tail calls, GCC 15
can analyze EH cleanup if it doesn't do anything at all (only debug stmts, or
var clobbers, followed by continuing throwing external exception) and still
tail call, but it has been decided to make it musttail specific as such code
has been introduced very late in the cycle.

And yet another one is an attempt to support copying of aggregate returns in
tail recursion (but again in GCC 15 as done late limited to musttail calls and
deferred for GCC 16 for other tail recursions).

Reply via email to