NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

toolchain/54428: GCC broken with std::atomic<__int128_t> with -mcx16

>Number:         54428
>Category:       toolchain
>Synopsis:       GCC broken with std::atomic<__int128_t> with -mcx16
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    toolchain-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Aug 01 18:15:00 +0000 2019
>Originator:     Kamil Rytarowski
>Release:        NetBSD/amd64 8.99.42
NetBSD rugged 8.99.42 NetBSD 8.99.42 (GENERIC) #2: Sat Jun  1 22:52:15 CEST 2019  root@chieftec:/public/netbsd-root/sys/arch/amd64/compile/GENERIC amd64
NetBSD deliberately does not ship with libatomic rejecting its idea due to corner cases when it does not work reliably.

This design decision breaks std::atomic<__int128_t> on NetBSD/amd64 with CPU supporting LOCK CMPXCHG16B, because GCC translates __atomic calls to libatomic library calls always.

This does not happen with Clang as it builds a functional code.

$ man gcc

           This option enables GCC to generate "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 __sync Builtins.  However, for
           __atomic Builtins operating on 128-bit integers, a library call is
           always used.

$ gcc -v
Using built-in specs.
Target: x86_64--netbsd
Configured with: /usr/src/tools/gcc/../../external/gpl3/gcc/dist/configure --target=x86_64--netbsd --enable-long-long --enable-threads --with-bugurl= --with-pkgversion='NetBSD nb3 20190319' --with-system-zlib --without-isl --enable-__cxa_atexit --enable-libstdcxx-time=rt --enable-libstdcxx-threads --with-diagnostics-color=auto-if-env --with-tune=nocona --with-default-libstdcxx-abi=new --with-mpc-lib=/var/obj/mknative/amd64-x86_64/usr/src/external/lgpl3/mpc/lib/libmpc --with-mpfr-lib=/var/obj/mknative/amd64-x86_64/usr/src/external/lgpl3/mpfr/lib/libmpfr --with-gmp-lib=/var/obj/mknative/amd64-x86_64/usr/src/external/lgpl3/gmp/lib/libgmp --with-mpc-include=/usr/src/external/lgpl3/mpc/dist/src --with-mpfr-include=/usr/src/external/lgpl3/mpfr/dist/src --with-gmp-include=/usr/src/external/lgpl3/gmp/lib/libgmp/arch/x86_64 --enable-tls --disable-multilib --disable-libstdcxx-pch --build=x86_64--netbsd --host=x86_64--netbsd --with-sysroot=/var/obj/mknativ
Thread model: posix
gcc version 7.4.0 (nb3 20190319)

$ clang -v
clang version 7.0.1 (tags/RELEASE_701/final)
Target: x86_64-unknown-netbsd8.99
Thread model: posix
InstalledDir: /usr/pkg/bin

$ objdump -d ./a.out
0000000000400a50 <_ZNKSt6atomicInE4loadESt12memory_order>: // std::atomic<__int128>::load(std::memory_order) const
  400ac3:       f0 48 0f c7 0e          lock cmpxchg16b (%rsi)
$ cat test2.cpp
#include <atomic>

#include <cstdio>

main(int argc, char **argv)
	puts("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 defined");
	puts("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 NOT defined");

	std::atomic<__int128_t> val;

	return val + 1;

$ g++ -mcx16 test2.cpp
ld: /var/tmp//cc6DZLsM.o: in function `std::atomic<__int128>::load(std::memory_order) const':
test2.cpp:(.text._ZNKSt6atomicInE4loadESt12memory_order[_ZNKSt6atomicInE4loadESt12memory_order]+0x2d): undefined reference to `__atomic_load_16'
1. Revisit the libatomic statement and ship it to those who are aware about its corner cases.

2. Patch GCC to support 128bit std::atomic without libatomic and reuse lock cmpxchg16b on x86_64.

Home | Main Index | Thread Index | Old Index