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 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, with SEE2 and CMPXCHG16B enabled.

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_function_specific_save): Save
x_ix86_128bit_atomic.
(ix86_function_specific_restore): Restore x_ix86_128bit_atomic.
(ix86_option_override_internal): Turn off -m128bit-atomic when
CMPXCHG16B is disabled and turn on CMPXCHG16B when -m128bit-atomic
is enabled.  Enable -m128bit-atomic by default if supported by
the targeting processor with SEE2 and CMPXCHG16B enabled.
* config/i386/i386.opt (x_ix86_128bit_atomic): New TargetSave.
(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: 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-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.


-- 
H.J.
From e41de437760b576bde1cb3a2b9e4aa08f90e47c8 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <[email protected]>
Date: Fri, 17 Jul 2026 08:35:34 +0800
Subject: [PATCH] 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 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, with SEE2 and CMPXCHG16B enabled.

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_function_specific_save): Save
	x_ix86_128bit_atomic.
	(ix86_function_specific_restore): Restore x_ix86_128bit_atomic.
	(ix86_option_override_internal): Turn off -m128bit-atomic when
	CMPXCHG16B is disabled and turn on CMPXCHG16B when -m128bit-atomic
	is enabled.  Enable -m128bit-atomic by default if supported by
	the targeting processor with SEE2 and CMPXCHG16B enabled.
	* config/i386/i386.opt (x_ix86_128bit_atomic): New TargetSave.
	(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: 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-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.

Signed-off-by: H.J. Lu <[email protected]>
---
 gcc/common/config/i386/i386-cpuinfo.h       | 126 ++++++++++++++++++++
 gcc/config/i386/i386-options.cc             |  53 ++++++++
 gcc/config/i386/i386.opt                    |   8 ++
 gcc/config/i386/i386.opt.urls               |   3 +
 gcc/config/i386/sync.md                     |  49 ++++++++
 gcc/doc/invoke.texi                         |  11 +-
 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-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-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 ++++
 42 files changed, 1043 insertions(+), 1 deletion(-)
 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-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-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..5c87b1df01f 100644
--- a/gcc/config/i386/i386-options.cc
+++ b/gcc/config/i386/i386-options.cc
@@ -730,6 +730,7 @@ ix86_function_specific_save (struct cl_target_option *ptr,
   ptr->x_ix86_tune_memcpy_strategy = opts->x_ix86_tune_memcpy_strategy;
   ptr->x_ix86_tune_memset_strategy = opts->x_ix86_tune_memset_strategy;
   ptr->x_ix86_tune_no_default = opts->x_ix86_tune_no_default;
+  ptr->x_ix86_128bit_atomic = opts->x_ix86_128bit_atomic;
 
   /* The fields are char but the variables are not; make sure the
      values fit in the fields.  */
@@ -879,6 +880,7 @@ ix86_function_specific_restore (struct gcc_options *opts,
   opts->x_ix86_tune_memcpy_strategy = ptr->x_ix86_tune_memcpy_strategy;
   opts->x_ix86_tune_memset_strategy = ptr->x_ix86_tune_memset_strategy;
   opts->x_ix86_tune_no_default = ptr->x_ix86_tune_no_default;
+  opts->x_ix86_128bit_atomic = ptr->x_ix86_128bit_atomic;
   ix86_tune_cost = processor_cost_table[ix86_tune];
   /* TODO: ix86_cost should be chosen at instruction or function granularity
      so for cold code we use size_cost even in !optimize_size compilation.  */
@@ -2219,6 +2221,22 @@ ix86_option_override_internal (bool main_args_p,
   SET_OPTION_IF_UNSET (opts, opts_set, flag_ms_extensions,
 		       (MS_ABI == DEFAULT_ABI));
 
+  if (TARGET_CX16_P (opts_set->x_ix86_isa_flags2))
+    {
+      /* Turn off -m128bit-atomic when CMPXCHG16B is disabled.  */
+      if (!TARGET_CX16_P (opts->x_ix86_isa_flags2))
+	opts->x_ix86_128bit_atomic = 0;
+    }
+  else
+    {
+      /* Enable CMPXCHG16B when -m128bit-atomic is enabled.  */
+      if (opts->x_ix86_128bit_atomic)
+	{
+	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_CX16;
+	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_CX16;
+	}
+    }
+
   if (opts_set->x_ix86_cmodel)
     {
       switch (opts->x_ix86_cmodel)
@@ -2303,6 +2321,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 +2361,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 +2553,32 @@ ix86_option_override_internal (bool main_args_p,
       XDELETEVEC (s);
     }
 
+  /* Enable -m128bit-atomic 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,
+     with SSE2 and CMPXCHG16B enabled.  */
+  if (!opts_set->x_ix86_128bit_atomic
+      && TARGET_CX16_P (opts->x_ix86_isa_flags2)
+      && ((TARGET_AVX_P (opts->x_ix86_isa_flags)
+	  && (ix86_vendor == VENDOR_INTEL
+	      || ix86_vendor == VENDOR_AMD
+	      || ix86_vendor == VENDOR_HYGON
+	      || ix86_vendor == VENDOR_ZHAOXIN))
+	  || (TARGET_SSE2_P (opts->x_ix86_isa_flags)
+	      && ((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)))))
+    opts->x_ix86_128bit_atomic = 1;
+
   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.opt b/gcc/config/i386/i386.opt
index 158090c2bde..22f590a65c2 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -188,6 +188,10 @@ const char *x_ix86_tune_memset_strategy
 TargetSave
 int x_ix86_tune_no_default
 
+;; -m128bit-atomic
+TargetSave
+int x_ix86_128bit_atomic
+
 ;; -mveclibabi=
 TargetVariable
 enum ix86_veclibabi ix86_veclibabi_type = ix86_veclibabi_type_none
@@ -1213,6 +1217,10 @@ mdirect-extern-access
 Target Var(ix86_direct_extern_access) Init(1)
 Do not use GOT to access external symbols.
 
+m128bit-atomic
+Target Var(ix86_128bit_atomic)
+Generate cmpxchg16b, 128-bit atomic vector loads and stores.
+
 -param=x86-stlf-window-ninsns=
 Target Joined UInteger Var(x86_stlf_window_ninsns) Init(64) Param
 Instructions number above which STFL stall penalty can be compensated.
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..c67b5f2b687 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_64BIT && TARGET_SSE2 && ix86_128bit_atomic"
+{
+  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_64BIT && TARGET_SSE2 && ix86_128bit_atomic"
+  "#"
+  "&& 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_64BIT && TARGET_SSE2 && ix86_128bit_atomic"
+{
+  /* 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_64BIT && TARGET_SSE2 && ix86_128bit_atomic"
+  "#"
+  "&& 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..65a4a5eb711 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
@@ -37278,6 +37278,15 @@ 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
+@item -m128bit-atomic
+Generate cmpxchg16b, 128-bit atomic vector load and store instructions.
+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
+is enabled by default if supported by the targeting processor with
+SEE2 and CMPXCHG16B enabled.
+
 @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-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-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

Reply via email to