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.

Reply via email to