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

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

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

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

    <tr>
      <th>Reporter</th>
      <td>
          appujee
      </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/eJzUWVtvq7gT_zTOi9UIzCXkIQ9J-q_0l460K-2-RwYmiSvALDZpej79ysbcDDTdc_pwTtWWhBnPjOfy89imQrBLAbBDwQEFzytayyuvdrQs61eAVczT9x0KneY3KUvkPCNnj8gLIi84yWhxQeSAyAE_CZki7zlpvrob_PSHh5_OBX-CewKlZLwQmiljMfKeMxYb1laix4okq1NA3vEGieQV8v5naPp_LVhxwUdeSMoKqDDynrHWuUfevh1xZIVU4zwjlhUSJ7x8PzXzzKGQiEQJL4QciiLhzUXkaL0iiGwx2hhRGN-IVnpzO_EYVyDrqsBO9wptns2H1mvDSfwfkU2K4V5CIrG8MoElxxcooKISMMUodHLIk_IdhQ6Oa4mZ7MgCUyx5gfkZC4CcFZfsHddFAQkIQat3nPAUhso6C6jImzdTV3QePJ3cGVeSI55y0CzjCR36G6s_7VVEwvlBPypWC9wib48R8TDynd93DiZlmp8kL_WzEkyJqlI2pr8CXn87HJwTGb8va3HV4-h9TMj5DbcEcsT_vPEqxaWsMAoOSnpg8rJnTGcZsarmqGe3xSf3xt5WvajjEcG2S9BqSCcLYtPGDYLZVhr_2GITmmXqeeMs_cpQGaYmwU5vTF5Pgn0HFBxozJRgN3Icx1H-McL3Sr75pGIdTd6SI864QkorB2iamjmWiidqqG3Yvf2Y-84bR0ITYLA9UoFsXvxmLulL-zczvPF-V5BxuVCpbrBE8GcIlestsS9BQXx_hBFdNbmerqZkCTxiq7ptukvGZTqh-7No1tODT4LTPIppcHLDh-hEl9DJjsXH6NSBdDu6Dc0rBU1Qteqe3PEoCUIOJjvRaaDdPbnu_CzGs3b9HpLnxNkQatNbpOSlaiN4hVPIQAIikao3ndNb5Dt_fvt7gjelUM88d5Rg_bQ114rlnueWxcbW2SHLU2wCS47Y-RzydV60oVJpmcSsjfh1FPHQCvlrMYrsps9LGotulB-6bhiFjhv5ZONFm63jLRVUubgqThCjSzczyDY9yfkthhl6Z12zpG8J8bwNcbwwCvzNJogcf0ERtcpdaaADDTZO2Bba9FeK57yXAR2mKAoOPiJ7JcQu5EmyFvCGSFQXepuSdtg7k68Wxiw2SHbqtXVl83dGN5hpl-IPVO6ihiYMagi96yFL7vlc-UyzrUVBA-_2SvIKo7AFk05xHlnsHs0Wa3Wa_TrVRtnsdQbB7CyYK2k8WGF6KDYpaUaGIznLYubWl2l4uw6t0Rp9PL9Ft6fzi89iT92Of7g4LYHceH3aPE5s0qddcu_nbwPFzFI20OP_t4XpUfoMsiTnN1iq-dmeoinrQSr4k1SYFEWXUeNqCH9yVvOJOsrTzWPjphX7ReaRoSHhcsHYNTwM0kyEOutsgV1JxR8XxRJM2wbMb6JaasnLTpvp19s3k3a6I9gNeEew-3VeznT3vF8i5_dn3eI427a0cbOXbFMMX789kteKv50yKC7yeoKq4tXcBolEiGzN-Yg27FcwpN86_grWPNiDTZugipUadtff1kJW873Q1OzPm5ZcadUeae27HeuXSvwoAj9r6MiVy-ddCwdoj9y9dnuHPzpaWYxExuKkLE83qGIu4ERjXsnpfI54vV5bXauJeQcBayoS9h1jRIjJXGLwaci_nnY0g4FDR-M3KrD2f4FZMTmJz3kK-I3JK85BCHoBjIKjUkkC0X5q9c8eZKdAs-xdzU1eAdOY3wAfzV1AooSLK6-zFMuKFiKjErDkmvXMs4y_6bP8AXs3LUvn4Mrh178gYGesdtXuOoYLKww2IOLqWwMyfNvneGeh6YUVWUkODo5Z8Rrl_febu9anWEbQXn3h5_asSovuLiOMYZ-4pVilOy_delu6gp0bbl3iOqHnr667AM6xE5HtNoDwHDghnGl6ThMa-5G3pUmwYjviEM-JnMDxfS_w14G7IeTsuC45k7O_VWkPOWXZOstu-ZpXlxUTooZd6PvBZpXRGDLR3j9VO8X0FNcXgXwnY0KKfphkMoPdX3XMS8lymunMuYBO8CbAOpa4j-WqrrLdVcpSKCfrW6sLk9c6Xic8R-RFiTaPp7Lir5BIRF60eQKRF23hvwEAAP__GE86Ww">