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

    <tr>
        <th>Summary</th>
        <td>
            Suboptimal codegen in vector copy assignment
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

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

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

<pre>
    ```cpp
// clang++ -std=c++17 -O3 -fno-exceptions -stdlib=libc++
#include<vector>

using Container = std::vector<int>;
int copy_assignment(const Container &v1, Container &v2) {
  v2 = v1;
  return 0;
}
```

I'd expect this to generate a `memcpy` but it generates a ton of seemingly unnecessary code

```asm
copy_assignment(std::__1::vector<int, std::__1::allocator<int> > const&, std::__1::vector<int, std::__1::allocator<int> >&): # @copy_assignment(std::__1::vector<int, std::__1::allocator<int> > const&, std::__1::vector<int, std::__1::allocator<int> >&)
        cmp     rsi, rdi
        je .LBB0_2
        push    rax
        mov     rax, qword ptr [rdi]
 mov     rdx, qword ptr [rdi + 8]
        mov     rcx, rdx
 sub     rcx, rax
        sar     rcx, 2
        mov     rdi, rsi
 mov     rsi, rax
        call    void std::__1::vector<int, std::__1::allocator<int> >::__assign_with_size[abi:v180000]<int*, int*>(int*, int*, long)
        add     rsp, 8
.LBB0_2:
        xor     eax, eax
        ret
void std::__1::vector<int, std::__1::allocator<int> >::__assign_with_size[abi:v180000]<int*, int*>(int*, int*, long): # @void std::__1::vector<int, std::__1::allocator<int> >::__assign_with_size[abi:v180000]<int*, int*>(int*, int*, long)
 push    rbp
        push    r15
        push    r14
        push r13
        push    r12
        push    rbx
        push    rax
 mov     r13, rcx
        mov     rbx, rdx
        mov     r12, rsi
        mov     r14, rdi
        mov     r15, qword ptr [rdi]
 mov     rax, qword ptr [rdi + 16]
        mov     rcx, rax
 sub     rcx, r15
        sar     rcx, 2
        cmp     rcx, r13
 jae     .LBB1_1
        test    r15, r15
        je .LBB1_11
        mov     qword ptr [r14 + 8], r15
        mov     rdi, r15
        call    operator delete(void*)@PLT
        xorps   xmm0, xmm0
        movups  xmmword ptr [r14], xmm0
        mov     qword ptr [r14 + 16], 0
        xor     eax, eax
.LBB1_11:
        mov rcx, r13
        shr     rcx, 62
        jne     .LBB1_17
 movabs  rcx, 4611686018427387903
        mov     rbp, rax
        sar rbp
        cmp     rbp, r13
        cmovbe  rbp, r13
 movabs  rdx, 9223372036854775804
        cmp     rax, rdx
 cmovae  rbp, rcx
        cmp     rbp, rcx
        ja      .LBB1_17
 lea     rdi, [4*rbp]
        call    operator new(unsigned long)@PLT
        mov     r15, rax
        mov     qword ptr [r14], rax
        lea     r13, [r14 + 8]
        mov     qword ptr [r14 + 8], rax
        lea     rax, [rax + 4*rbp]
        mov     qword ptr [r14 + 16], rax
        sub     rbx, r12
        je      .LBB1_15
 mov     rdi, r15
        mov     rsi, r12
        mov     rdx, rbx
 call    memcpy@PLT
.LBB1_15:
        mov     r14, r13
 jmp     .LBB1_16
.LBB1_1:
        mov     rax, qword ptr [r14 + 8]
 add     r14, 8
        mov     rdx, rax
        sub     rdx, r15
        mov     rcx, rdx
        sar     rcx, 2
        cmp rcx, r13
        jae     .LBB1_7
        lea     r13, [r12 + 4*rcx]
 cmp     rax, r15
        je      .LBB1_4
        mov     rdi, r15
        mov     rsi, r12
        call    memmove@PLT
        mov r15, qword ptr [r14]
.LBB1_4:
        sub     rbx, r13
 je      .LBB1_16
        mov     rdi, r15
        mov     rsi, r13
 jmp     .LBB1_6
.LBB1_7:
        sub     rbx, r12
        je .LBB1_16
        mov     rdi, r15
        mov     rsi, r12
.LBB1_6:
        mov     rdx, rbx
        call memmove@PLT
.LBB1_16:
        add     rbx, r15
        mov     qword ptr [r14], rbx
        add     rsp, 8
        pop     rbx
 pop     r12
        pop     r13
        pop     r14
        pop r15
        pop     rbp
        ret
.LBB1_17:
        mov rdi, r14
        call    std::__1::vector<int, std::__1::allocator<int> >::__throw_length_error[abi:v180000]() const
std::__1::vector<int, std::__1::allocator<int> >::__throw_length_error[abi:v180000]() const: # @std::__1::vector<int, std::__1::allocator<int> >::__throw_length_error[abi:v180000]() const
        push    rax
 lea     rdi, [rip + .L.str]
        call std::__1::__throw_length_error[abi:v180000](char const*)
std::__1::__throw_length_error[abi:v180000](char const*): # @std::__1::__throw_length_error[abi:v180000](char const*)
        push rax
        mov     rsi, rdi
        lea     rdi, [rip + .L.str.1]
 xor     eax, eax
        call std::__1::__libcpp_verbose_abort(char const*, ...)@PLT
.L.str:
 .asciz  "vector"

.L.str.1:
        .asciz  "length_error was thrown in -fno-exceptions mode with message \"%s\""
```

