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

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
The RISCV ABIs apparently pass some of the vector arguments by invisible
reference (dunno if it is only if there are no vector registers reserved for
argument passing left or if it depends solely on the exact vector types,
question to the RISCV maintainers).

Anyway, that is a thing that generally prevents tail calls, you can't tail call
if you need to create a temporary in the caller on the stack and pass to the
tail called function address of that temporary, because tail call will make the
caller frame disappear.

I guess the only exception that could be handled is if the passed value is
unmodified value from one of the parameters of the function (same type, no
conversions, no possibility of modification) and most importantly that it is
passed by invisible reference in the caller as well.  In that case the compiler
could look up in what register/memory the address of the argument has been
passed and propagate it to the tail call.  In the GCC IL, that means only
handle it for cases like in the #c2 testcase
where the optimized dump has something like
  _2 (list, src_4(D), dst_5(D), r_6(D), g_7(D), b_8(D)); [tail call] [must tail
call]
i.e. the values of the arguments are unmodified values of the parameters, and
it can prove they are passed by invisible reference in the caller too (in this
case in a3/a4/a5 registers it passes the addresses of r, g and b arguments).

This is somewhat similar to the optimization I did for s390x in PR119873, there
the ABI also prevents tailcalls if a certain register must be used for argument
passing, but as a special optimization it can be done if only the original
parameter value from the same argument is passed through.

Reply via email to