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.

Reply via email to