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