Ideally, the above C++ code should translate to the following C++ code:

```cpp
#include<vector>

using Container = std::vector<int>;
int copy_assignment(const Container &v1, Container &v2) {
  if (v1.begin() != v2.begin())
 std::memcpy(&v2[0], &v1[0], v1.size()*sizeof(int));

  return 0;
}
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzUWVtv66gT_zTkBTUy-JqHPCTpv9JfOtKutPseYZvGVLbxGpyk59OvwPiG7aZ7Th_Oqdo68cDMMJffDECEYJeS0j3wj8B_3pBGZrzeZ6wmKZPvZBPz9H0PAqf9TaoKOM_AOQD8AvALTHJSXgA-AnyET0KmwH1O2q8ohE9_uPDpteRP9J7QSjJeCj0oZzFwn3MWm6EdR5eVSd6kFLinK00kr4H7P0PT_xvBygs88VISVtIaAvcZapkH4B66GSdWSjXPNWxZKWHCq_dzu9KClhLgKOGlkGNWOLgigE_WKwzwDoLQsILwirXQK-rZQ1hT2dQldPpXIHw2HzqrjRfxf4DDFNJ7RRMJZcYElBxeaElrIikkEAROQYukegeBA-NGQiZ7soAESl5C_goFpQUrL_k7bMqSJlQIUr_DhKd0LKzXgIiifTM3RW_B8xktmBKf4HwEyXOekLG9ofrTVgU4WJ70o2w1wx1wDxBgFwLP-X3XYEKm_UmKSj9rwRSrOmVT-huF22_Ho3PG0_dVIzI9j9ynhIJfYUfAJ_jPjdcprGQNgX9U3H0Tl8PAdHEgVNkcDcNt9sm91bcTL5p4QrD1EqQe0_EK27Q1g2C2lsY-NtuE5Ll6XjlLv9JVZlAbYOcbk9lZsO8U-EcSM8UYRY7jOMo-hvlB8TeflK-j2Vt8gjlXSGnFAElTs8ZKjYlaaud29zAdfeetIWnrYGpbpKayffGbmWRI7d9M8db6fULG1UqmIn-N4C0QauSuDV-Dgvj-CCP6bEKuzqZkDTxiK7ttOsLTNJ3RvUU0G-j-J8FpGcU0OKHgITqRNXSyffExOvUg3c3uXPNGqCaoXEVnNJ0lqZCjxc5kGmhHZ4SWVzFdNfIGSF5iZ0OoTe-QkleqjeA1TGlOJQU4UvmmY3oHPOfPb3_P8KYS6lkUjmKsn7bkRg25F4WlsdF1ccr6ElvH4hN0Pod8vRVtqFRSZj7rPJ5NPB5YLn8rJ54Nh7gksehneQFCQRQ4KPJw6EbhznHXEqparYozxOjDzUyyVU8Kfo3pAr3Xri3pO4xdN8SOG0S-F4Z-5HgrgoiV7koCGUmwccLW0Ka_EbhkvZyScYgC_-gBfFBM7ESeBWtJbwBHTak3KmmPvQvxamHMaoNkh16XV_b4XukWM-1U_IHMXZXQukFNIXc9Zc08n0ufebR1KGjg3a4kb3TiNn_WKS4ji92j2WytTnOoU52XzV5n5Mxeg6WUhqMKM0CxCUkzM5jwWWezVF_m7u07tFZq9PH6Vs2eLhef1Z66m_-wOK2B3LQ-hY8DGw9hl9yH9dtAsVDKRnK8_1aYHoXPKEoKfqVrOb_YU7RpPQoFbxYKs6ToI2qaDcFPrmo5UCdxGj5Wbp6xX6QeHisSrCeMncNjJy14qNfOZtinVPxxUqzBtK3A8iaqo1a86qWZfr17M2une4LdgPcEu1_n1UJ3z4cSubw_64vjYtvS-c0u2SYZvn57JLOa3845LS8yO9O65vXSBglHAO_M-YhW7FdQZNg6_graPNiDzZugmlUadrfftkLWy73QXO3Pq5ZkpO6OtA79jvVLOX7kgZ9VdGLK9fOulQO0R-beosHgj45WVj2RszipqvOV1jEX9ExiXsv5ek5wu91aXavxeQ8BWyIS9h1CgLGJXGzwaTx-O-9oRhPHhoY3IqC2fwlZOTuJL3hK4Y3JDBZUCHKhEPgnJRL7ovvUyV88yE4pyfN3tTaZUUhifqXwZO4CEsVcZLzJUyhrUoqcSAol10NfeZ7zmz7LHw3vl2XJHF05_PoXBOwVql012sb0wkqDDQAjfWuAx2-HGO81NL2wIivO_tExFa8VPny_oq0-xTKMDuoLf-3OqjTr_jLCKPaJW4pNunfTnbsjG7pHwQ5hhByMNtne9X3kugFCYRimNPCw5wVuSpPdLvbIaxRt2B472HUix3c838Foi1Do7PzXnRenHk53LvAcWhCWb_P8Wmx5fdkwIRq6DzzPjzY5iWku9A0UxiW9QU1U0ec_b-q9mvMUNxcBPCdnQoqBi2Qyp_u_mphXkhUk14F0oTreW39r18LBtZumzveZlJVQNteXWBcmsybeJrwA-EWxNo-nquZvNJEAv2iFBMAvWuF_AwAA__-F4D6K">