arm: prevent impossible tail- long-calls with static chain [PR119430]

When a function call uses up all argument registers, and needs IP for
the static chain, there aren't any call-clobbered registers left for
reload to assign as the sibcall target, when -mlong-calls is enabled.
Use the same logic that does the job for indirect calls to prevent
tail calls in this case.

With this change, it is possible to bootstrap armv7a-linux-gnu with
both -O3 and lto, but only with both -mlong-calls and
-ffunction-sections.

Without -mlong-calls, linker veneer thunks may clobber the static
chain register set up by callers in one lto unit, preventing them from
reaching the callee in a separate lto unit.  -ffunction-sections is
required for -mlong-calls to be effective, because both caller and
callee are in the same section, and that disables long-calls when
!flag_reorder_blocks_and_partition.

gcc/ChangeLog

	PR target/119430
	* config/arm/arm.cc (arm_function_ok_for_sibcall): Disable
	sibcalls for long-calls that use all call-clobbered
	general-purpose registers, including the static chain.
This commit is contained in:
Alexandre Oliva
2025-07-10 22:21:31 -03:00
committed by Richard Earnshaw
parent a40666202d
commit f5166f5bad

View File

@@ -7983,10 +7983,14 @@ arm_function_ok_for_sibcall (tree decl, tree exp)
address. But we only have r0-r3 and ip in that class. If r0-r3 all hold
function arguments, then we can only use IP. But IP may be needed in the
epilogue (for PAC validation), or for passing the static chain. We have
to disable the tail call if nothing is available. */
if (!decl
&& ((CALL_EXPR_BY_DESCRIPTOR (exp) && !flag_trampolines)
|| arm_current_function_pac_enabled_p()))
to disable the tail call if nothing is available. Long-calls are
effectively handled as indirect calls, so handle that as well. */
if ((!decl
&& ((CALL_EXPR_BY_DESCRIPTOR (exp) && !flag_trampolines)
|| arm_current_function_pac_enabled_p ()))
|| (decl && arm_is_long_call_p (decl)
&& (CALL_EXPR_STATIC_CHAIN (exp)
|| arm_current_function_pac_enabled_p ())))
{
tree fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (exp)));
CUMULATIVE_ARGS cum;