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
>Organization:
TNF
>Environment:
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
>Description:
NetBSD deliberately does not ship with libatomic rejecting its idea due to corner cases when it does not work reliably.
https://clang.llvm.org/docs/Toolchain.html#atomics-library
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
-mcx16
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.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/lto-wrapper
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=http://www.NetBSD.org/Misc/send-pr.html --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
e/amd64-x86_64/usr/src/destdir.amd64
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)
[...]
>How-To-Repeat:
$ cat test2.cpp
#include <atomic>
#include <cstdio>
int
main(int argc, char **argv)
{
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
puts("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 defined");
#else
puts("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 NOT defined");
#endif
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'
>Fix:
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