https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96945
Bug ID: 96945 Summary: optimizations regression when defaulting copy constructor Product: gcc Version: 10.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: federico.kircheis at gmail dot com Target Milestone: --- While toying with a piece of code, I've noticed that the code did not get optimized as expected. All snippets where compiled with -O3. A) ---- #include <vector> struct c { }; void foo(){ std::vector<c> vi = {c(),c(),c()}; } ---- gets compiled to: https://godbolt.org/z/s7YaEf ---- foo(): sub rsp, 24 mov edi, 3 call operator new(unsigned long) mov esi, 3 mov rdi, rax movzx eax, WORD PTR [rsp+13] mov WORD PTR [rdi], ax movzx eax, BYTE PTR [rsp+15] mov BYTE PTR [rdi+2], al add rsp, 24 jmp operator delete(void*, unsigned long) ---- Adding and defaulting the constructors produces even more optimized code (the whole vector is optimized out(!): https://godbolt.org/z/E4GT9x B) ---- #include <vector> struct c { c() = default; c(const c&) =default; c(c&&) = default; }; void foo(){ std::vector<c> vi = {c(),c(),c()}; } ---- ---- foo(): ret ---- Adding and defaulting the constructors, except the move constructor produces the same code as A): https://godbolt.org/z/ch71fb B) ---- #include <vector> struct c { c() = default; c(const c&) =default; c(c&&) = default; }; void foo(){ std::vector<c> vi = {c(),c(),c()}; } ---- If the copy or default constructor is implemented and not defaulted, then the code is optimized as B): https://godbolt.org/z/v8E37b, https://godbolt.org/z/v3EY69, #include <vector> struct c { c() {}; }; void foo(){ std::vector<c> vi = {c(),c(),c()}; } C) ---- #include <vector> struct c { c() = default; c(const c&) {}; }; void foo(){ std::vector<c> vi = {c(),c(),c()}; } ---- D) ---- #include <vector> struct c { c() = default; c(const c&) {}; c(c&&) = default; }; void foo(){ std::vector<c> vi = {c(),c(),c()}; } ---- E) ---- #include <vector> struct c { c() {} }; void foo(){ std::vector<c> vi = {c(),c(),c()}; } ---- While ideally the code for those cases is equivalent (as c has no state and all snippets are functionally equivalent), I would have expected the class with compiler-defined operators have the best codegen, followed by the class with defaulted operators, and last the class with a non-defaulted implementation. Strangely all constructor calls of `c` are always optimized away, but depending how the class is defined g++ does or does not optimize the whole vector away.