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

    <tr>
        <th>Summary</th>
        <td>
            Unoptimized constexpr code for std::array
        </td>
    </tr>

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

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

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

<pre>
    Hello,
forgive me when I can't be that precise. I just pasted some test code to [godbolt](https://godbolt.org/z/Mde6WdrbE) and compared the assembly output between GCC 12.2 and clang 16.0.0 and the assembly code of clang was about 3 times larger and I guess, that this code is less optimized.

Here the code:

```cpp
#include <array>
#include <algorithm>
#include <stdexcept>
#include <iostream>       

template <typename Key, typename Value, std::size_t Size>
struct FlatMap {
    constexpr explicit FlatMap(std::array<std::pair<Key, Value>, Size> data) :
 m_data(std::move(data)) {}

    constexpr Value at(const Key &key) const {
        const auto itr =
 std::find_if(begin(m_data), end(m_data),
 [&key](const auto &v) { return v.first == key; });
        if (itr != end(m_data)) {
            return itr->second;
        }

 throw std::range_error("Not Found");
    }

private:
 std::array<std::pair<Key, Value>, Size> m_data;
};

enum Foo
{
    P, N, B, R, Q, K, p, n, b, r, q, k
};

constexpr FlatMap<char, Foo, 12> map {
        {{
                    {'P', P},
                    {'N', N},
                    {'B', B},
 {'R', R},
                    {'Q', Q},
 {'K', K},
                    {'p', p},
                    {'n', n},
                    {'b', b},
                    {'r', r},
 {'q', q},
                    {'k', k}
 }}
};

int main()
{
    std::cout << map.at('P') << std::endl;
    return 0;
}
```

The assembly output of x86-64 GCC 12.2 with -O3 -std=c++20
```asm
main:
  pushq %rbp
  xorl %esi, %esi
  movl $_ZSt4cout, %edi
  pushq %rbx
  subq $8, %rsp
 call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
 movq %rax, %rbx
  movq (%rax), %rax
  movq -24(%rax), %rax
  movq 240(%rbx,%rax), %rbp
  testq %rbp, %rbp
  je .L7
  cmpb $0, 56(%rbp)
  je .L3
  movsbl 67(%rbp), %esi
.L4:
  movq %rbx, %rdi
  call std::basic_ostream<char, std::char_traits<char> >::put(char)
  movq %rax, %rdi
  call std::basic_ostream<char, std::char_traits<char> >::flush()
  addq $8, %rsp
  xorl %eax, %eax
 popq %rbx
  popq %rbp
  ret
.L3:
  movq %rbp, %rdi
  call std::ctype<char>::_M_widen_init() const
  movq 0(%rbp), %rax
  movl $10, %esi
  movq %rbp, %rdi
  call *48(%rax)
  movsbl %al, %esi
 jmp .L4
.L7:
  call std::__throw_bad_cast()
_GLOBAL__sub_I_main:
 subq $8, %rsp
  movl $_ZStL8__ioinit, %edi
  call std::ios_base::Init::Init() [complete object constructor]
  movl $__dso_handle, %edx
  movl $_ZStL8__ioinit, %esi
  movl $_ZNSt8ios_base4InitD1Ev, %edi
  addq $8, %rsp
  jmp __cxa_atexit
```

The assembly output of x86-64 clang 16.0.0 with -O3 -std=c++20:

