From: Alexandre Oliva Date: Fri, 11 Jul 2025 01:21:31 +0000 (-0300) Subject: arm: prevent impossible tail- long-calls with static chain [PR119430] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f5166f5badb190eec5d3707fe25ad33febf1969e;p=thirdparty%2Fgcc.git 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. --- diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index ec21fb96b66..0a1f6612d07 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -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;