On Fri, May 15, 2026 at 7:40 PM H.J. Lu <[email protected]> wrote: > > On Fri, May 15, 2026 at 6:02 PM Richard Sandiford > <[email protected]> wrote: > > > > Richard Sandiford <[email protected]> writes: > > > "H.J. Lu" <[email protected]> writes: > > >> I found a typo in the v2 patch. Here is the v3 patch. I also changed > > >> ix86_original_abi and ix86_alternate_abi implementation: > > >> > > >> /* Return the descriptor of the standard function ABI type. If > > >> ABI_TYPE == ABI_ALTERNATE, return the function alternate ABI type. */ > > >> > > >> static const predefined_function_abi & > > >> ix86_standard_abi (int abi_type) > > >> { > > >> static const char ix86_call_used_regs[] = CALL_USED_REGISTERS; > > >> auto &standard_abi = function_abis[abi_type]; > > >> if (!standard_abi.initialized_p ()) > > >> { > > >> HARD_REG_SET full_reg_clobbers = {}; > > >> > > >> /* Add all registers that are clobbered by the call. NB: If the > > >> current ABI is SYSV_ABI, the alternate ABI is MS_ABI. */ > > >> bool is_64bit_ms_abi = (TARGET_64BIT > > >> && ix86_abi == (abi_type == ABI_ALTERNATE > > >> ? SYSV_ABI : MS_ABI)); > > >> char c_mask = CALL_USED_REGISTERS_MASK (is_64bit_ms_abi); > > >> for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++) > > >> if (global_regs[i] > > >> || (!fixed_regs[i] > > >> && (ix86_call_used_regs[i] == 1 > > >> || (ix86_call_used_regs[i] & c_mask)))) > > >> SET_HARD_REG_BIT (full_reg_clobbers, i); > > >> > > >> SET_HARD_REG_BIT (full_reg_clobbers, FLAGS_REG); > > >> SET_HARD_REG_BIT (full_reg_clobbers, FPSR_REG); > > >> > > >> standard_abi.initialize (abi_type, full_reg_clobbers); > > >> } > > >> return standard_abi; > > >> } > > >> > > >> /* Return the descriptor of the function ABI type without attributes > > >> on the current function. */ > > >> > > >> static const predefined_function_abi & > > >> ix86_original_abi (void) > > >> { > > >> return ix86_standard_abi (ABI_ORIGINAL); > > >> } > > >> > > >> /* Return the descriptor of the function alternate ABI type. */ > > >> > > >> static const predefined_function_abi & > > >> ix86_alternate_abi (void) > > >> { > > >> return ix86_standard_abi (ABI_ALTERNATE); > > >> } > > > > > > Thanks. I made a start on what I wanted to try today, but realised > > > that I needed a target-independent patch first. I'll send that in a sec. > > > > Here's what I came up with. It's split into two parts: > > > > - 3 prepatches to lay some groundwork. If they're ok, I think they'd > > make sense independently of the main patch. > > > > - some suggested changes to the main patch. If versions of these > > patches are ok, they'd make more sense folded into your patch, > > rather than treated separately. > > > > So the full sequence is: > > > > - the first 3 of the attached patches (the ones with changelogs) > > - the CALL_INSN_ABI_ID patch that I posted yesterday > > - your LRA patch > > - your main patch (has a minor conflict with the first 3 patches) > > - the rest of the attached patches > > > > Yes, it's a bit of a stack :) > > > > I get three extra failures with this: > > > > FAIL: gcc.target/i386/no-callee-saved-19b.c check-function-bodies start > > FAIL: gcc.target/i386/no-callee-saved-19e.c check-function-bodies start
The new implementation changes RA slightly. Now we get call *%rax instead of call *%rbp I updated these 2 tests. > > FAIL: gcc.target/i386/stack-check-17.c scan-assembler-times pop[ql] 1 > > > > The first two fail for both 32-bit and 64-bit. The last one is > > specific to 64-bit. > > > > In no-callee-saved-19b.c and no-callee-saved-19e.c, the test is expecting > > a call from no_caller_saved_registers to no_callee_saved_registers to > > save the frame pointer. But both your patch and LLVM seem to agree > > that preserve_none does not change the frame pointer. For LLVM, see: > > https://godbolt.org/z/KrGePj3or where start does not save or restore > > rbp and clobber does preserve rbp. So maybe the test could be adjusted? > > > > stack-check-17.c passes in its original form, in that we go back > > to not having a pop for 64-bit. True. I reverted it. > > I'm obviously far from an x86 expert, so there are probably lots of > > details that I've got wrong or missed, but hopefully it's at least > > somewhat useful. > > > > I will take a closer look. > I put users/hjl/pr124798/master branch at https://gitlab.com/x86-gcc/gcc/-/commits/users/hjl/pr124798/master I applied all of your patches and merge some of them into commit 9d0043fdcbab21ed2cc3ac547fe4b37c6f02ac94 Author: H.J. Lu <[email protected]> Date: Tue Apr 14 18:37:20 2026 +0800 x86: Implement TARGET_FNTYPE_ABI with these changes: diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 00ae939d805..cda897f994d 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -562,13 +562,6 @@ ix86_conditional_register_usage (void) for (i = FIRST_REX2_INT_REG; i <= LAST_REX2_INT_REG; i++) CLEAR_HARD_REG_BIT (accessible_reg_set, i); } - - /* If a register is disabled, it can't be used for call. This avoids - reg_to_stack crashes when x87 registers are still accessed even - with -mno-mmx -mno-80387. */ - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (!TEST_HARD_REG_BIT (accessible_reg_set, i)) - call_used_regs[i] = 0; } /* Canonicalize a comparison from one we don't have to one we do have. */ @@ -21842,15 +21869,32 @@ ix86_initialize_abi (unsigned int abi_id, HARD_REG_SET full_reg_clobbers) } /* Return the descriptor of no_callee_saved_registers function type. - None of the enabled registers are preserved, except for the common - rules applied by ix86_initialize_abi. */ + None of the registers are preserved, except for frame register to + mitigate PR target/114116. + + NB: All registers, including disabled registers, aren't preserved + so that ABI_NO_CALLEE_SAVED can be used for all callers and callees, + including callers with additional registers enabled by target + attribute. Disabled registers won't be caller-saved since they + won't be accessed in the caller after + + commit 3050eeeee4183b9723a1465552b5798a1c21d223 + Author: H.J. Lu <[email protected]> + Date: Fri May 15 08:01:56 2026 +0800 + + caller_save_regs: Return the enabled registers + + */ static const predefined_function_abi & ix86_no_callee_saved_abi (void) { auto &no_callee_saved_abi = function_abis[ABI_NO_CALLEE_SAVED]; if (!no_callee_saved_abi.initialized_p ()) - ix86_initialize_abi (ABI_NO_CALLEE_SAVED, accessible_reg_set); + { + HARD_REG_SET full_reg_clobbers = reg_class_contents[ALL_REGS]; + ix86_initialize_abi (ABI_NO_CALLEE_SAVED, full_reg_clobbers); + } return no_callee_saved_abi; } @@ -21859,9 +21903,6 @@ ix86_no_callee_saved_abi (void) - the return registers, which are enumerated in ABI_ID. - - MMX and x87 registers, which aren't supported when saving and restoring - registers. - - the common rules applied by ix86_initialize_abi. */ static const predefined_function_abi & @@ -21871,9 +21912,6 @@ ix86_no_caller_saved_abi (unsigned int abi_id) if (!abi.initialized_p ()) { HARD_REG_SET full_reg_clobbers = {}; - for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (STACK_REGNO_P (i) || MMX_REGNO_P (i)) - SET_HARD_REG_BIT (full_reg_clobbers, i); switch (abi_id) { I also included: commit d9a2688a7bb744e6a2b4d29e62f85ab53cb1618c Author: H.J. Lu <[email protected]> Date: Wed May 13 08:27:50 2026 +0800 x86-64: Disallow mixed ABI attributes Thanks. -- H.J.