```asm
main: # @main
  pushq %r14
  pushq %rbx
  pushq %rax
  movb $80, 7(%rsp)
  leaq _ZL3map(%rip), %rdi
 leaq 7(%rsp), %rsi
  callq _ZNK7FlatMapIc3FooLm12EE2atERKc
  movq _ZSt4cout@GOTPCREL(%rip), %rdi
  movl %eax, %esi
  callq _ZNSolsEi@PLT
  movq %rax, %rbx
  movq (%rax), %rax
  movq -24(%rax), %rax
  movq 240(%rbx,%rax), %r14
  testq %r14, %r14
  je .LBB0_5
  cmpb $0, 56(%r14)
  je .LBB0_3
  movzbl 67(%r14), %eax
 jmp .LBB0_4
.LBB0_3:
  movq %r14, %rdi
  callq _ZNKSt5ctypeIcE13_M_widen_initEv@PLT
  movq (%r14), %rax
  movq %r14, %rdi
  movl $10, %esi
  callq *48(%rax)
.LBB0_4:
  movsbl %al, %esi
  movq %rbx, %rdi
  callq _ZNSo3putEc@PLT
  movq %rax, %rdi
 callq _ZNSo5flushEv@PLT
  xorl %eax, %eax
  addq $8, %rsp
  popq %rbx
  popq %r14
  retq
.LBB0_5:
  callq _ZSt16__throw_bad_castv@PLT
_ZNK7FlatMapIc3FooLm12EE2atERKc: # @_ZNK7FlatMapIc3FooLm12EE2atERKc
  pushq %r14
  pushq %rbx
  pushq %rax
  movzbl (%rsi), %eax
  cmpb %al, (%rdi)
  jne .LBB1_3
 xorl %ecx, %ecx
  jmp .LBB1_2
.LBB1_3:
  movl $1, %ecx
  cmpb %al, 8(%rdi)
  je .LBB1_2
  movl $2, %ecx
  cmpb %al, 16(%rdi)
 je .LBB1_2
  movl $3, %ecx
  cmpb %al, 24(%rdi)
  je .LBB1_2
 movl $4, %ecx
  cmpb %al, 32(%rdi)
  je .LBB1_2
  movl $5, %ecx
 cmpb %al, 40(%rdi)
  je .LBB1_2
  movl $6, %ecx
  cmpb %al, 48(%rdi)
  je .LBB1_2
  movl $7, %ecx
  cmpb %al, 56(%rdi)
  je .LBB1_2
  movl $8, %ecx
  cmpb %al, 64(%rdi)
  je .LBB1_2
  movl $9, %ecx
  cmpb %al, 72(%rdi)
  je .LBB1_2
  movl $10, %ecx
 cmpb %al, 80(%rdi)
  je .LBB1_2
  movl $11, %ecx
  cmpb %al, 88(%rdi)
  jne .LBB1_14
.LBB1_2:
  movl 4(%rdi,%rcx,8), %eax
 addq $8, %rsp
  popq %rbx
  popq %r14
  retq
.LBB1_14:
  movl $16, %edi
  callq __cxa_allocate_exception@PLT
  movq %rax, %rbx
 leaq .L.str(%rip), %rsi
  movq %rax, %rdi
  callq _ZNSt11range_errorC1EPKc@PLT
  movq _ZTISt11range_error@GOTPCREL(%rip), %rsi
  movq _ZNSt11range_errorD1Ev@GOTPCREL(%rip), %rdx
  movq %rbx, %rdi
  callq __cxa_throw@PLT
  movq %rax, %r14
  movq %rbx, %rdi
 callq __cxa_free_exception@PLT
  movq %r14, %rdi
  callq _Unwind_Resume@PLT
_GLOBAL__sub_I_example.cpp: # @_GLOBAL__sub_I_example.cpp
  pushq %rbx
  leaq _ZStL8__ioinit(%rip), %rbx
  movq %rbx, %rdi
  callq _ZNSt8ios_base4InitC1Ev@PLT
  movq _ZNSt8ios_base4InitD1Ev@GOTPCREL(%rip), %rdi
  leaq __dso_handle(%rip), %rdx
  movq %rbx, %rsi
  popq %rbx
  jmp __cxa_atexit@PLT # TAILCALL
_ZL3map:
  .byte 80 # 0x50
  .zero 3
  .long 0 # 0x0
 .byte 78 # 0x4e
  .zero 3
  .long 1 # 0x1
  .byte 66 # 0x42
 .zero 3
  .long 2 # 0x2
  .byte 82 # 0x52
  .zero 3
  .long 3 # 0x3
  .byte 81 # 0x51
  .zero 3
  .long 4 # 0x4
  .byte 75 # 0x4b
  .zero 3
  .long 5 # 0x5
  .byte 112 # 0x70
  .zero 3
 .long 6 # 0x6
  .byte 110 # 0x6e
  .zero 3
  .long 7 # 0x7
 .byte 98 # 0x62
  .zero 3
  .long 8 # 0x8
  .byte 114 # 0x72
 .zero 3
  .long 9 # 0x9
  .byte 113 # 0x71
  .zero 3
  .long 10 # 0xa
  .byte 107 # 0x6b
  .zero 3
  .long 11 # 0xb

.L.str:
 .asciz "Not Found"

DW.ref.__gxx_personality_v0:
  .quad __gxx_personality_v0
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzEWltz4jbf_zTKjSaMLR-5yEUgpM2EpmmyfTvTG49sC9CusRxJTkg-_TuSLZ8whn3aZ56dHQek_-H3P0sAFoJuc0JugLcA3t0VLuWO8ZtXSTY4Z3dXMUs_b34lWcYAWgLrDli3G8a39J3APYEfO5LDB5jgHKBAwphAucMSFpwkVJAZfIDfSyFhgYUkKRRsT6AkQsKEpQRKBoG32LI0ZpkE3h1A4U7KQgDnFqB7gO7rrRnjW4DuvwC6_y0l_l8pj1cAzSHOU5iwfYE5SaHcEYiFIPs4-4SslEWp4MgPQnL4y3IJbTRDFUeG8y20_Zk1s_RCj1MDY5ua6gMLiGNWSuhASfdEwAzzLeGa7wFuSyIEQMvKaLmjouKnAmZECMgKSff0i6SzynHV81fCiVaqaJWtnT3gW9X_pCjqFeTQPMnKlEDgLDHn-BM4q9G9bMs4lbv9iX0hU3JISCFP7FMmJCe4Yp93UUmyLzIsNZX8LEiO9wQ-kk9tunn_fzgriVoRMlVWObeCfpFIwlf6RRqVQvIykfA-w_I3XEAQLKp1CCFMWC4kORQckkOR0YQ2dACFjdTaBctmocCUA2dZ46lgOCv1utYMUyyxSpjG2XAfVWut2D17JwCFNammDhYguOv6oQ9Sa4JYAhTqReURCJD_QwGZV4R9Axt-iEvJIJUcAqfW0LptQ_M0ohuAwphsaQ5QaNDOlVEkTwdLtQBVwJV2XUodRQD577VFkBNZ8hy-zzaUK3zOHXDuoOJyFlDZi-bAGWCmGwhQqOEiW5EfYZgfG6r-1cqo5NfAWQmSsDw9kj50stxx9tG6g-N8SyLCOeMAhQChJybhPSsVBDREO5BVcPqOZVtk8J9kUW2uUadUNa_1k-TlHt4zZvY7uJ6VoCf1WKjHi3r8oR6P6lGoR64esXpw9XhTjx-nVLVZaCrEWSY7rDkVAqQangY9LLLKS4vRcHX3UfAMUKAEPeusWJ4jf6rJny4jX9Tkix55tfdS771cJuqPmvyPEVGP9d7jZaKKmry4jDyvyfPLyOOaPL6MnNfkfMSut3rv7TJRP2ryH02B6FJpquUowWgu4R7r7qNq7Dijm8JJ1HgEzhI4S5VtM90Qm_SZm62GnuRp1qvZuklYvcrqT8Musm8jg55t4CH0r323HfUfVO7g9e8OvNaa7xKAFgAtkDUQjcW-WtHWNo0CFqXYvUGAPB4XZu3AeKaWiKDKmfWrenPP3tWmG_39Kl3lFEOS0hGZB7MmylgtuWFNzoVRl-Asa90WY0GTqBnRTbW3cdhhHkmOqRRm21lB1cP0NisIx5LxKhyqneeyiawCXwHDB4OjhVhvhmZ_bkhwn-QauRdQIdeqqWKl64i8dbc6KTYhONr9TuBsHZh3yb6IlRstRej5RkPRmlgxOB0sIs6gH_RIB1Gdrd1OSjROihsntbH9d6NVlPpYobnmR_rxf13_JivFrlv7EOI0PZGobV00wEgT9IIVw5RvlxoJnEjjcWfU48U5ixN1EG1NqRaj36IPmpI8ojmt2lJ9LuspsEZSoJ-1urBta7TozwAE6Fa5rFMW_QQEyMPZkeDv-wKq5Kt9EnR80jc7ivRxKYpxGiVYyG7Mol_Wvy9u11Ekyjh6iPoN7nTf6XWydRhFlFXuG7azPhLKRBRjQap3D4qjfVW5HngLdV_LiCSQxd9JIqtoqCsB4-rYOkQQpYJFO5ynGWn0HwVmHOdYZ356laHB6Spgd_bq_diwiVRXgYmi5IAjLMmByv94UPWuoaeH1Ynr4XBqQYAcCFxLvz2aNrY7NYHatV7O63Ya6pw3PVJ022lG8BuM_l47e30_U_u0W0CNOzVhX4Rxay-VlLSnx6A-0D4kzj1j672NViuE5erlMekVXTtmXeuX3789L19W60kYJg26XWoEwCvLxIoC13pef5tovP-r6diGsp2Otnu8q4fdYmFF3vSEVLzzI6bulPzqTsmKfNjjq26lGJuOVUkZ6eQt2HQk-q_S0438IVnZTq97r95HY3KEaujQUzqnunqF50TnNob2bDvdyc-fGuq0c4pSrpKzidfwdlg9Pa6HHpqaylMtbmpitwnGiXzrOsQbjKiqQm1_OKB6IM8VfNvYLmwN_7DnfekwhnVvGsl0U0VNpMM6Jp0iyqsqspsqagKRNIFIDt2BUpGj1p32sHaqVD3m7sMJR_GQvvxWHjonz_ZHBJ6W55yT13TAaYBGnntOnoN-zmDvSGBfXtN7L5TnnwPo_mREgnMCvbGITAgMzwn0LwtJI3B-TmDwkzFp---JoIQ_GRT7fJmMR6WpW9vtViIaVmLXY3pA67IOx9rFv9xlNbSRvuCPn83fzEk1y1iCJYmqj_8pyy8_3ujD22w9E5KPna5Gxtypy2k1q6Rtdz7QXdqr58exmRf9_e1hQHvmnDdAcqxLH_XPnBWPjw4TQ1v7Vg-3s-5sAzoluCt3w8n5eE2cpf7MP2ieRi9ElHvSG7n9SyE5YHUhmyVF0Z22p4kmhmp9I-hfxo69fHR0Pnc0GtzZlvboWfDU7e7S60GFvnfh_MkMaVNwpLiPLo7aAu3wb7cP6-Xtem3ORNWVqq3zWfwpCQwtTWwdPKvZ-CKcweawPstYvoWGzFBV3EFYL7tkktuuyey-ct837KbfjnKjmgoNoJt1D00qd2oyZ8BuQHn2JLtrMPbZA8-sx5Pshszrs9u2QR-ccHzFbjzkD9lNQPxpzwdGSy9ucxM3f9p1hiwcajdOCSYDN6-p5kN2E5Jg2vWNkXggwDJm-dPOt02MazIz9PTgaUphhkVCv-DwS8AOx91fM042syjaHg5RQbhgOc6o_IzerW5FvZU4haNElSzzOctVeuOkc2eOr8iN7YfWPAi8wLna3VieGycedmN_E7hzK5i7tuslju95qRPMw-SK3iALOZZrhXZoI8-Z2Ruy2fgBclPX2-BgA1yL7DHNZln2vp8xvr2iQpTkxkcWsq8yHJNM6B9lIJSTD6g3lbHe3RW_UTzXcbkVwLUyKqRopUgqM3LzZ978-KDzlbX-dcKG8cH3oFclz24GP72gclfGs4TtAbpXsus_1wVn30kiAbrXiARA9xrx_wcAAP__c483_w">