> -----Original Message-----
> From: H.J. Lu <[email protected]>
> Sent: Tuesday, July 21, 2026 10:02 AM
> To: Hongtao Liu <[email protected]>
> Cc: GCC Patches <[email protected]>; Uros Bizjak
> <[email protected]>; Liu, Hongtao <[email protected]>
> Subject: [PATCH v5] x86: Don't set cum->preserve_none_abi for x86-64 MS
> calls
> 
> On Mon, Jul 20, 2026 at 5:30 PM Hongtao Liu <[email protected]> wrote:
> >
> > On Mon, Jul 20, 2026 at 4:03 PM H.J. Lu <[email protected]> wrote:
> > >
> > > On Mon, Jul 20, 2026 at 3:41 PM Hongtao Liu <[email protected]>
> wrote:
> > > >
> > > > On Fri, Jul 10, 2026 at 2:51 PM H.J. Lu <[email protected]> wrote:
> > > > >
> > > > > On Thu, Jul 9, 2026 at 2:42 PM Hongtao Liu <[email protected]>
> wrote:
> > > > > >
> > > > > > On Thu, Jul 9, 2026 at 9:41 AM H.J. Lu <[email protected]> wrote:
> > > > > > >
> > > > > > > In 64-bit mode, preserve_none attribute uses a different
> > > > > > > calling convention.  Ignore MS ABI with preserve_none
> > > > > > > attribute to always use the preserve_none calling convention
> > > > > > > with preserve_none attribute.
> > > > > > >
> > > > > > > gcc/
> > > > > > >
> > > > > >
> > > > > > >
> > > > > > > It has 8 registers.   Tests show that
> > > > > > > x86_64_preserve_none_int_parameter_registers
> > > > > > > is used for functions with __attribute__ ((preserve_none, 
> > > > > > > ms_abi)).
> > > > > > I mean for sse registers, init_cumulative_args sets the
> > > > > > integer count via the new predicate but leaves the SSE count
> > > > > > keyed on the raw ABI
> > > > > > (i386.cc:1940):
> > > > >
> > > > > Fixed with tests in the v3 patch.
> > > > >
> > > > > > 927  /* Set up the number of registers to use for passing
> > > > > > arguments.  */
> > > > > > 928  cum->nregs = ix86_regparm;
> > > > > > 929  if (TARGET_64BIT)
> > > > > > 930    {
> > > > > > 931      cum->nregs = (x86_64_cumulative_ms_abi_p (cum)
> > > > > > 932                    ? X86_64_MS_REGPARM_MAX
> > > > > > 933                    : X86_64_REGPARM_MAX);
> > > > > > 934    }
> > > > > > 935  if (TARGET_SSE)
> > > > > > 936    {
> > > > > > 937      cum->sse_nregs = SSE_REGPARM_MAX;
> > > > > > 938      if (TARGET_64BIT)
> > > > > > 939        {
> > > > > > 940          cum->sse_nregs = (cum->call_abi == SYSV_ABI
> > > > > > 941                           ? X86_64_SSE_REGPARM_MAX
> > > > > > 942                           : X86_64_MS_SSE_REGPARM_MAX);
> > > > > > 943        }
> > > > > > 944    }
> > > > > >
> > > > > >
> > > > > >  if  -mabi=ms is in the command line, with plain preserve_none
> > > > > > in the attribute, only 4 sse registers is used for parameter
> > > > > > passing But with __attribute__ ((preserve_none, ms_abi)), 8
> > > > > > sse registers are used for parameter passing.
> > > > > >
> > > > > > .i.e
> > > > > > void bar(double,double,double,double,double,double)
> > > > > > __attribute__((preserve_none));
> > > > > >
> > > > > > void
> > > > > > entry (long a1, long a2, long a3, long a4, long a5, long a6) {
> > > > > > bar (a1, a2, a3, a4, a5, a6); }
> > > > > >
> > > > >
> > > > > Fixed with tests in the v3 patch.
> > > > >
> > > > > Here is the v3 patch.
> > > >
> > > > Ok.
> > >
> > > I found an issue with the v3 patch.   Here is the v4 patch with
> > > the fix:
> > >
> > > @@ -1665,10 +1668,18 @@ ix86_function_type_abi (const_tree fntype)
> > >           warned = 1;
> > >         }
> > >
> > > -      abi = MS_ABI;
> > > +      /* NB: preserve_none attribute overrides ms_abi in 64-bit mode.  */
> > > +      if (!TARGET_64BIT
> > > +         || !lookup_attribute ("preserve_none",
> > > +                               TYPE_ATTRIBUTES (fntype)))
> > > +       abi = MS_ABI;
> > >      }
> > >    else if (abi == MS_ABI
> > > -          && lookup_attribute ("sysv_abi", TYPE_ATTRIBUTES (fntype)))
> > > +          && ((TARGET_64BIT
> > > +               && lookup_attribute ("preserve_none",             <<<<
> > > This is added.
> > > +                                    TYPE_ATTRIBUTES (fntype)))
> > > +              || lookup_attribute ("sysv_abi",
> > > +                                   TYPE_ATTRIBUTES (fntype))))
> > >      abi = SYSV_ABI;
> > >
> > >    return abi;
> >
> > Routing everything through ix86_function_type_abi means a
> > preserve_none function under -mabi=ms now flips all MS-vs-SYSV-keyed
> > behavior to SYSV, not just argument registers:
> >
> > - ix86_function_value / ix86_return_in_memory → SYSV return
> > conventions
> > - STACK_BOUNDARY (via TARGET_64BIT_MS_ABI) → 64 instead of 128
> >
> > Do they make sense?
> >
> > +  return !cum->preserve_none_abi && cum->call_abi == MS_ABI;
> >
> > Also !cum->preserve_none_abi seems redundant if we set abi  to
> > SYSV_ABI whenever preserve_none_abi exists.
> >
> 
> Given the differences between MS ABI and SYSV ABI,  it's better to treat
> preserve_none attribute the same way as no_callee_saved_registers
> attribute for MS ABI functions.   Here is the v5 patch to implement it.  
> Tested
> on Linux/x86-64.

