<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/116092>116092</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            LLVM is unable to fully optimize out `std::vector` allocation with libc++
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            libc++
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          zygoloid
      </td>
    </tr>
</table>

<pre>
    [Testcase](https://godbolt.org/z/GGjW199nn):
```c++
#include <vector>
void f(std::vector<char> v) {
    std::vector<char> v2 = v;
}
```

With `clang -stdlib=libstdc++`, we get this:
```asm
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:
```asm
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:
```asm
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.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0V01v47wR_jX0ZRBDomzHPvgQ282iQIq-XaTNUaDEscWUIrXkyHby6wvS8pecZLftu4EQweTMcD4ePjMS3quNQZyz8YKNVwPRUmXd_P1tY7VVclBY-Rb2ntFTKTyy8YrxaUXUeJY9MP7I-OPGysJqGlq3YfzxnfHHb99eX9LZzBjGZ0EsWbHkgU2Sw1MyvgjPYZVnypS6lQgsW26xJOtY9pfD5tYqCWvGp55ksJM9HAWWZSWCHGwZnwG776wBAHwhy4FlK9iy7Hj4_arnW_cz_n9RVEHwVwuzgTtPUquCZSutCk_yGMUkYXwJO4QNElCl_G3AwteHlS9C4cuz40JrW4or38NzkUvo_mq7BSf2QfvHzjoJDTlg44WTChhfwDTU60qjrJv4_kTrLO-RMAgKfW3AIxkfDPXWresO0MFuX-sVYfi0WCQ5v153SIeF424_wqb11dHf60CE1ueU5TlVzu7yQsg8po_xaUjYKPnj6fnjGvPpc4VQOGHKCoSREC2A8iCgUAReyBBJ0RL8FXzbNNYjPD39629QCQ_Gwk68AVn4t7E7oEpQwMo24uHeA-6VJ2U24NU7grToDeP3BLgvEWUU7eof3K_FPg-CndeTZBheF1j8tlzCRm0xOOdVrbRw4NC3mn4L3KCPtwC0C9j84-Xv31fwx_P3G9j0YHYjyBcRk3x5UdFXPCgNn9IeavxpIznCJL2ByAWG0uS869visO2bcNz0f4HP5-SwaAl2nxPEp-wAynhCIX-1bHme_qx-J5Ff543TrSp6t6qXtKx3XffWNaEm-7qOgcV3n5FEENnX9RW1-KYr-4cq8f2jpxAZLJ10ep8o_Sb2O5Md_tkM2MO4kPKrjDe28_hUqR5l3t6HU2rCdVtGw19C__8G2NUV0mg2VOXonHVsvBCFYtmDQZ6Ev8P4EFp2aY2nPrkU-2ti-DigPk5uqkbo6RS9VDd16DglZG_8X0DxRFx9kyf__If-XeD4k7v2saexTgFXDbqQdJCokUKPCHMR4w9BqzVxgJOgrdn0Ot4xxJ8BpE8C8eD8n2anjMy_o29rvGqknfGhJ3djeyh8qd6Bcd7hifNLrdXL0OF6mOeb_T5v0HlrhFb0lm-TW1M_WiHhQ9GPeDl0c9yTE1BaiVChw9jMibBuYismCxI7DCNQhSAFCWisMoQu0rkysTVzNklAhJRGsdC0G1LWQCOoGkIg_9jx40nhEK2hNQ5FWYlCI9zdBc5fK-fpOGFYA7sKqUIXTR4PVR5MqyNj7CpVVqAIlI-DB5ai9Qc_rdFv4Mk6DEFEkbjOJkmNtUdik-SO7N07OguC4p4n4QjsOv5Yt6YMARx8j1PMeSbxiHWwayypEmNkw4GcZ3KWzcQA5-l9lo75KB3zQTXPpsVoNhOY8TTJZCKn48mEi2xSYiZwWiYDNecJH6VpmqXT8XjMh5PRWkzXxXo8u8-mo6xgowRrofRQ620dvhoGyvsW52k6SWZ8oEWB2scPEs4vWinn4QPFzYPWXdFuPBslWnnyZzukSOM8Rqc8tCbWgiysW63fwDak6jCN2TbOav3RKJY8giNUOjb38_GD1ul577tHUdUWw9LWjD8GH7rXXePsK5bE-GMMzDP-2MW2nfP_BAAA__94_8mf">