Files
gcc/libatomic/config
Xi Ruoyao 1b6d733c98 LoongArch: Don't mix lock-free and locking 16B atomics
As [1] says, we cannot mix up lock-free and locking atomics for one
object.  For example assume atom = (0, 0) initially, if we have a
locking "atomic" xor running on T0 and a lock-free store running on T1
concurrently:

       T0                    |       T1
-----------------------------+-------------------------------------
 acquire_lock                |
 t0 = atom[0]                |
 /* some CPU cycles */       | atom = (1, 1) /* lock-free atomic */
 t1 = atom[1]                |
 t0 ^= 1                     |
 t1 ^= 1                     |
 atom[0] = t0                |
 atom[1] = t1                |
 release_lock                |

we get atom = (0, 1), but the atomicity of xor and store should
guarantee that atom is either (0, 0) or (1, 1).

So, if we want to use a lock-free 16B atomic operation, we need both LSX
and SCQ even if that specific operation only needs one of them.  To make
things worse, one may link a TU compiled with -mlsx -mscq and another
without them together, then if we want to use the lock-free 16B atomic
operations in the former, we must make libatomic also use the lock-free
16B atomic operation for the latter so we need to add ifuncs for
libatomic, similar to the discussion about i386 vs. i486 in [1].

Implementing and building the ifuncs currently requires:

- Glibc, because the ifunc resolver interface is libc-specific
- Linux, because the HWCAP bit for LSX is kernel-specific
- A recent enough assembler at build time to recognize sc.q

So the approach here is: only allow 16B lock-free atomic operations in
the compiler if the criteria above is satisfied, and ensure libatomic to
use those lock-free operations on capable hardware (via ifunc unless
both LSX and SCQ are already enabled by the builder) if the compiler
allows 16B lock-free atomic.

[1]: https://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary

gcc/
	* configure.ac (HAVE_AS_16B_ATOMIC): Define if the assembler
	supports LSX and sc.q.
	* configure: Regenerate.
	* config.in: Regenerate.
	* config/loongarch/loongarch-opts.h (HAVE_AS_16B_ATOMIC):
	Defined to 0 if undefined yet.
	* config/loongarch/linux.h (HAVE_IFUNC_FOR_LIBATOMIC_16B):
	Define as HAVE_AS_16B_ATOMIC && OPTION_GLIBC.
	* config/loongarch/loongarch-protos.h
	(loongarch_16b_atomic_lock_free_p): New prototype.
	* config/loongarch/loongarch.cc
	(loongarch_16b_atomic_lock_free_p): Implement.
	* config/loongarch/sync.md (atomic_storeti_lsx): Require
	loongarch_16b_atomic_lock_free_p.
	(atomic_storeti): Likewise.
	(atomic_exchangeti_scq): Likewise.
	(atomic_exchangeti): Likewise.
	(atomic_compare_and_swapti): Likewise.
	(atomic_fetch_<amop_ti_fetch>ti_scq): Likewise.
	(atomic_fetch_<amop_ti_fetch>ti): Likewise.
	(ALL_SC): Likewise for TImode.
	(atomic_storeti_scq): Remove.

libatomic/

	* configure.ac (ARCH_LOONGARCH): New AM_CONDITIONAL.
	* Makefile.am (IFUNC_OPT): Separate the item from IFUNC_OPTIONS
	to allow using multiple options for an ISA variant.
	(libatomic_la_LIBADD): Add *_16_1_.lo for LoongArch.
	(IFUNC_OPTIONS): Build *_16_1_.lo for LoongArch with -mlsx and
	-mscq.
	* configure: Regenerate.
	* Makefile.in: Regenerate.
	* configure.tgt (try_ifunc): Set to yes for LoongArch if the
	compiler can produce lock-free 16B atomic with -mlsx -mscq.
	* config/loongarch/host-config.h: Implement ifunc selector.
2025-11-13 23:22:18 +08:00
..
2025-01-02 11:59:57 +01:00
2025-01-02 11:59:57 +01:00
2025-01-02 11:59:57 +01:00
2025-01-02 11:59:57 +01:00
2025-01-02 11:59:57 +01:00
2025-01-02 11:59:57 +01:00
2025-01-02 11:59:57 +01:00