On Tue, Jul 7, 2026 at 1:33 PM Hongtao Liu <[email protected]> wrote:
>
> On Tue, Jul 7, 2026 at 5:44 AM H.J. Lu <[email protected]> wrote:
> >
> > Implement TARGET_FNTYPE_ABI to avoid spills of callee-saved registers
> > when calling functions with no_caller_saved_registers attribute.
> >
> > After
> >
> > commit 754c6600fe058f1026098fde57860bbc38cc28fe
> > Author: Richard Sandiford <[email protected]>
> > Date: Wed Jun 3 13:11:17 2026 +0100
> >
> > Add CALL_INSN_ABI_ID
> >
> > there is no need for ix86_expand_call to add clobbers for when one ABI
> > calls another ABI.
> >
> > ABI_ALTERNATE is the alternate function ABI from the system ABI. If
> > ix86_abi is SYSV_ABI, ABI_ALTERNATE is the function ABI for MS_ABI.
> > Otherwise, ABI_ALTERNATE is the function ABI for SYSV_ABI.
> >
> > This target hook also properly marks the implicit __tls_get_addr call:
> >
> > (call_insn/u 9 8 10 (parallel [
> > (set (reg:DI 0 ax)
> > (call:DI (mem:QI (symbol_ref:DI ("__tls_get_addr")) [0 S1
> > A8])
> > (const_int 0 [0])))
> > (unspec:DI [
> > (reg/f:DI 7 sp)
> > ] UNSPEC_TLS_LD_BASE)
> > (clobber (reg:DI 5 di))
> > ]) "x.c":7:16 -1
> > (expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
> > (nil))
> > (nil) 0)
> >
> > with ABI_DEFAULT function ABI.
> >
> > Tested on Linux/x86-64 and with CPython 3.14.4.
> >
> > gcc/
> >
> > PR target/124798
> > PR target/125436
> > * config/i386/i386-expand.cc: Include "function-abi.h".
> > (x86_64_ms_sysv_extra_clobbered_registers): Removed.
> > (ix86_expand_call): Don't add explicit call and ABI-switch
> > clobbers.
> > * config/i386/i386-features.cc (ix86_place_single_tls_call):
> > Set CALL_INSN_ABI_ID on TLS calls.
> > * config/i386/i386-options.cc (ix86_set_current_function): Don't
> > call reinit_regs.
> > * config/i386/i386-protos.h
> > (ix86_type_no_callee_saved_registers_p): Removed.
> > (ix86_tls_get_addr_abi): New.
> > * config/i386/i386.cc (ix86_alternate_abi): New prototype.
> > (ix86_conditional_register_usage): Changed to describe the
> > system ABI.
> > (ix86_type_no_callee_saved_registers_p): Make it static.
> > (ix86_function_value_regno_p): Replace ix86_cfun_abi () with
> > ix86_abi.
> > (ix86_save_reg): Only check TYPE_NO_CALLEE_SAVED_REGISTERS as
> > a special case.
> > (ix86_tls_get_addr_abi): New.
> > (legitimize_tls_address): Set CALL_INSN_ABI_ID on TLS calls.
> > Call ix86_alternate_abi to initialize the alternate function ABI.
> > (ix86_initialize_abi): New function.
> > (ix86_no_callee_saved_abi): Likewise.
> > (ix86_no_caller_saved_abi): Likewise.
> > (ix86_standard_abi): Likewise.
> > (ix86_alternate_abi): Likewise.
> > (ix86_function_abi_id): Likewise.
> > (ix86_fntype_abi): Likewise.
> > (ix86_hard_regno_call_part_clobbered): Handle newly added ABIs.
> > (TARGET_FNTYPE_ABI): New.
> > * config/i386/i386.md: Add ABI_ALTERNATE, ABI_NO_CALLEE_SAVED,
> > ABI_NO_CALLER_SAVED_RETURN_VOID, ABI_NO_CALLER_SAVED_RETURN_AX,
> > ABI_NO_CALLER_SAVED_RETURN_AX_DX,
> > ABI_NO_CALLER_SAVED_RETURN_AX_XMM0,
> > ABI_NO_CALLER_SAVED_RETURN_XMM0 and
> > ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1.
> >
> > gcc/testsuite/
> >
> > PR target/124798
> > PR target/125436
> > * gcc.target/i386/abi-mix-1.c: New test.
> > * gcc.target/i386/abi-mix-2.c: Likewise.
> > * gcc.target/i386/no-callee-saved-20.c: Likewise.
> > * gcc.target/i386/no-caller-saved-1-ms.c: Likewise.
> > * gcc.target/i386/no-caller-saved-1-sysv.c: Likewise.
> > * gcc.target/i386/no-caller-saved-1.c: Likewise.
> > * gcc.target/i386/no-caller-saved-2.c: Likewise.
> > * gcc.target/i386/no-caller-saved-3.c: Likewise.
> > * gcc.target/i386/no-caller-saved-4.c: Likewise.
> > * gcc.target/i386/no-caller-saved-5.c: Likewise.
> > * gcc.target/i386/no-caller-saved-6.c: Likewise.
> > * gcc.target/i386/no-caller-saved-7.c: Likewise.
> > * gcc.target/i386/no-caller-saved-8.c: Likewise.
> > * gcc.target/i386/no-caller-saved-9.c: Likewise.
> > * gcc.target/i386/no-caller-saved-10.c: Likewise.
> > * gcc.target/i386/no-caller-saved-11.c: Likewise.
> > * gcc.target/i386/pr125436-1a.c: Likewise.
> > * gcc.target/i386/pr125436-1b.c: Likewise.
> > * gcc.target/i386/pr125436-2a.c: Likewise.
> > * gcc.target/i386/pr125436-2b.c: Likewise.
> > * gcc.target/i386/pr125436-3.c: Likewise.
> > * gcc.target/i386/pr125436-4.c: Likewise.
> > * gcc.target/i386/pr119784b.c: Adjusted for unused RBP.
> > * gcc.target/i386/no-callee-saved-18.c: Don't check frame
> > register.
> > * gcc.target/i386/no-callee-saved-19b.c: Update the expected
> > instruction order.
> > * gcc.target/i386/no-callee-saved-19d.c: Likewise.
> > * gcc.target/i386/no-callee-saved-19e.c: Likewise.
> > * gcc.target/i386/no-callee-saved-2.c: Check frame register isn't
> > saved nor restored in 64-bit mode.
> > * gcc.target/i386/no-callee-saved-8.c: Expect no saving nor
> > restoring caller-saved registers.
> > * gcc.target/i386/no-callee-saved-9.c: Likewise.
> > * gcc.target/i386/preserve-none-14.c: Don't check frame register.
> > * gcc.target/i386/preserve-none-23.c: Likewise.
> > * gcc.target/i386/preserve-none-7.c: Check frame register isn't
> > saved nor restored in 64-bit mode.
> >
> > Signed-off-by: H.J. Lu <[email protected]>
> > Co-Authored by: Richard Sandiford <[email protected]>
> >
> > Signed-off-by: H.J. Lu <[email protected]>
>
> On Tue, Jul 7, 2026 at 5:44 AM H.J. Lu <[email protected]> wrote:
> >
> > Implement TARGET_FNTYPE_ABI to avoid spills of callee-saved registers
> > when calling functions with no_caller_saved_registers attribute.
> >
> > After
> >
> > commit 754c6600fe058f1026098fde57860bbc38cc28fe
> > Author: Richard Sandiford <[email protected]>
> > Date: Wed Jun 3 13:11:17 2026 +0100
> >
> > Add CALL_INSN_ABI_ID
> >
> > there is no need for ix86_expand_call to add clobbers for when one ABI
> > calls another ABI.
> >
> > ABI_ALTERNATE is the alternate function ABI from the system ABI. If
> > ix86_abi is SYSV_ABI, ABI_ALTERNATE is the function ABI for MS_ABI.
> > Otherwise, ABI_ALTERNATE is the function ABI for SYSV_ABI.
> >
> > This target hook also properly marks the implicit __tls_get_addr call:
> >
> > (call_insn/u 9 8 10 (parallel [
> > (set (reg:DI 0 ax)
> > (call:DI (mem:QI (symbol_ref:DI ("__tls_get_addr")) [0 S1
> > A8])
> > (const_int 0 [0])))
> > (unspec:DI [
> > (reg/f:DI 7 sp)
> > ] UNSPEC_TLS_LD_BASE)
> > (clobber (reg:DI 5 di))
> > ]) "x.c":7:16 -1
> > (expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
> > (nil))
> > (nil) 0)
> >
> > with ABI_DEFAULT function ABI.
> >
> > Tested on Linux/x86-64 and with CPython 3.14.4.
> >
> > gcc/
> >
> > PR target/124798
> > PR target/125436
> > * config/i386/i386-expand.cc: Include "function-abi.h".
> > (x86_64_ms_sysv_extra_clobbered_registers): Removed.
> > (ix86_expand_call): Don't add explicit call and ABI-switch
> > clobbers.
> > * config/i386/i386-features.cc (ix86_place_single_tls_call):
> > Set CALL_INSN_ABI_ID on TLS calls.
> > * config/i386/i386-options.cc (ix86_set_current_function): Don't
> > call reinit_regs.
> > * config/i386/i386-protos.h
> > (ix86_type_no_callee_saved_registers_p): Removed.
> > (ix86_tls_get_addr_abi): New.
> > * config/i386/i386.cc (ix86_alternate_abi): New prototype.
> > (ix86_conditional_register_usage): Changed to describe the
> > system ABI.
> > (ix86_type_no_callee_saved_registers_p): Make it static.
> > (ix86_function_value_regno_p): Replace ix86_cfun_abi () with
> > ix86_abi.
> > (ix86_save_reg): Only check TYPE_NO_CALLEE_SAVED_REGISTERS as
> > a special case.
> > (ix86_tls_get_addr_abi): New.
> > (legitimize_tls_address): Set CALL_INSN_ABI_ID on TLS calls.
> > Call ix86_alternate_abi to initialize the alternate function ABI.
> > (ix86_initialize_abi): New function.
> > (ix86_no_callee_saved_abi): Likewise.
> > (ix86_no_caller_saved_abi): Likewise.
> > (ix86_standard_abi): Likewise.
> > (ix86_alternate_abi): Likewise.
> > (ix86_function_abi_id): Likewise.
> > (ix86_fntype_abi): Likewise.
> > (ix86_hard_regno_call_part_clobbered): Handle newly added ABIs.
> > (TARGET_FNTYPE_ABI): New.
> > * config/i386/i386.md: Add ABI_ALTERNATE, ABI_NO_CALLEE_SAVED,
> > ABI_NO_CALLER_SAVED_RETURN_VOID, ABI_NO_CALLER_SAVED_RETURN_AX,
> > ABI_NO_CALLER_SAVED_RETURN_AX_DX,
> > ABI_NO_CALLER_SAVED_RETURN_AX_XMM0,
> > ABI_NO_CALLER_SAVED_RETURN_XMM0 and
> > ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1.
> >
> > gcc/testsuite/
> >
> > PR target/124798
> > PR target/125436
> > * gcc.target/i386/abi-mix-1.c: New test.
> > * gcc.target/i386/abi-mix-2.c: Likewise.
> > * gcc.target/i386/no-callee-saved-20.c: Likewise.
> > * gcc.target/i386/no-caller-saved-1-ms.c: Likewise.
> > * gcc.target/i386/no-caller-saved-1-sysv.c: Likewise.
> > * gcc.target/i386/no-caller-saved-1.c: Likewise.
> > * gcc.target/i386/no-caller-saved-2.c: Likewise.
> > * gcc.target/i386/no-caller-saved-3.c: Likewise.
> > * gcc.target/i386/no-caller-saved-4.c: Likewise.
> > * gcc.target/i386/no-caller-saved-5.c: Likewise.
> > * gcc.target/i386/no-caller-saved-6.c: Likewise.
> > * gcc.target/i386/no-caller-saved-7.c: Likewise.
> > * gcc.target/i386/no-caller-saved-8.c: Likewise.
> > * gcc.target/i386/no-caller-saved-9.c: Likewise.
> > * gcc.target/i386/no-caller-saved-10.c: Likewise.
> > * gcc.target/i386/no-caller-saved-11.c: Likewise.
> > * gcc.target/i386/pr125436-1a.c: Likewise.
> > * gcc.target/i386/pr125436-1b.c: Likewise.
> > * gcc.target/i386/pr125436-2a.c: Likewise.
> > * gcc.target/i386/pr125436-2b.c: Likewise.
> > * gcc.target/i386/pr125436-3.c: Likewise.
> > * gcc.target/i386/pr125436-4.c: Likewise.
> > * gcc.target/i386/pr119784b.c: Adjusted for unused RBP.
> > * gcc.target/i386/no-callee-saved-18.c: Don't check frame
> > register.
> > * gcc.target/i386/no-callee-saved-19b.c: Update the expected
> > instruction order.
> > * gcc.target/i386/no-callee-saved-19d.c: Likewise.
> > * gcc.target/i386/no-callee-saved-19e.c: Likewise.
> > * gcc.target/i386/no-callee-saved-2.c: Check frame register isn't
> > saved nor restored in 64-bit mode.
> > * gcc.target/i386/no-callee-saved-8.c: Expect no saving nor
> > restoring caller-saved registers.
> > * gcc.target/i386/no-callee-saved-9.c: Likewise.
> > * gcc.target/i386/preserve-none-14.c: Don't check frame register.
> > * gcc.target/i386/preserve-none-23.c: Likewise.
> > * gcc.target/i386/preserve-none-7.c: Check frame register isn't
> > saved nor restored in 64-bit mode.
> >
> > Signed-off-by: H.J. Lu <[email protected]>
> > Co-Authored by: Richard Sandiford <[email protected]>
> >
> > Signed-off-by: H.J. Lu <[email protected]>
>
> gcc/config/i386/i386-features.cc:4353, should we also use
> ix86_tls_get_addr_abi().clobbers_full_reg_p(i) instead of
> default_function_abi.clobbers_full_reg_p (i)?
>
> 4349 /* Get all live caller-saved registers for TLS_GD and TLS_LD_BASE
> 4350 instructions. */
> 4351 if (kind != X86_CSE_TLSDESC)
> 4352 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
> 4353 if (default_function_abi.clobbers_full_reg_p (i)
> 4354 && !fixed_regs[i]
> 4355 && bitmap_bit_p (in, i))
> 4356 bitmap_set_bit (live_caller_saved_regs, i);
>
>
> Other LGTM.
Good catch. I changed it to
/* Get all live caller-saved registers for TLS_GD and TLS_LD_BASE
instructions. */
if (kind != X86_CSE_TLSDESC)
{
const predefined_function_abi &tls_abi
= ix86_tls_get_addr_abi ();
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (tls_abi.clobbers_full_reg_p (i)
&& !fixed_regs[i]
&& bitmap_bit_p (in, i))
bitmap_set_bit (live_caller_saved_regs, i);
}
in v4.
Thanks.
--
H.J.