Files
gcc-reflection/libatomic/Makefile.am
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

192 lines
6.8 KiB
Makefile

## Copyright (C) 2012-2025 Free Software Foundation, Inc.
## Contributed by Richard Henderson <rth@redhat.com>.
##
## This file is part of the GNU Atomic Library (libatomic).
##
## Libatomic is free software; you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 3 of the License, or
## (at your option) any later version.
##
## Libatomic is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for
## more details.
##
## Under Section 7 of GPL version 3, you are granted additional
## permissions described in the GCC Runtime Library Exception, version
## 3.1, as published by the Free Software Foundation.
##
## You should have received a copy of the GNU General Public License and
## a copy of the GCC Runtime Library Exception along with this program;
## see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
## <http://www.gnu.org/licenses/>.
ACLOCAL_AMFLAGS = -I .. -I ../config
SUBDIRS = testsuite
## May be used by toolexeclibdir.
gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
config_path= @config_path@
search_path = $(addprefix $(top_srcdir)/config/, $(config_path)) \
$(top_srcdir) $(top_builddir)
vpath % $(strip $(search_path))
DEFAULT_INCLUDES = $(addprefix -I, $(search_path))
AM_CFLAGS = $(XCFLAGS)
AM_CCASFLAGS = $(XCFLAGS)
AM_LDFLAGS = $(XLDFLAGS) $(SECTION_LDFLAGS) $(OPT_LDFLAGS)
toolexeclib_LTLIBRARIES = libatomic.la
noinst_LTLIBRARIES = libatomic_convenience.la
if LIBAT_BUILD_VERSIONED_SHLIB
if LIBAT_BUILD_VERSIONED_SHLIB_GNU
libatomic_version_script = -Wl,--version-script,$(top_srcdir)/libatomic.map
libatomic_version_dep = $(top_srcdir)/libatomic.map
endif
if LIBAT_BUILD_VERSIONED_SHLIB_SUN
libatomic_version_script = -Wl,-M,libatomic.map-sun
libatomic_version_dep = libatomic.map-sun
libatomic.map-sun : $(top_srcdir)/libatomic.map \
$(top_srcdir)/../contrib/make_sunver.pl \
$(libatomic_la_OBJECTS) $(libatomic_la_LIBADD)
perl $(top_srcdir)/../contrib/make_sunver.pl \
$(top_srcdir)/libatomic.map \
$(libatomic_la_OBJECTS) $(libatomic_la_LIBADD) \
> $@ || (rm -f $@ ; exit 1)
endif
else
libatomic_version_script =
libatomic_version_dep =
endif
libatomic_version_info = -version-info $(libtool_VERSION)
if ENABLE_DARWIN_AT_RPATH
libatomic_darwin_rpath = -Wc,-nodefaultrpaths
libatomic_darwin_rpath += -Wl,-rpath,@loader_path
endif
libatomic_la_LDFLAGS = $(libatomic_version_info) $(libatomic_version_script) \
-Wc,-fno-link-libatomic $(lt_host_flags) $(libatomic_darwin_rpath)
SIZES = @SIZES@
if PARTIAL_VXWORKS
libatomic_la_SOURCES = fenv.c fence.c flag.c
else
libatomic_la_SOURCES = gload.c gstore.c gcas.c gexch.c glfree.c lock.c init.c \
fenv.c fence.c flag.c
SIZEOBJS = load store cas exch fadd fsub fand fior fxor fnand tas
EXTRA_libatomic_la_SOURCES = $(addsuffix _n.c,$(SIZEOBJS))
libatomic_la_DEPENDENCIES = $(libatomic_la_LIBADD) $(libatomic_version_dep)
## And now our custom target patterns that allow us not to have tons of
## extra source files hanging about. Unfortunately, the complex relation
## between source and object filenames doesn't allow us to add an explicit
## dependency here. Fortunately that doesn't matter since auto-generated
## dependencies do the job just as well:
-include $(wildcard $(DEPDIR)/*.Ppo)
## Naming pattern: base_n_i_.lo
##
## N size of data
## I IFUNC alternative, index beginning at 1.
##
## The trailing _ in the output object file name is required to differentiate
## these objects from those which should be compiled normally. We can only
## have one stem in the implicit rule.
empty =
space = $(empty) $(empty)
PAT_SPLIT = $(subst _,$(space),$(*F))
PAT_BASE = $(word 1,$(PAT_SPLIT))
PAT_N = $(word 2,$(PAT_SPLIT))
PAT_S = $(word 3,$(PAT_SPLIT))
IFUNC_DEF = -DIFUNC_ALT=$(PAT_S)
IFUNC_OPT = $(subst |,$(space),$(word $(PAT_S),$(IFUNC_OPTIONS)))
@AMDEP_TRUE@M_DEPS = -MT $@ -MD -MP -MF $(DEPDIR)/$(@F).Ppo
@AMDEP_FALSE@M_DEPS =
M_SIZE = -DN=$(PAT_N)
M_IFUNC = $(if $(PAT_S),$(IFUNC_DEF) $(IFUNC_OPT))
M_FILE = $(PAT_BASE)_n.c
# The lack of explicit dependency on the source file means that VPATH cannot
# work properly. Instead, perform this operation by hand. First, collect a
# list of all .c files in the search path.
all_c_files := $(foreach dir,$(search_path),$(wildcard $(dir)/*.c))
# Then sort through them to find the one we want, and select the first.
M_SRC = $(firstword $(filter %/$(M_FILE), $(all_c_files)))
%_.lo: Makefile
$(LTCOMPILE) $(M_DEPS) $(M_SIZE) $(M_IFUNC) -c -o $@ $(M_SRC)
## Include all of the sizes in the "normal" set of compilation flags.
libatomic_la_LIBADD = $(foreach s,$(SIZES),$(addsuffix _$(s)_.lo,$(SIZEOBJS)))
## On a target-specific basis, include alternates to be selected by IFUNC.
if HAVE_IFUNC
if ARCH_AARCH64_LINUX
IFUNC_OPTIONS = -march=armv8-a+lse
libatomic_la_LIBADD += $(foreach s,$(SIZES),$(addsuffix _$(s)_1_.lo,$(SIZEOBJS)))
endif
if ARCH_ARM_LINUX
IFUNC_OPTIONS = -march=armv7-a+fp -DHAVE_KERNEL64
libatomic_la_LIBADD += $(foreach s,$(SIZES),$(addsuffix _$(s)_1_.lo,$(SIZEOBJS)))
libatomic_la_LIBADD += $(addsuffix _8_2_.lo,$(SIZEOBJS))
libatomic_la_LIBADD += tas_1_2_.lo
endif
if ARCH_I386
IFUNC_OPTIONS = -march=i586
libatomic_la_LIBADD += $(addsuffix _8_1_.lo,$(SIZEOBJS))
endif
if ARCH_X86_64
IFUNC_OPTIONS = -mcx16 -mcx16
libatomic_la_LIBADD += $(addsuffix _16_1_.lo,$(SIZEOBJS)) \
$(addsuffix _16_2_.lo,$(SIZEOBJS))
endif
if ARCH_LOONGARCH
IFUNC_OPTIONS = -mlsx|-mscq
libatomic_la_LIBADD += $(addsuffix _16_1_.lo,$(SIZEOBJS))
endif
endif
if ARCH_AARCH64_LINUX
libatomic_la_SOURCES += atomic_16.S
endif
endif
libatomic_convenience_la_SOURCES = $(libatomic_la_SOURCES)
libatomic_convenience_la_LIBADD = $(libatomic_la_LIBADD)
# Amend the automake generated all-multi rule to guarantee that all-multi
# is not run in parallel with the %_.lo rules which generate $(DEPDIR)/*.Ppo
# makefile fragments to avoid broken *.Ppo getting included into the Makefile
# when it is reloaded during the build of all-multi.
all-multi: $(libatomic_la_LIBADD)
# Copy built libatomic library to $build/gcc so it's easier to locate,
# similar to libgcc.
#
# FIXME: libtool --mode=install also ends up copying libatomic.la in $gcc_objdir,
# which (somehow) ends up adding $gcc_objdir to RPATH for libraries that get
# built after libatomic, which makes RPATH insecure. Removing libatomic.la
# from $gcc_objdir seems to fix the issue.
gcc_objdir = `pwd`/$(MULTIBUILDTOP)../../gcc/
all-local: libatomic.la
$(LIBTOOL) --mode=install $(INSTALL_DATA) libatomic.la $(gcc_objdir)$(MULTISUBDIR)/
rm $(gcc_objdir)$(MULTISUBDIR)/libatomic.la
# target overrides
-include $(tmake_file)
include $(top_srcdir)/../multilib.am