https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100746

            Bug ID: 100746
           Summary: NRVO should not introduce aliasing
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: antoshkka at gmail dot com
  Target Milestone: ---

Consider the example:

struct NrvoPassed {
    NrvoPassed() = default;
    NrvoPassed(const NrvoPassed&);
    NrvoPassed(NrvoPassed&&);

    int i = 0;
};

auto test(int* data) {
    NrvoPassed x;
    *data = 3;
    if (x.i != 0) __builtin_abort();
    return x;
}


Resulting assembly contains call to `abort`:

test(int*):
  mov DWORD PTR [rdi], 0
  mov DWORD PTR [rsi], 3
  mov edx, DWORD PTR [rdi]
  test edx, edx
  jne .L3
  mov rax, rdi
  ret
test(int*) [clone .cold]:
.L3:
  push rax
  call abort

Optimizer thinks that the value of `x.i` is aliased by `data`, however `data`
is a local variable and it's address could not leak before the object is
constructed.

Some other compilers already have the proposed optimization:
https://godbolt.org/z/aqdveadnE

Adding `__restrict` to `data` fixes the codegen:

test2(int*):
  mov DWORD PTR [rdi], 0
  mov rax, rdi
  mov DWORD PTR [rsi], 3
  ret

Probably `__restrict` should be always added to the storage address passed for
NRVO.

Reply via email to