https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94293
Bug ID: 94293 Summary: [missed optimization] Useless statements populating local string not removed Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: eyalroz at technion dot ac.il Target Milestone: --- (Relevant Godbolt: https://godbolt.org/z/GygbjZ) This is the first of two apparent bugs manifesting when compiling the following program: #include <string> int bar() { struct poor_mans_pair { int first; std::string second; }; poor_mans_pair p { 123, "Hey... no small-string optimization for me please!" }; return p.first; } For x86_64, this would ideally compile into: bar(): mov eax, 123 ret but when compiling this with GCC 10.0.1 20200322 (or GCC 9.x etc.), we get assembly which calls operator new[](), populates the string, calls operator delete[](), then returns 123: bar(): sub rsp, 8 mov edi, 51 call operator new(unsigned long) movdqa xmm0, XMMWORD PTR .LC0[rip] mov esi, 51 mov rdi, rax movups XMMWORD PTR [rax], xmm0 movdqa xmm0, XMMWORD PTR .LC1[rip] movups XMMWORD PTR [rax+16], xmm0 movdqa xmm0, XMMWORD PTR .LC2[rip] movups XMMWORD PTR [rax+32], xmm0 mov eax, 8549 mov WORD PTR [rdi+48], ax mov BYTE PTR [rdi+50], 0 call operator delete(void*, unsigned long) mov eax, 123 add rsp, 8 ret .LC0: .quad 7935393319309894984 .quad 3273110194895396975 .LC1: .quad 8007513861377913971 .quad 8386118574366356592 .LC2: .quad 2338053640980164457 .quad 8314037903514690925 This bug report is about the population of the string, i.e. let's ignore the question of whether any memory should be allocated at all. g++ should be aware that the string has no visibility outside `bar()` (except through access using raw arbitrary memory addresses from another while `bar()` is executing). Also, IANALL, even if the allocation can be considered observable behavior which needs to be maintained - values at that memory location, which may transiently be present, do not constitute such behavior. Why even set those values, therefore, when they are not used? At least these string constants and population statements should be optimized away, into something like (hand-written assembly): bar(): sub rsp, 8 mov edi, 51 call operator new(unsigned long) mov rdi, rax mov esi, 51 call operator delete(void*, unsigned long) mov eax, 123 add rsp, 8 ret