Skip to content

constexpr structured bindings bad codegen P2686 #164150

@ordinary-github-user

Description

@ordinary-github-user

https://godbolt.org/z/1bn1Kdj3f

-std=c++26 -O3 -Wall -march=znver5 -fno-exceptions -fconstexpr-steps=4294967295 -fbracket-depth=4294967295

#include <array>
#include <cstdint>
using u8 = std::uint8_t;
template<u8 N>
struct Range
{
    template<std::size_t I>
    consteval friend u8 get(Range) noexcept { return I; }
};
namespace std
{
    template<u8 N>
    struct tuple_size<Range<N>> {static constexpr std::size_t value = N;};
    template<std::size_t I, u8 N>
    struct tuple_element<I, Range<N>> {using type = u8;};
}
template<u8 x>constexpr u8 constant{x};
template<std::size_t L, std::size_t R>
__attribute__((always_inline)) inline constexpr std::array<u8, L+R> concat(const std::array<u8, L>& l, const std::array<u8, R>& r)
{
    static constexpr auto [...I] = Range<L>{};
    static constexpr auto [...J] = Range<R>{};
#if 1
    return { l[I]..., r[J]... };//bad codegen
#else
    return { l[constant<I>]..., r[constant<J>]... };//good codegen
#endif
}
auto test(const std::array<u8, 16>& l, const std::array<u8, 16>& r)
{
    return concat(l, r);
}

good codegen

test(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&):
  vmovups xmm0, xmmword ptr [rsi]
  vmovups xmm1, xmmword ptr [rdx]
  mov rax, rdi
  vmovups xmmword ptr [rdi + 16], xmm1
  vmovups xmmword ptr [rdi], xmm0
  ret

bad codegen

test(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&):
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I]
  mov rax, rdi
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.2)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 1], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.4)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 2], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.6)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 3], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.8)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 4], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.10)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 5], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.12)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 6], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.14)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 7], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.16)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 8], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.18)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 9], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.20)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 10], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.22)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 11], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.24)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 12], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.26)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 13], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.28)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 14], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.30)]
  movzx ecx, byte ptr [rsi + rcx]
  mov byte ptr [rdi + 15], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 16], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.32)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 17], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.34)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 18], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.36)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 19], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.38)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 20], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.40)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 21], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.42)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 22], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.44)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 23], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.46)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 24], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.48)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 25], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.50)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 26], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.52)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 27], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.54)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 28], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.56)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 29], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.58)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 30], cl
  movzx ecx, byte ptr [rip + reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.60)]
  movzx ecx, byte ptr [rdx + rcx]
  mov byte ptr [rdi + 31], cl
  ret

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I:
  .byte 0

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.2):
  .byte 1

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.4):
  .byte 2

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.6):
  .byte 3

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.8):
  .byte 4

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.10):
  .byte 5

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.12):
  .byte 6

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.14):
  .byte 7

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.16):
  .byte 8

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.18):
  .byte 9

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.20):
  .byte 10

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.22):
  .byte 11

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.24):
  .byte 12

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.26):
  .byte 13

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.28):
  .byte 14

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::I (.30):
  .byte 15

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J:
  .byte 0

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.32):
  .byte 1

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.34):
  .byte 2

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.36):
  .byte 3

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.38):
  .byte 4

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.40):
  .byte 5

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.42):
  .byte 6

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.44):
  .byte 7

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.46):
  .byte 8

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.48):
  .byte 9

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.50):
  .byte 10

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.52):
  .byte 11

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.54):
  .byte 12

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.56):
  .byte 13

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.58):
  .byte 14

reference temporary for std::array<unsigned char, 16ul + 16ul> concat<16ul, 16ul>(std::array<unsigned char, 16ul> const&, std::array<unsigned char, 16ul> const&)::J (.60):
  .byte 15

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions