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

Reply via email to