https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94294
Bug ID: 94294
Summary: [missed optimization] new+delete of unused local
string not removed
Product: gcc
Version: 10.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
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 second of two apparent bugs, following bug 94293. They both
manifest 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 how the allocation and de-allocation are not
elided/optimized-away, even though the std::string variable is local and
unused.
AFAICT, g++ is not required to do this. And, in fact, clang++ doesn't do this
with its libc++. cppreference says that, starting in C++14,
> New-expressions are allowed to elide or combine allocations made
> through replaceable allocation functions. In case of elision, the
> storage may be provided by the compiler without making the call to
> an allocation function (this also permits optimizing out unused
> new-expression)
and this is, indeed, the case of an unused new-expression. Well,
eventually-unused.
Note: I suppose it's theoretically possible that this bug only manifests
because bug 94293 prevents the allocated space from being recognized as
unused; but I can't tell whether that's the case.