Ok.
> 
> H.J.
> ---
> In 64-bit mode, preserve_none attribute uses the same number of integer
> parameters passed in registers as SYSV ABI, but with a different set of
> 6 registers, by setting cum->preserve_none_abi to true.  Don't set
> cum->preserve_none_abi to true for MS ABI functions with preserve_none
> attribute to keep the number of integer parameters passed in registers
> unchanged as 4.  This treats preserve_none attribute the same way as
> no_callee_saved_registers attribute for MS ABI functions.
> 
> gcc/
> 
> PR target/125297
> * config/i386/i386.cc (init_cumulative_args): Don't set
> cum->preserve_none_abi to true for MS ABI functions.
> * doc/extend.texi: Update x86-64 preserve_none attribute documentation.
> 
> gcc/testsuite/
> 
> PR target/125297
> * gcc.target/i386/preserve-none-1.c: Skip llp64 target.
> * gcc.target/i386/preserve-none-31a.c: New test.
> * gcc.target/i386/preserve-none-31b.c: Likewise.
> * gcc.target/i386/preserve-none-32.c: Likewise.
> * gcc.target/i386/preserve-none-33a.c: Likewise.
> * gcc.target/i386/preserve-none-33b.c: Likewise.
> * gcc.target/i386/preserve-none-34a.c: Likewise.
> * gcc.target/i386/preserve-none-34b.c: Likewise.
> * gcc.target/i386/preserve-none-35a.c: Likewise.
> * gcc.target/i386/preserve-none-35b.c: Likewise.
> * gcc.target/i386/preserve-none-35c.c: Likewise.
> * gcc.target/i386/preserve-none-35d.c: Likewise.
> * gcc.target/i386/preserve-none-35e.c: Likewise.
> * gcc.target/i386/preserve-none-35f.c: Likewise.
> * gcc.target/i386/preserve-none-35g.c: Likewise.
> * gcc.target/i386/preserve-none-36a.c: Likewise.
> * gcc.target/i386/preserve-none-36b.c: Likewise.
> * gcc.target/i386/preserve-none-36c.c: Likewise.
> * gcc.target/i386/preserve-none-36d.c: Likewise.
> * gcc.target/i386/preserve-none-36e.c: Likewise.
> * gcc.target/i386/preserve-none-36f.c: Likewise.
> * gcc.target/i386/preserve-none-36g.c: Likewise.
> * gcc.target/i386/preserve-none-37a.c: Likewise.
> * gcc.target/i386/preserve-none-37b.c: Likewise.
> * gcc.target/i386/preserve-none-37c.c: Likewise.
> * gcc.target/i386/preserve-none-37d.c: Likewise.
> * gcc.target/i386/preserve-none-37e.c: Likewise.
> * gcc.target/i386/preserve-none-37f.c: Likewise.
> * gcc.target/i386/preserve-none-37g.c: Likewise.
> * gcc.target/i386/preserve-none-37h.c: Likewise.
> * gcc.target/i386/preserve-none-37i.c: Likewise.
> * gcc.target/i386/preserve-none-37j.c: Likewise.

Reply via email to