Created
December 30, 2020 08:50
-
-
Save neunhoef/1ebbedbbd7867c42126e715ddaad261d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This program does not behave as intended: | |
#include <atomic> | |
#include <iostream> | |
int main() { | |
std::atomic<long double> x; | |
x.store(1.0); | |
long double tmp = 2.0; | |
bool worked = x.compare_exchange_weak(tmp, 3.0); | |
std::cout << "worked " << worked << " set tmp to " << tmp << std::endl; | |
std::atomic<double> x2; | |
x2.store(1.0); | |
double tmp2 = 2.0; | |
worked = x2.compare_exchange_weak(tmp2, 3.0); | |
std::cout << "worked " << worked << " set tmp to " << tmp2 << std::endl; | |
return 0; | |
} | |
I compile with | |
clang++-12 -std=c++17 atomiclongdoublecompareexchangeweak.cpp -o atomiclongdoublecompareexchangeweak -Wall -O0 -g -latomic | |
The output is: | |
worked 0 set tmp to 2 | |
worked 0 set tmp to 1 | |
The expected output is | |
worked 0 set tmp to 1 | |
worked 0 set tmp to 1 | |
My version of clang++-12 is: | |
% clang++-12 -v | |
Ubuntu clang version 12.0.0-++20201229052625+b76014a4f15a-1~exp1~20201229163322.268 | |
Target: x86_64-pc-linux-gnu | |
Thread model: posix | |
InstalledDir: /usr/bin | |
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/10 | |
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/8 | |
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9 | |
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/10 | |
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8 | |
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9 | |
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/10 | |
Candidate multilib: .;@m64 | |
Selected multilib: .;@m64 | |
The same problem occurs with clang++11 and other optimization levels. | |
The problem is that | |
std::atomic<long double>::compare_exchange_weak(long double& expected, | |
long double desired) | |
does not update `expected` as specified when the expected value is not | |
found. | |
Here are the libraries my program is linked against: | |
% ldd ./atomiclongdoublecompareexchangeweak | |
linux-vdso.so.1 (0x00007fffe5b79000) | |
libatomic.so.1 => /lib/x86_64-linux-gnu/libatomic.so.1 (0x00007f61dcb69000) | |
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f61dc988000) | |
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f61dc839000) | |
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f61dc81e000) | |
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f61dc62c000) | |
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f61dc609000) | |
/lib64/ld-linux-x86-64.so.2 (0x00007f61dcb9c000) | |
The problem seems to be that the atomic headers lead to the fact that in | |
the end the compiler intrinsic | |
__atomic_compare_exchange | |
is called for the 16 byte case. Unfortunately, I cannot easily find the | |
source code for this. In any case this function seems to misbehave | |
for the 16 byte case. I have traced the assembler code and this shows | |
the wrong behaviour. | |
I am happy to report this bug on llvm-bugs once I have access. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment