> -----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.
