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.