Changes in v2: 1. Add TARGET_128BIT_ATOMIC_ENABLED. 2. Remove __atomic Builtins reference from -mcx16. 3. Update -m128bit-atomic documentation. 4. Issue an error for -m128bit-atomic with -m32.
-- H.J. -- With the silicon vendor guarantees from Intel, AMD, Hygon and Zhaoxin in: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688 many software developers would happily use inline 128-bit atomic loads and stores in their programs because they only target compatible CPUs. Add -m128bit-atomic to generate 128-bit atomic loads and stores to avoid the overhead of calling into libatomic. Enable -m128bit-atomic in 64-bit mode by default if supported by the targeting processor, which is one of x86-64-v3 capable processors as well as AVX capable processors from Intel, AMD, Hygon and Zhaoxin. gcc/ PR target/94649 PR target/126293 * common/config/i386/i386-cpuinfo.h (ix86_decode_cpu_info): New function. * config/i386/i386-options.cc (ix86_option_override_internal): Issue an error for -m128bit-atomic in 32-bit mode. Turn on -mcx16 if -m128bit-atomic is enabled. Enable -m128bit-atomic in 64-bit mode by default if supported by the targeting processor. * config/i386/i386.h (TARGET_128BIT_ATOMIC_ENABLED): New. * config/i386/i386.opt (ix86_flags): New Variable. (m128bit-atomic): New option. * config/i386/i386.opt.urls: Regenerated. * config/i386/sync.md (atomic_loadti): New pattern. (atomic_loadti_sse): Likewise. (atomic_storeti): Likewise. (atomic_storeti_sse): Likewise. * doc/invoke.texi: Remove __atomic Builtins reference from -mcx16. Document -m128bit-atomic. gcc/testsuite/ PR target/94649 PR target/126293 * g++.target/i386/pr94649-1.C: New test. * gcc.target/i386/pr126293-1a.c: Likewise. * gcc.target/i386/pr126293-1b.c: Likewise. * gcc.target/i386/pr126293-1c.c: Likewise. * gcc.target/i386/pr126293-1d.c: Likewise. * gcc.target/i386/pr126293-2a.c: Likewise. * gcc.target/i386/pr126293-2b.c: Likewise. * gcc.target/i386/pr126293-3a.c: Likewise. * gcc.target/i386/pr126293-3b.c: Likewise. * gcc.target/i386/pr126293-4a.c: Likewise. * gcc.target/i386/pr126293-4b.c: Likewise. * gcc.target/i386/pr126293-4c.c: Likewise. * gcc.target/i386/pr126293-4d.c: Likewise. * gcc.target/i386/pr126293-4e.c: Likewise. * gcc.target/i386/pr126293-4f.c: Likewise. * gcc.target/i386/pr126293-4g.c: Likewise. * gcc.target/i386/pr126293-4h.c: Likewise. * gcc.target/i386/pr126293-4i.c: Likewise. * gcc.target/i386/pr126293-4j.c: Likewise. * gcc.target/i386/pr126293-4k.c: Likewise. * gcc.target/i386/pr126293-4l.c: Likewise. * gcc.target/i386/pr126293-4m.c: Likewise. * gcc.target/i386/pr126293-4n.c: Likewise. * gcc.target/i386/pr126293-4o.c: Likewise. * gcc.target/i386/pr126293-4p.c: Likewise. * gcc.target/i386/pr126293-4q.c: Likewise. * gcc.target/i386/pr126293-5.c: Likewise. * gcc.target/i386/pr126293-6.c: Likewise. * gcc.target/i386/pr126293-7.c: Likewise. * gcc.target/i386/pr126293-8.c: Likewise. * gcc.target/i386/pr126293-9.c: Likewise. * gcc.target/i386/pr126293-10.c: Likewise. * gcc.target/i386/pr126293-11.c: Likewise. * gcc.target/i386/pr126293-12.c: Likewise. * gcc.target/i386/pr126293-13.c: Likewise. * gcc.target/i386/pr126293-14.c: Likewise. * gcc.target/i386/pr126293-15.c: Likewise. * gcc.target/i386/pr126293-16.c: Likewise. * gcc.target/i386/pr126293-17.c: Likewise.
From 3f665af0bc24801c9c0ba362ef43eccf4e66e229 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <[email protected]> Date: Fri, 17 Jul 2026 08:35:34 +0800 Subject: [PATCH v2] x86-64: Add -m128bit-atomic With the silicon vendor guarantees from Intel, AMD, Hygon and Zhaoxin in: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688 many software developers would happily use inline 128-bit atomic loads and stores in their programs because they only target compatible CPUs. Add -m128bit-atomic to generate 128-bit atomic loads and stores to avoid the overhead of calling into libatomic. Enable -m128bit-atomic in 64-bit mode by default if supported by the targeting processor, which is one of x86-64-v3 capable processors as well as AVX capable processors from Intel, AMD, Hygon and Zhaoxin. gcc/ PR target/94649 PR target/126293 * common/config/i386/i386-cpuinfo.h (ix86_decode_cpu_info): New function. * config/i386/i386-options.cc (ix86_option_override_internal): Issue an error for -m128bit-atomic in 32-bit mode. Turn on -mcx16 if -m128bit-atomic is enabled. Enable -m128bit-atomic in 64-bit mode by default if supported by the targeting processor. * config/i386/i386.h (TARGET_128BIT_ATOMIC_ENABLED): New. * config/i386/i386.opt (ix86_flags): New Variable. (m128bit-atomic): New option. * config/i386/i386.opt.urls: Regenerated. * config/i386/sync.md (atomic_loadti): New pattern. (atomic_loadti_sse): Likewise. (atomic_storeti): Likewise. (atomic_storeti_sse): Likewise. * doc/invoke.texi: Remove __atomic Builtins reference from -mcx16. Document -m128bit-atomic. gcc/testsuite/ PR target/94649 PR target/126293 * g++.target/i386/pr94649-1.C: New test. * gcc.target/i386/pr126293-1a.c: Likewise. * gcc.target/i386/pr126293-1b.c: Likewise. * gcc.target/i386/pr126293-1c.c: Likewise. * gcc.target/i386/pr126293-1d.c: Likewise. * gcc.target/i386/pr126293-2a.c: Likewise. * gcc.target/i386/pr126293-2b.c: Likewise. * gcc.target/i386/pr126293-3a.c: Likewise. * gcc.target/i386/pr126293-3b.c: Likewise. * gcc.target/i386/pr126293-4a.c: Likewise. * gcc.target/i386/pr126293-4b.c: Likewise. * gcc.target/i386/pr126293-4c.c: Likewise. * gcc.target/i386/pr126293-4d.c: Likewise. * gcc.target/i386/pr126293-4e.c: Likewise. * gcc.target/i386/pr126293-4f.c: Likewise. * gcc.target/i386/pr126293-4g.c: Likewise. * gcc.target/i386/pr126293-4h.c: Likewise. * gcc.target/i386/pr126293-4i.c: Likewise. * gcc.target/i386/pr126293-4j.c: Likewise. * gcc.target/i386/pr126293-4k.c: Likewise. * gcc.target/i386/pr126293-4l.c: Likewise. * gcc.target/i386/pr126293-4m.c: Likewise. * gcc.target/i386/pr126293-4n.c: Likewise. * gcc.target/i386/pr126293-4o.c: Likewise. * gcc.target/i386/pr126293-4p.c: Likewise. * gcc.target/i386/pr126293-4q.c: Likewise. * gcc.target/i386/pr126293-5.c: Likewise. * gcc.target/i386/pr126293-6.c: Likewise. * gcc.target/i386/pr126293-7.c: Likewise. * gcc.target/i386/pr126293-8.c: Likewise. * gcc.target/i386/pr126293-9.c: Likewise. * gcc.target/i386/pr126293-10.c: Likewise. * gcc.target/i386/pr126293-11.c: Likewise. * gcc.target/i386/pr126293-12.c: Likewise. * gcc.target/i386/pr126293-13.c: Likewise. * gcc.target/i386/pr126293-14.c: Likewise. * gcc.target/i386/pr126293-15.c: Likewise. * gcc.target/i386/pr126293-16.c: Likewise. * gcc.target/i386/pr126293-17.c: Likewise. Signed-off-by: H.J. Lu <[email protected]> --- gcc/common/config/i386/i386-cpuinfo.h | 126 ++++++++++++++++++++ gcc/config/i386/i386-options.cc | 46 +++++++ gcc/config/i386/i386.h | 9 ++ gcc/config/i386/i386.opt | 7 ++ gcc/config/i386/i386.opt.urls | 3 + gcc/config/i386/sync.md | 49 ++++++++ gcc/doc/invoke.texi | 24 +++- gcc/testsuite/g++.target/i386/pr94649-1.C | 17 +++ gcc/testsuite/gcc.target/i386/pr126293-10.c | 25 ++++ gcc/testsuite/gcc.target/i386/pr126293-11.c | 24 ++++ gcc/testsuite/gcc.target/i386/pr126293-12.c | 28 +++++ gcc/testsuite/gcc.target/i386/pr126293-13.c | 28 +++++ gcc/testsuite/gcc.target/i386/pr126293-14.c | 30 +++++ gcc/testsuite/gcc.target/i386/pr126293-15.c | 30 +++++ gcc/testsuite/gcc.target/i386/pr126293-16.c | 3 + gcc/testsuite/gcc.target/i386/pr126293-17.c | 4 + gcc/testsuite/gcc.target/i386/pr126293-1a.c | 22 ++++ gcc/testsuite/gcc.target/i386/pr126293-1b.c | 6 + gcc/testsuite/gcc.target/i386/pr126293-1c.c | 6 + gcc/testsuite/gcc.target/i386/pr126293-1d.c | 6 + gcc/testsuite/gcc.target/i386/pr126293-2a.c | 23 ++++ gcc/testsuite/gcc.target/i386/pr126293-2b.c | 55 +++++++++ gcc/testsuite/gcc.target/i386/pr126293-3a.c | 21 ++++ gcc/testsuite/gcc.target/i386/pr126293-3b.c | 45 +++++++ gcc/testsuite/gcc.target/i386/pr126293-4a.c | 25 ++++ gcc/testsuite/gcc.target/i386/pr126293-4b.c | 18 +++ gcc/testsuite/gcc.target/i386/pr126293-4c.c | 18 +++ gcc/testsuite/gcc.target/i386/pr126293-4d.c | 18 +++ gcc/testsuite/gcc.target/i386/pr126293-4e.c | 18 +++ gcc/testsuite/gcc.target/i386/pr126293-4f.c | 18 +++ gcc/testsuite/gcc.target/i386/pr126293-4g.c | 18 +++ gcc/testsuite/gcc.target/i386/pr126293-4h.c | 18 +++ gcc/testsuite/gcc.target/i386/pr126293-4i.c | 18 +++ gcc/testsuite/gcc.target/i386/pr126293-4j.c | 19 +++ gcc/testsuite/gcc.target/i386/pr126293-4k.c | 19 +++ gcc/testsuite/gcc.target/i386/pr126293-4l.c | 19 +++ gcc/testsuite/gcc.target/i386/pr126293-4m.c | 18 +++ gcc/testsuite/gcc.target/i386/pr126293-4n.c | 19 +++ gcc/testsuite/gcc.target/i386/pr126293-4o.c | 18 +++ gcc/testsuite/gcc.target/i386/pr126293-4p.c | 18 +++ gcc/testsuite/gcc.target/i386/pr126293-4q.c | 18 +++ gcc/testsuite/gcc.target/i386/pr126293-5.c | 25 ++++ gcc/testsuite/gcc.target/i386/pr126293-6.c | 23 ++++ gcc/testsuite/gcc.target/i386/pr126293-7.c | 23 ++++ gcc/testsuite/gcc.target/i386/pr126293-8.c | 23 ++++ gcc/testsuite/gcc.target/i386/pr126293-9.c | 23 ++++ 46 files changed, 1068 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.target/i386/pr94649-1.C create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-10.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-11.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-12.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-13.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-14.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-15.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-16.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-17.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-1a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-1b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-1c.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-1d.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-2a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-2b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-3a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-3b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4c.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4d.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4e.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4f.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4g.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4h.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4i.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4j.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4k.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4l.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4m.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4n.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4o.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4p.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-4q.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-5.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-6.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-7.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-8.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126293-9.c diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h index a38534c53df..7ea02bbe7e8 100644 --- a/gcc/common/config/i386/i386-cpuinfo.h +++ b/gcc/common/config/i386/i386-cpuinfo.h @@ -299,3 +299,129 @@ enum processor_features #define M_VENDOR(a) (a) #define M_CPU_TYPE(a) (M_CPU_TYPE_START + int (a)) #define M_CPU_SUBTYPE(a) (M_CPU_SUBTYPE_START + a) + +#ifdef __cplusplus +/* Extract processor VENDOR, TYPE and SUBTYPE from MODEL. */ + +static inline void +ix86_decode_cpu_info (int model, processor_vendor &vendor, + processor_types &type, + processor_subtypes &subtype) +{ + if (model > M_CPU_SUBTYPE_START) + { + subtype = (processor_subtypes) (model - M_CPU_SUBTYPE_START); + if (subtype <= INTEL_COREI7_SANDYBRIDGE + || (subtype >= INTEL_COREI7_IVYBRIDGE + && subtype <= INTEL_COREI7_ICELAKE_SERVER) + || (subtype >= INTEL_COREI7_CASCADELAKE + && subtype <= INTEL_COREI7_ALDERLAKE) + || subtype == INTEL_COREI7_ROCKETLAKE + || (subtype >= INTEL_COREI7_GRANITERAPIDS + && subtype <= INTEL_COREI7_PANTHERLAKE) + || subtype == INTEL_COREI7_DIAMONDRAPIDS + || subtype <= INTEL_COREI7_NOVALAKE) + { + vendor = VENDOR_INTEL; + type = INTEL_COREI7; + } + else if (subtype >= AMDFAM10H_BARCELONA + && subtype <= AMDFAM10H_ISTANBUL) + { + vendor = VENDOR_AMD; + type = AMDFAM10H; + } + else if (subtype >= AMDFAM15H_BDVER1 + && subtype <= AMDFAM15H_BDVER4) + { + vendor = VENDOR_AMD; + type = AMDFAM15H; + } + else if (subtype == AMDFAM17H_ZNVER1 + || subtype == AMDFAM17H_ZNVER2) + { + vendor = VENDOR_AMD; + type = AMDFAM17H; + } + else if (subtype == AMDFAM19H_ZNVER3 + || subtype == AMDFAM19H_ZNVER4) + { + vendor = VENDOR_AMD; + type = AMDFAM19H; + } + else if (subtype == AMDFAM1AH_ZNVER5 + || subtype == AMDFAM1AH_ZNVER6) + { + vendor = VENDOR_AMD; + type = AMDFAM1AH; + } + else if (subtype == ZHAOXIN_FAM7H_LUJIAZUI + || subtype == ZHAOXIN_FAM7H_YONGFENG + || subtype == ZHAOXIN_FAM7H_SHIJIDADAO) + { + vendor = VENDOR_ZHAOXIN; + type = ZHAOXIN_FAM7H; + } + else if (subtype >= HYGONFAM18H_C86_4G_M4 + && subtype <= HYGONFAM18H_C86_4G_M8) + { + vendor = VENDOR_HYGON; + type = HYGONFAM18H; + } + else + { + /* Set VENDOR to VENDOR_OTHER and TYPE to CPU_TYPE_MAX for + unsupported SUBTYPE. */ + vendor = VENDOR_OTHER; + type = CPU_TYPE_MAX; + } + } + else if (model > M_CPU_TYPE_START) + { + type = (processor_types) (model - M_CPU_TYPE_START); + if ((type >= INTEL_BONNELL && type <= INTEL_COREI7) + || type == INTEL_SILVERMONT + || (type >= INTEL_GOLDMONT && type <= INTEL_TREMONT) + || (type >= INTEL_SIERRAFOREST + && type <= INTEL_CLEARWATERFOREST)) + { + vendor = VENDOR_INTEL; + subtype = CPU_SUBTYPE_MAX; + } + else if (type == AMDFAM10H + || type == AMDFAM15H + || (type >= AMD_BTVER1 && type <= AMDFAM17H) + || type == AMDFAM19H + || type == AMDFAM1AH) + { + vendor = VENDOR_AMD; + subtype = CPU_SUBTYPE_MAX; + } + else if (type == ZHAOXIN_FAM7H) + { + vendor = VENDOR_ZHAOXIN; + subtype = CPU_SUBTYPE_MAX; + } + else if (type == HYGONFAM18H) + { + vendor = VENDOR_HYGON; + subtype = CPU_SUBTYPE_MAX; + } + else + { + /* Set VENDOR to VENDOR_OTHER and SUBTYPE to CPU_SUBTYPE_MAX + for unsupported TYPE. */ + vendor = VENDOR_OTHER; + subtype = CPU_SUBTYPE_MAX; + } + } + else + { + vendor = (processor_vendor) model; + /* Set TYPE to CPU_TYPE_MAX and SUBTYPE to CPU_SUBTYPE_MAX for + unknown TYPE and SUBTYPE. */ + type = CPU_TYPE_MAX; + subtype = CPU_SUBTYPE_MAX; + } +} +#endif diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc index a9d31714f13..30f4649a5b2 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -2303,6 +2303,11 @@ ix86_option_override_internal (bool main_args_p, sorry ("%i-bit mode not compiled in", (opts->x_ix86_isa_flags & OPTION_MASK_ISA_64BIT) ? 64 : 32); + processor_vendor ix86_vendor = VENDOR_OTHER; + processor_types ix86_type = CPU_TYPE_MAX; + processor_subtypes ix86_subtype = CPU_SUBTYPE_MAX; + wide_int_bitmask ix86_pta = 0; + /* Last processor_alias_table must point to "generic" entry. */ gcc_checking_assert (strcmp (processor_alias_table[pta_size - 1].name, "generic") == 0); @@ -2338,6 +2343,10 @@ ix86_option_override_internal (bool main_args_p, ix86_schedule = processor_alias_table[i].schedule; ix86_arch = processor_alias_table[i].processor; + ix86_pta = processor_alias_table[i].flags; + + ix86_decode_cpu_info (processor_alias_table[i].model, + ix86_vendor, ix86_type, ix86_subtype); /* Default cpu tuning to the architecture, unless the table entry requests not to do this. Used by the x86-64 psABI @@ -2526,6 +2535,43 @@ ix86_option_override_internal (bool main_args_p, XDELETEVEC (s); } + if (TARGET_128BIT_ATOMIC_P (opts->x_ix86_flags)) + { + if (!TARGET_64BIT_P (opts->x_ix86_isa_flags)) + error ("%<-m128bit-atomic%> not supported for 32-bit code"); + else if (!TARGET_CX16_P (opts_set->x_ix86_isa_flags2)) + { + /* Enable CMPXCHG16B when -m128bit-atomic is enabled. */ + opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_CX16; + } + } + else if (!TARGET_128BIT_ATOMIC_P (opts_set->x_ix86_flags) + && TARGET_64BIT_P (opts->x_ix86_isa_flags) + && ((TARGET_AVX_P (opts->x_ix86_isa_flags) + && (ix86_vendor == VENDOR_INTEL + || ix86_vendor == VENDOR_AMD + || ix86_vendor == VENDOR_HYGON + || ix86_vendor == VENDOR_ZHAOXIN)) + || (ix86_pta & PTA_X86_64_V3) == PTA_X86_64_V3 + || ix86_type == AMDFAM17H + || ix86_type == AMDFAM19H + || ix86_type == AMDFAM1AH + || ix86_type == HYGONFAM18H + || (ix86_type >= INTEL_SIERRAFOREST + && ix86_type <= INTEL_CLEARWATERFOREST) + || ix86_subtype == INTEL_COREI7_SANDYBRIDGE + || (ix86_subtype >= AMDFAM17H_ZNVER1 + && ix86_subtype <= INTEL_COREI7_ROCKETLAKE) + || (ix86_subtype >= AMDFAM19H_ZNVER4 + && ix86_subtype <= HYGONFAM18H_C86_4G_M8))) + { + /* Turn on -m128bit-atomic in 64-bit mode by default if supported + by the targeting processor, which is one of x86-64-v3 capable + processors as well as AVX capable processors from Intel, AMD, + Hygon and Zhaoxin. */ + opts->x_ix86_flags |= OPTION_MASK_128BIT_ATOMIC; + } + set_ix86_tune_features (opts, ix86_tune, opts->x_ix86_dump_tunes); ix86_recompute_optlev_based_flags (opts, opts_set); diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index f2e8fd2447f..8a11a5c75e5 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -3085,6 +3085,15 @@ extern void debug_dispatch_window (int); #define TARGET_RECIP_VEC_DIV ((recip_mask & RECIP_MASK_VEC_DIV) != 0) #define TARGET_RECIP_VEC_SQRT ((recip_mask & RECIP_MASK_VEC_SQRT) != 0) +/* -m128bit-atomic requires CMPXCHG16B and SSE2. + + Note: Pre-Tiger Lake (Desktop/Mobile): Generations including Kaby + Lake, Coffee Lake, and Comet Lake (e.g., Pentium Gold G5400, Celeron + G5900, N4020) do not support AVX. However, 128-bit aligned SSE loads + and stores are atomic on these processors. Should AVX be required? */ +#define TARGET_128BIT_ATOMIC_ENABLED \ + (TARGET_CX16 && TARGET_SSE2 && TARGET_128BIT_ATOMIC) + /* Use 128-bit AVX instructions in the auto-vectorizer. */ #define TARGET_PREFER_AVX128 (prefer_vector_width_type == PVW_AVX128) /* Use 256-bit AVX instructions in the auto-vectorizer. */ diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index 158090c2bde..003b6a8c0b8 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -188,6 +188,9 @@ const char *x_ix86_tune_memset_strategy TargetSave int x_ix86_tune_no_default +Variable +int ix86_flags = 0 + ;; -mveclibabi= TargetVariable enum ix86_veclibabi ix86_veclibabi_type = ix86_veclibabi_type_none @@ -1385,3 +1388,7 @@ Support AMX-MOVRS built-in functions and code generation. mavx512bmm Target Mask(ISA2_AVX512BMM) Var(ix86_isa_flags2) Save Support AVX512BMM built-in functions and code generation. + +m128bit-atomic +Target Mask(128BIT_ATOMIC) Var(ix86_flags) Save +Generate cmpxchg16b, 128-bit atomic vector loads and stores for the x86-64 architecture. diff --git a/gcc/config/i386/i386.opt.urls b/gcc/config/i386/i386.opt.urls index 5ae63d6b520..63345150ba1 100644 --- a/gcc/config/i386/i386.opt.urls +++ b/gcc/config/i386/i386.opt.urls @@ -554,6 +554,9 @@ UrlSuffix(gcc/x86-Options.html#index-mavx512fp16) mdirect-extern-access UrlSuffix(gcc/x86-Options.html#index-mdirect-extern-access-1) +m128bit-atomic +UrlSuffix(gcc/x86-Options.html#index-m128bit-atomic) + mavxifma UrlSuffix(gcc/x86-Options.html#index-mavxifma) diff --git a/gcc/config/i386/sync.md b/gcc/config/i386/sync.md index d9f822f4821..562592ac1fc 100644 --- a/gcc/config/i386/sync.md +++ b/gcc/config/i386/sync.md @@ -388,6 +388,55 @@ (define_insn "storedi_via_sse" [(set_attr "type" "ssemov") (set_attr "mode" "DI")]) +(define_expand "atomic_loadti" + [(set (match_operand:TI 0 "nonimmediate_operand") + (unspec:TI [(match_operand:TI 1 "memory_operand") + (match_operand:SI 2 "const_int_operand")] + UNSPEC_LDA))] + "TARGET_128BIT_ATOMIC_ENABLED" +{ + emit_insn (gen_atomic_loadti_sse (operands[0], operands[1])); + DONE; +}) + +(define_insn_and_split "atomic_loadti_sse" + [(set (match_operand:TI 0 "register_operand" "=v") + (unspec:TI [(match_operand:TI 1 "memory_operand" "m")] + UNSPEC_LDX_ATOMIC))] + "TARGET_128BIT_ATOMIC_ENABLED" + "#" + "&& reload_completed" + [(set (match_dup 0) (match_dup 1))]) + +(define_expand "atomic_storeti" + [(set (match_operand:TI 0 "memory_operand") + (unspec:TI [(match_operand:TI 1 "nonimmediate_operand") + (match_operand:SI 2 "const_int_operand")] + UNSPEC_STA))] + "TARGET_128BIT_ATOMIC_ENABLED" +{ + /* Use V1TImode to force vector register for atomic store. */ + rtx src = gen_reg_rtx (V1TImode); + rtx op1 = gen_lowpart (V1TImode, operands[1]); + emit_move_insn (src, op1); + emit_insn (gen_atomic_storeti_sse (operands[0], src)); + DONE; +}) + +(define_insn_and_split "atomic_storeti_sse" + [(set (match_operand:TI 0 "memory_operand" "=m") + (unspec:TI [(match_operand:V1TI 1 "nonimmediate_operand" "v")] + UNSPEC_STX_ATOMIC))] + "TARGET_128BIT_ATOMIC_ENABLED" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx src = gen_lowpart (TImode, operands[1]); + emit_move_insn (operands[0], src); + DONE; +}) + (define_expand "atomic_compare_and_swap<mode>" [(match_operand:QI 0 "register_operand") ;; bool success output (match_operand:SWI124 1 "register_operand") ;; oldval output diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 2c2ed1a003f..0c3bc709ef7 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1576,7 +1576,7 @@ See RS/6000 and PowerPC Options. -mstack-protector-guard-offset=@var{offset} -mstack-protector-guard-symbol=@var{symbol} -mgeneral-regs-only -mcall-ms2sysv-xlogues -mtls-dialect=@var{type} --mrelax-cmpxchg-loop +-m128bit-atomic -mrelax-cmpxchg-loop -mindirect-branch=@var{choice} -mfunction-return=@var{choice} -mindirect-branch-register -mharden-sls=@var{choice} -mindirect-branch-cs-prefix -mapx-inline-asm-use-gpr32 @@ -36712,8 +36712,7 @@ This option enables GCC to generate @code{CMPXCHG16B} instructions in 64-bit code to implement compare-and-exchange operations on 16-byte aligned 128-bit objects. This is useful for atomic updates of data structures exceeding one machine word in size. The compiler uses this instruction to implement -@ref{__sync Builtins}. However, for @ref{__atomic Builtins} operating on -128-bit integers, a library call is always used. +@ref{__sync Builtins}. @opindex msahf @opindex mno-sahf @@ -37278,6 +37277,25 @@ Generate code that uses only the general-purpose registers. This prevents the compiler from using floating-point, vector, mask and bound registers. +@opindex m128bit-atomic +@opindex mno-128bit-atomic +@item -m128bit-atomic +Generate cmpxchg16b, 128-bit atomic vector load and store instructions +for the x86-64 architecture. This is safe to use only on x86-64-v3 +capable processors as well as AVX capable processors from Intel, AMD, +Hygon and Zhaoxin, which guarantee that 128-bit aligned vector loads +and stores are atomic. This option requires SSE2 and CMPXCHG16B. It +implies @option{-mcx16} which enables CMPXCHG16B. This option is +enabled in 64-bit mode by default if supported by the targeting +processor. For @ref{__atomic Builtins} operating on 128-bit integers, +this option generates atomic instructions directly, instead of calling +a library function in the @file{libatomic} runtime library. + +Note that when SSE2 is disabled, i.e., by @option{-mgeneral-regs-only}, +128-bit atomic operations are unsupported and @file{libatomic} shouldn't +be used since it may use SSE2 or AVX instructions to implement 128-bit +atomic operations. + @opindex mrelax-cmpxchg-loop @opindex mno-relax-cmpxchg-loop @item -mrelax-cmpxchg-loop diff --git a/gcc/testsuite/g++.target/i386/pr94649-1.C b/gcc/testsuite/g++.target/i386/pr94649-1.C new file mode 100644 index 00000000000..7871e319134 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr94649-1.C @@ -0,0 +1,17 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -std=c++11 -march=x86-64 -m128bit-atomic" } */ +/* { dg-final { scan-assembler-times "lock;?\[ \\t\]+cmpxchg16b" 1 } } */ + +#include <atomic> + +struct alignas(16) a +{ + long x; + long y; +}; + +bool +cmpxchg(std::atomic<a>& data, a expected, a newval) +{ + return std::atomic_compare_exchange_weak(&data, &expected, newval); +} diff --git a/gcc/testsuite/gcc.target/i386/pr126293-10.c b/gcc/testsuite/gcc.target/i386/pr126293-10.c new file mode 100644 index 00000000000..62ed9dd0e8c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-10.c @@ -0,0 +1,25 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=x86-64 -m128bit-atomic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** fldt 8\(%rsp\) +** fstpt -24\(%rsp\) +** movdqa -24\(%rsp\), %xmm0 +** movaps %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +extern _Atomic long double store; + +void +func (long double i) +{ + store = i; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126293-11.c b/gcc/testsuite/gcc.target/i386/pr126293-11.c new file mode 100644 index 00000000000..aa65acda009 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-11.c @@ -0,0 +1,24 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=x86-64 -m128bit-atomic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movdqa load\(%rip\), %xmm0 +** movaps %xmm0, -24\(%rsp\) +** fldt -24\(%rsp\) +** ret +** .cfi_endproc +**... +*/ + +extern _Atomic long double load; + +long double +func (void) +{ + return load; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126293-12.c b/gcc/testsuite/gcc.target/i386/pr126293-12.c new file mode 100644 index 00000000000..feb7ba465ba --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-12.c @@ -0,0 +1,28 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=x86-64 -m128bit-atomic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movaps %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +typedef float vector __attribute__((vector_size (16))); +typedef struct +{ + vector v; +} v; + +extern _Atomic v store; + +void +func (v i) +{ + store = i; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126293-13.c b/gcc/testsuite/gcc.target/i386/pr126293-13.c new file mode 100644 index 00000000000..a46eb736347 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-13.c @@ -0,0 +1,28 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=x86-64 -m128bit-atomic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movdqa load\(%rip\), %xmm0 +** ret +** .cfi_endproc +**... +*/ + +typedef float vector __attribute__((vector_size (16))); +typedef struct +{ + vector v; +} v; + +extern _Atomic v load; + +v +func (void) +{ + return load; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126293-14.c b/gcc/testsuite/gcc.target/i386/pr126293-14.c new file mode 100644 index 00000000000..b342020cf97 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-14.c @@ -0,0 +1,30 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=x86-64 -m128bit-atomic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movq %rdi, %xmm0 +** movq %rsi, %xmm1 +** punpcklqdq %xmm1, %xmm0 +** movaps %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +typedef struct +{ + int a[4]; +} s; + +extern _Atomic s store; + +void +func (s i) +{ + store = i; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126293-15.c b/gcc/testsuite/gcc.target/i386/pr126293-15.c new file mode 100644 index 00000000000..058e432058d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-15.c @@ -0,0 +1,30 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=x86-64 -m128bit-atomic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movdqa load\(%rip\), %xmm0 +** movaps %xmm0, -24\(%rsp\) +** movq -24\(%rsp\), %rax +** movq -16\(%rsp\), %rdx +** ret +** .cfi_endproc +**... +*/ + +typedef struct +{ + int a[4]; +} s; + +_Atomic s load; + +s +func (void) +{ + return load; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126293-16.c b/gcc/testsuite/gcc.target/i386/pr126293-16.c new file mode 100644 index 00000000000..4c4d486bc30 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-16.c @@ -0,0 +1,3 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-additional-options "-O2 -march=x86-64 -m128bit-atomic" } */ +/* { dg-error "'-m128bit-atomic' not supported for 32-bit code" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/gcc.target/i386/pr126293-17.c b/gcc/testsuite/gcc.target/i386/pr126293-17.c new file mode 100644 index 00000000000..aafee4797fb --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-17.c @@ -0,0 +1,4 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-additional-options "-O2 -march=x86-64-v3" } */ + +#include <x86intrin.h> diff --git a/gcc/testsuite/gcc.target/i386/pr126293-1a.c b/gcc/testsuite/gcc.target/i386/pr126293-1a.c new file mode 100644 index 00000000000..cd34926a377 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-1a.c @@ -0,0 +1,22 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -march=x86-64 -m128bit-atomic" } */ +/* { dg-final { scan-assembler-times "lock;?\[ \\t\]+cmpxchg16b" 8 } } */ + +#include <stdint.h> + +#define FUNC_ATOMIC(TYPE, OP) \ +__attribute__ ((noinline, noclone)) \ +TYPE f_##TYPE##_##OP##_fetch (TYPE *a, TYPE b) \ +{ \ + return __atomic_##OP##_fetch (a, b, __ATOMIC_RELAXED); \ +} \ +__attribute__ ((noinline, noclone)) \ +TYPE f_##TYPE##_fetch_##OP (TYPE *a, TYPE b) \ +{ \ + return __atomic_fetch_##OP (a, b, __ATOMIC_RELAXED); \ +} + +FUNC_ATOMIC (__int128_t, and) +FUNC_ATOMIC (__int128_t, nand) +FUNC_ATOMIC (__int128_t, or) +FUNC_ATOMIC (__int128_t, xor) diff --git a/gcc/testsuite/gcc.target/i386/pr126293-1b.c b/gcc/testsuite/gcc.target/i386/pr126293-1b.c new file mode 100644 index 00000000000..bbd74e4c73a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-1b.c @@ -0,0 +1,6 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -march=x86-64 -mno-cx16 -m128bit-atomic" } */ +/* { dg-final { scan-assembler-times "call\[ \\t\]+__atomic_fetch_" 4 } } */ +/* { dg-final { scan-assembler-times "jmp\[ \\t\]+__atomic_fetch_" 4 } } */ + +#include "pr126293-1a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-1c.c b/gcc/testsuite/gcc.target/i386/pr126293-1c.c new file mode 100644 index 00000000000..85fe25cae8b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-1c.c @@ -0,0 +1,6 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -march=x86-64 -m128bit-atomic -mno-cx16" } */ +/* { dg-final { scan-assembler-times "call\[ \\t\]+__atomic_fetch_" 4 } } */ +/* { dg-final { scan-assembler-times "jmp\[ \\t\]+__atomic_fetch_" 4 } } */ + +#include "pr126293-1a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-1d.c b/gcc/testsuite/gcc.target/i386/pr126293-1d.c new file mode 100644 index 00000000000..6ca19cb1060 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-1d.c @@ -0,0 +1,6 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -march=x86-64 -m128bit-atomic" } */ +/* { dg-final { scan-assembler-times "lock;?\[ \\t\]+cmpxchg16b" 8 } } */ + +#include <x86intrin.h> +#include "pr126293-1a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-2a.c b/gcc/testsuite/gcc.target/i386/pr126293-2a.c new file mode 100644 index 00000000000..d2a11579d2f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-2a.c @@ -0,0 +1,23 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -march=x86-64 -m128bit-atomic -mrelax-cmpxchg-loop" } */ +/* { dg-final { scan-assembler-times "rep;?\[ \\t\]+nop" 8 } } */ +/* { dg-final { scan-assembler-times "lock;?\[ \\t\]+cmpxchg16b" 8 } } */ + +#include <stdint.h> + +#define FUNC_ATOMIC(TYPE, OP) \ +__attribute__ ((noinline, noclone)) \ +TYPE f_##TYPE##_##OP##_fetch (TYPE *a, TYPE b) \ +{ \ + return __atomic_##OP##_fetch (a, b, __ATOMIC_RELAXED); \ +} \ +__attribute__ ((noinline, noclone)) \ +TYPE f_##TYPE##_fetch_##OP (TYPE *a, TYPE b) \ +{ \ + return __atomic_fetch_##OP (a, b, __ATOMIC_RELAXED); \ +} + +FUNC_ATOMIC (__int128_t, and) +FUNC_ATOMIC (__int128_t, nand) +FUNC_ATOMIC (__int128_t, or) +FUNC_ATOMIC (__int128_t, xor) diff --git a/gcc/testsuite/gcc.target/i386/pr126293-2b.c b/gcc/testsuite/gcc.target/i386/pr126293-2b.c new file mode 100644 index 00000000000..b74579c7cb0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-2b.c @@ -0,0 +1,55 @@ +/* { dg-do run { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -march=x86-64 -m128bit-atomic" } */ + +#include <stdlib.h> +#include "pr126293-2a.c" + +#define FUNC_ATOMIC_RELAX(TYPE, OP) \ +__attribute__ ((noinline, noclone, target ("relax-cmpxchg-loop"))) \ +TYPE relax_##TYPE##_##OP##_fetch (TYPE *a, TYPE b) \ +{ \ + return __atomic_##OP##_fetch (a, b, __ATOMIC_RELAXED); \ +} \ +__attribute__ ((noinline, noclone, target ("relax-cmpxchg-loop"))) \ +TYPE relax_##TYPE##_fetch_##OP (TYPE *a, TYPE b) \ +{ \ + return __atomic_fetch_##OP (a, b, __ATOMIC_RELAXED); \ +} + +FUNC_ATOMIC_RELAX (__int128_t, and) +FUNC_ATOMIC_RELAX (__int128_t, nand) +FUNC_ATOMIC_RELAX (__int128_t, or) +FUNC_ATOMIC_RELAX (__int128_t, xor) + +#define TEST_ATOMIC_FETCH_LOGIC(TYPE, OP) \ +{ \ + TYPE a = 11, b = 101, res, exp; \ + TYPE c = 11, d = 101; \ + res = relax_##TYPE##_##OP##_fetch (&a, b); \ + exp = f_##TYPE##_##OP##_fetch (&c, d); \ + if (res != exp || a != c) \ + abort (); \ + a = c = 21, b = d = 92; \ + res = relax_##TYPE##_fetch_##OP (&a, b); \ + exp = f_##TYPE##_fetch_##OP (&c, d); \ + if (res != exp || a != c) \ + abort (); \ +} + +__attribute__((noinline)) +static void +do_test (void) +{ + TEST_ATOMIC_FETCH_LOGIC (__int128_t, and) + TEST_ATOMIC_FETCH_LOGIC (__int128_t, nand) + TEST_ATOMIC_FETCH_LOGIC (__int128_t, or) + TEST_ATOMIC_FETCH_LOGIC (__int128_t, xor) +} + +int +main (void) +{ + if (__builtin_cpu_supports ("cmpxchg16b")) + do_test (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126293-3a.c b/gcc/testsuite/gcc.target/i386/pr126293-3a.c new file mode 100644 index 00000000000..48630f5f6b6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-3a.c @@ -0,0 +1,21 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -march=x86-64 -m128bit-atomic -mrelax-cmpxchg-loop" } */ +/* { dg-final { scan-assembler-times "lock;?\[ \\t\]+cmpxchg16b" 1 } } */ + +#include <stdint.h> + +#define FUNC_CMPXCHG(TYPE) \ +__attribute__ ((noinline, noclone)) \ +TYPE f_##TYPE##_cmpxchg (TYPE *lock, TYPE newval, TYPE oldval) \ +{ \ + do \ + { \ + newval = oldval | 1; \ + } while (! __atomic_compare_exchange_n (lock, &oldval, newval, \ + 0, __ATOMIC_RELEASE, \ + __ATOMIC_RELAXED)); \ + return *lock; \ +} + + +FUNC_CMPXCHG (__int128_t) diff --git a/gcc/testsuite/gcc.target/i386/pr126293-3b.c b/gcc/testsuite/gcc.target/i386/pr126293-3b.c new file mode 100644 index 00000000000..1e9d1872f8e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-3b.c @@ -0,0 +1,45 @@ +/* { dg-do run { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -march=x86-64 -m128bit-atomic" } */ + +#include <stdlib.h> +#include "pr126293-3a.c" + +#define FUNC_CMPXCHG_RELAX(TYPE) \ +__attribute__ ((noinline, noclone, target ("relax-cmpxchg-loop"))) \ +TYPE relax_##TYPE##_cmpxchg (TYPE *lock, TYPE newval, TYPE oldval) \ +{ \ + do \ + { \ + newval = oldval | 1; \ + } while (! __atomic_compare_exchange_n (lock, &oldval, newval, \ + 0, __ATOMIC_RELEASE, \ + __ATOMIC_RELAXED)); \ + return *lock; \ +} + +FUNC_CMPXCHG_RELAX (__int128_t) + +#define TEST_CMPXCHG_LOOP(TYPE) \ +{ \ + TYPE a = 11, b = 20, c = 11, res, exp; \ + TYPE d = 11, e = 20, f = 11; \ + res = relax_##TYPE##_cmpxchg (&a, b, c); \ + exp = f_##TYPE##_cmpxchg (&d, e, f); \ + if (res != exp || a != d) \ + abort (); \ +} + +__attribute__((noinline)) +static void +do_test (void) +{ + TEST_CMPXCHG_LOOP (__int128_t) +} + +int +main (void) +{ + if (__builtin_cpu_supports ("cmpxchg16b")) + do_test (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4a.c b/gcc/testsuite/gcc.target/i386/pr126293-4a.c new file mode 100644 index 00000000000..add9a95bcb8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4a.c @@ -0,0 +1,25 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=x86-64 -m128bit-atomic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movq %rdi, %xmm0 +** movq %rsi, %xmm1 +** punpcklqdq %xmm1, %xmm0 +** movaps %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +_Atomic __uint128_t store; + +void +func (__uint128_t i) +{ + store = i; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4b.c b/gcc/testsuite/gcc.target/i386/pr126293-4b.c new file mode 100644 index 00000000000..12692798b96 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4b.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=diamondrapids" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** vmovq %rdi, %xmm1 +** vpinsrq \$1, %rsi, %xmm1, %xmm0 +** vmovdqa %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4c.c b/gcc/testsuite/gcc.target/i386/pr126293-4c.c new file mode 100644 index 00000000000..d84eb022d2b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4c.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=nehalem -mavx" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** vmovq %rdi, %xmm1 +** vpinsrq \$1, %rsi, %xmm1, %xmm0 +** vmovdqa %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4d.c b/gcc/testsuite/gcc.target/i386/pr126293-4d.c new file mode 100644 index 00000000000..fc847953584 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4d.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=znver1" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** vmovq %rdi, %xmm1 +** vpinsrq \$1, %rsi, %xmm1, %xmm0 +** vmovdqa %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4e.c b/gcc/testsuite/gcc.target/i386/pr126293-4e.c new file mode 100644 index 00000000000..783de4a823d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4e.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=yongfeng" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** vmovq %rdi, %xmm1 +** vpinsrq \$1, %rsi, %xmm1, %xmm0 +** vmovdqa %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4f.c b/gcc/testsuite/gcc.target/i386/pr126293-4f.c new file mode 100644 index 00000000000..0329e51f190 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4f.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=diamondrapids -mno-avx" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movq %rdi, %xmm0 +** pinsrq \$1, %rsi, %xmm0 +** movaps %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4g.c b/gcc/testsuite/gcc.target/i386/pr126293-4g.c new file mode 100644 index 00000000000..036f4b9b827 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4g.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=sandybridge -mno-avx" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movq %rdi, %xmm0 +** pinsrq \$1, %rsi, %xmm0 +** movaps %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4h.c b/gcc/testsuite/gcc.target/i386/pr126293-4h.c new file mode 100644 index 00000000000..fbe375b930b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4h.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=ivybridge -mno-avx" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movq %rdi, %xmm0 +** pinsrq \$1, %rsi, %xmm0 +** movaps %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4i.c b/gcc/testsuite/gcc.target/i386/pr126293-4i.c new file mode 100644 index 00000000000..47ed4472eef --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4i.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=znver1 -mno-avx" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movq %rdi, %xmm0 +** pinsrq \$1, %rsi, %xmm0 +** movaps %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4j.c b/gcc/testsuite/gcc.target/i386/pr126293-4j.c new file mode 100644 index 00000000000..1628319b5b5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4j.c @@ -0,0 +1,19 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=lujiazui" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movq %rsi, %rdx +** movl \$5, %ecx +** movq %rdi, %rsi +** movl \$store, %edi +** jmp __atomic_store_16 +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4k.c b/gcc/testsuite/gcc.target/i386/pr126293-4k.c new file mode 100644 index 00000000000..76a37927575 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4k.c @@ -0,0 +1,19 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=skylake -mno-cx16" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movq %rsi, %rdx +** movl \$5, %ecx +** movq %rdi, %rsi +** movl \$store, %edi +** jmp __atomic_store_16 +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4l.c b/gcc/testsuite/gcc.target/i386/pr126293-4l.c new file mode 100644 index 00000000000..4a80ed40efa --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4l.c @@ -0,0 +1,19 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=skylake -mno-sse" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movq %rsi, %rdx +** movl \$5, %ecx +** movq %rdi, %rsi +** movl \$store, %edi +** jmp __atomic_store_16 +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4m.c b/gcc/testsuite/gcc.target/i386/pr126293-4m.c new file mode 100644 index 00000000000..136d3dcdccf --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4m.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=grandridge" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** vmovq %rdi, %xmm1 +** vpinsrq \$1, %rsi, %xmm1, %xmm0 +** vmovdqa %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4n.c b/gcc/testsuite/gcc.target/i386/pr126293-4n.c new file mode 100644 index 00000000000..f0f92b429ce --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4n.c @@ -0,0 +1,19 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=skylake -mno-128bit-atomic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movq %rsi, %rdx +** movl \$5, %ecx +** movq %rdi, %rsi +** movl \$store, %edi +** jmp __atomic_store_16 +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4o.c b/gcc/testsuite/gcc.target/i386/pr126293-4o.c new file mode 100644 index 00000000000..7cdc62d26d9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4o.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=c86-4g-m8" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** vmovq %rdi, %xmm1 +** vpinsrq \$1, %rsi, %xmm1, %xmm0 +** vmovdqa %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4p.c b/gcc/testsuite/gcc.target/i386/pr126293-4p.c new file mode 100644 index 00000000000..c07073cf78c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4p.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=x86-64-v3" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** vmovq %rdi, %xmm1 +** vpinsrq \$1, %rsi, %xmm1, %xmm0 +** vmovdqa %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-4q.c b/gcc/testsuite/gcc.target/i386/pr126293-4q.c new file mode 100644 index 00000000000..3cd43041335 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-4q.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=x86-64-v4" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** vmovq %rdi, %xmm1 +** vpinsrq \$1, %rsi, %xmm1, %xmm0 +** vmovdqa %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +#include "pr126293-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126293-5.c b/gcc/testsuite/gcc.target/i386/pr126293-5.c new file mode 100644 index 00000000000..2f0794132c9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-5.c @@ -0,0 +1,25 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=x86-64 -m128bit-atomic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movdqa load\(%rip\), %xmm0 +** movaps %xmm0, -24\(%rsp\) +** movq -24\(%rsp\), %rax +** movq -16\(%rsp\), %rdx +** ret +** .cfi_endproc +**... +*/ + +_Atomic __uint128_t load; + +__uint128_t +func (void) +{ + return load; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126293-6.c b/gcc/testsuite/gcc.target/i386/pr126293-6.c new file mode 100644 index 00000000000..16a667fbd24 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-6.c @@ -0,0 +1,23 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=x86-64 -m128bit-atomic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movaps %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +typedef int vector __attribute__((vector_size (16))); +extern _Atomic vector store; + +void +func (vector i) +{ + store = i; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126293-7.c b/gcc/testsuite/gcc.target/i386/pr126293-7.c new file mode 100644 index 00000000000..0f5073ea985 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-7.c @@ -0,0 +1,23 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=x86-64 -m128bit-atomic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movdqa load\(%rip\), %xmm0 +** ret +** .cfi_endproc +**... +*/ + +typedef int vector __attribute__((vector_size (16))); +extern _Atomic vector load; + +vector +func (void) +{ + return load; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126293-8.c b/gcc/testsuite/gcc.target/i386/pr126293-8.c new file mode 100644 index 00000000000..53387873378 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-8.c @@ -0,0 +1,23 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=x86-64 -m128bit-atomic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movaps %xmm0, store\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +typedef float vector __attribute__((vector_size (16))); +extern _Atomic vector store; + +void +func (vector i) +{ + store = i; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126293-9.c b/gcc/testsuite/gcc.target/i386/pr126293-9.c new file mode 100644 index 00000000000..623498711f7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126293-9.c @@ -0,0 +1,23 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-additional-options "-O2 -fno-pic -std=c23 -march=x86-64 -m128bit-atomic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movdqa load\(%rip\), %xmm0 +** ret +** .cfi_endproc +**... +*/ + +typedef float vector __attribute__((vector_size (16))); +extern _Atomic vector load; + +vector +func (void) +{ + return load; +} -- 2.55.0
