Hi
I'm looking at a Valgrind issue. Full details here
https://bugs.kde.org/show_bug.cgi?id=472329
This code
void foo(std::optional<int64_t> f) {
std::cout << (f ? *f : 0) << std::endl;
std::set<int64_t> test;
test.emplace(0);
auto it{test.begin()};
while (it != test.end()) {
int64_t b{*it};
// Valgrind error on next line
if (f && *f != b) {
[snip]
int main() { foo(std::nullopt); }
generates (using g++ 12.2 on FreeBSD 13.2 amd64)
movq 40(%rbx), %rax
Error on next line:
cmpq %r14, %rax # f, SR.252
je .L47
cmpb $0, -97(%rbp) #, %sfp
jne .L69
Unless I'm completely mistaken cmpq %r14, %rax is the quadword
comparison of *f != b and cmpb $0, -97(%rbp) is the
std::optional::operator bool() comparison with 0. That means that g++
has transposed the order of evaluation.
The first cmpq/je generates a
==49599== Conditional jump or move depends on uninitialised value(s)
Valgrind has machinery to detect transformations like this and to
convert them back into bit accurate bitwise ands.
However, Valgrind thinks that these transpositions can't be done when
there are potentially trapping memory loads like *f.
So who is right? Is this a safe transformation?
Regards
Paul