[Bug c++/78778] New: non-atomic load moved to before atomic load with std::memory_order_acquire
erik at rigtorp dot se
gcc-bugzilla@gcc.gnu.org
Mon Dec 12 16:37:00 GMT 2016
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78778
Bug ID: 78778
Summary: non-atomic load moved to before atomic load with
std::memory_order_acquire
Product: gcc
Version: 5.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: erik at rigtorp dot se
Target Milestone: ---
Compiling this with GCC 5.1 and up with -O2 or higher for x86_64:
#include <atomic>
#include <cstdint>
int seqlock_load(std::atomic<std::size_t> &seq, double &value) {
double copy;
std::size_t seq0, seq1;
do {
seq0 = seq.load(std::memory_order_acquire);
copy = value;
seq1 = seq.load(std::memory_order_acquire);
} while (seq0 != seq1 || seq0 & 1);
return copy;
}
Yields the following assembly:
seqlock_load(std::atomic<unsigned long>&, double&):
movsd xmm0, QWORD PTR [rsi] // copy = value;
.L3:
mov rdx, QWORD PTR [rdi] // seq0 = seq.load(...)
mov rax, QWORD PTR [rdi] // seq1 = seq.load(...)
cmp rax, rdx
jne .L3
test al, 1
jne .L3
cvttsd2si eax, xmm0
ret
In GCC Explorer: https://godbolt.org/g/0X8nUC
As I understand this operation:
copy = value;
Is guaranteed to happen after:
seq0 = seq.load(std::memory_order_acquire);
But it's moved to before the loop. A valid optimization would be to move it
after the loop, but not before. This came up when I was implementing seqlocks:
https://github.com/rigtorp/Seqlock
More information about the Gcc-bugs
mailing list