Skip to content

LLVM is unable to fully optimize out std::vector allocation with libc++Β #116092

@zygoloid

Description

@zygoloid

Testcase:

#include <vector>
void f(std::vector<char> v) {
    std::vector<char> v2 = v;
}

With clang -stdlib=libstdc++, we get this:

f(std::vector<char, std::allocator<char>>):
        mov     rax, qword ptr [rdi + 8]
        cmp     rax, qword ptr [rdi]
        sete    al
        setns   cl
        or      cl, al
        je      .LBB0_2
        ret
.LBB0_2:
        push    rax
        call    std::__throw_bad_alloc()@PLT

(The branch and throw is a bit sad, but I suppose LLVM has no way to know that v's existing size doesn't exceed vector::max_size().)

GCC gives a similar result:

f(std::vector<char, std::allocator<char> >):
        mov     rax, QWORD PTR [rdi]
        cmp     QWORD PTR [rdi+8], rax
        je      .L1
        js      .L10
.L1:
        ret
.L10:
        sub     rsp, 8
        call    std::__throw_bad_alloc()

But with clang -stdlib=libc++, we get this instead:

f(std::__1::vector<char, std::__1::allocator<char>>):
        push    rbx
        sub     rsp, 32
        xorps   xmm0, xmm0
        movaps  xmmword ptr [rsp], xmm0
        mov     qword ptr [rsp + 16], 0
        mov     rax, qword ptr [rdi + 8]
        cmp     rax, qword ptr [rdi]
        sete    al
        setns   cl
        or      cl, al
        je      .LBB0_1
        add     rsp, 32
        pop     rbx
        ret
.LBB0_1:
        mov     rdi, rsp
        call    std::__1::vector<char, std::__1::allocator<char>>::__throw_length_error[abi:ne200000]() const
        mov     rbx, rax
        mov     rdi, qword ptr [rsp]
        test    rdi, rdi
        je      .LBB0_5
        mov     qword ptr [rsp + 8], rdi
        mov     rsi, qword ptr [rsp + 16]
        sub     rsi, rdi
        call    operator delete(void*, unsigned long)@PLT
.LBB0_5:
        mov     rdi, rbx
        call    _Unwind_Resume@PLT

.L.str:
        .asciz  "vector"

DW.ref.__gxx_personality_v0:
        .quad   __gxx_personality_v0

The extra code here is attempting to deallocate the data pointer within v2 along the exception path. But that code is all unreachable -- we first branch on whether the pointer is null, which it is, because the only store to it is the memset-to-zero at the start of the function. But LLVM doesn't seem to notice that.

Metadata

Metadata

Assignees

No one assigned

    Labels

    libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.missed-optimization

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions