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.
