Files
llvm-project/clang/test/CodeGenCXX/bad-codegen-for-constexpr-structured-bindings.cpp
Takashi Idobe cbe9891b44 [Clang] fix bad codegen from constexpr structured bindings (#186594)
Resolves: https://github.com/llvm/llvm-project/issues/164150

C++26 allows for constexpr packs in structured bindings. This is a new
feature (the code doesn't compile on lower the -std=c++26) and so was
previously unhandled in clang.

This makes clang aware of packs and handle them as one constant unit
instead of materializing them as separate mutable reference temporaries
allowing llvm to optimize them.

This turns the example code from the issue into this as you would expect
without compiling for zen 5 (the good codegen described).

```asm
  movq    %rdi, %rax
  movups  (%rsi), %xmm0
  movups  %xmm0, (%rdi)
  movups  (%rdx), %xmm0
  movups  %xmm0, 16(%rdi)
  retq
```
2026-03-27 12:07:23 +08:00

41 lines
1020 B
C++

// RUN: %clang_cc1 -std=c++26 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
namespace std {
using size_t = decltype(sizeof(0));
template <typename T> struct tuple_size;
template <size_t I, typename T> struct tuple_element;
template <typename T> struct tuple_size<const T> : tuple_size<T> {};
template <size_t I, typename T> struct tuple_element<I, const T> {
using type = const typename tuple_element<I, T>::type;
};
} // namespace std
using u8 = unsigned char;
template <u8 N> struct Range {
template <std::size_t I>
constexpr 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;
};
} // namespace std
const u8 &f() {
static constexpr auto [I] = Range<1>();
return I;
}
// CHECK: @[[TMP:_ZGR.*]] = internal constant i8 0, align 1
// CHECK-LABEL: define {{.*}} @_Z1fv(
// CHECK: ret ptr @[[TMP]]