[libcxx-commits] [libcxx] [libc++] Start implementing std::datapar::simd (PR #139919)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Fri May 30 08:49:56 PDT 2025
================
@@ -0,0 +1,350 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___SIMD_BASIC_SIMD_H
+#define _LIBCPP___SIMD_BASIC_SIMD_H
+
+#include <__assert>
+#include <__concepts/convertible_to.h>
+#include <__config>
+#include <__memory/assume_aligned.h>
+#include <__ranges/concepts.h>
+#include <__simd/abi.h>
+#include <__simd/basic_simd_mask.h>
+#include <__simd/simd_flags.h>
+#include <__type_traits/is_arithmetic.h>
+#include <__type_traits/pack_utils.h>
+#include <__type_traits/remove_const.h>
+#include <__type_traits/remove_cvref.h>
+#include <__utility/integer_sequence.h>
+
+#if _LIBCPP_STD_VER >= 26
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace datapar {
+
+_LIBCPP_DIAGNOSTIC_PUSH
+_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wpsabi")
+template <class _Tp, class _Abi = __native_abi<_Tp>>
+class basic_simd {
+public:
+ using value_type = _Tp;
+ using mask_type = basic_simd_mask<sizeof(_Tp), _Abi>;
+ using abi_type = _Abi;
+
+private:
+ using __data_t = abi_type::_SimdT;
+
+ __data_t __data_;
+
+ _LIBCPP_ALWAYS_INLINE static constexpr __data_t __broadcast(value_type __value) {
+ return [&]<size_t... _Indices>(index_sequence<_Indices...>) _LIBCPP_ALWAYS_INLINE noexcept {
+ return __data_t{((void)_Indices, __value)...};
+ }(make_index_sequence<size()>{});
+ }
+
+ template <class _Up>
+ _LIBCPP_ALWAYS_INLINE static constexpr __data_t __load_from_pointer(const _Up* __ptr) {
+ return [&]<size_t... _Indices>(index_sequence<_Indices...>) _LIBCPP_ALWAYS_INLINE noexcept {
+ return __data_t{__ptr[_Indices]...};
+ }(make_index_sequence<size()>{});
+ }
+
+public:
+ static constexpr integral_constant<__simd_size_type, __simd_size_v<value_type, abi_type>> size{};
+
+ constexpr basic_simd() noexcept = default;
+
+ // [simd.ctor]
+ template <convertible_to<value_type> _Up, class _From = remove_cvref_t<_Up>>
+ requires(__value_preserving_convertible<_From, value_type> ||
+ (!is_arithmetic_v<_From> && !__constexpr_wrapper_like<_From>) ||
+ (__constexpr_wrapper_like<_From> && is_arithmetic_v<remove_const_t<decltype(_From::value)>> &&
+ bool_constant<(static_cast<value_type>(_From::value) == _From::value)>::value))
+ _LIBCPP_HIDE_FROM_ABI constexpr basic_simd(_Up&& __value) noexcept : __data_{__broadcast(__value)} {}
+
+ // TODO: converting constructor
+ // TODO: generator constructor
+ // TODO: flag constructor
+ // TODO: mask flag constructortrue
+
+ template <ranges::contiguous_range _Range, class... _Flags>
+ _LIBCPP_HIDE_FROM_ABI constexpr basic_simd(_Range&& __range, simd_flags<_Flags...> = {}) noexcept
+ requires(ranges::size(__range) == size())
+ {
+ static_assert(__is_vectorizable_type_v<ranges::range_value_t<_Range>>, "Range has to be of a vectorizable type");
+ static_assert(__contains_type_v<__type_list<_Flags...>, __convert_flag> ||
+ __value_preserving_convertible<ranges::range_value_t<_Range>, value_type>,
+ "implicit conversion is not value preserving - consider using std::datapar::simd_flag_convert");
+ auto* __ptr = std::assume_aligned<__get_align_for<value_type, _Flags...>>(std::to_address(ranges::begin(__range)));
+ __data_ = __load_from_pointer(__ptr);
+ }
+
+ template <ranges::contiguous_range _Range, class... _Flags>
+ _LIBCPP_HIDE_FROM_ABI constexpr basic_simd(
+ _Range&& __range, const mask_type& __mask, simd_flags<_Flags...> = {}) noexcept
+ requires(ranges::size(__range) == size())
+ {
+ static_assert(__is_vectorizable_type_v<ranges::range_value_t<_Range>>, "Range has to be of a vectorizable type");
+ static_assert(__contains_type_v<__type_list<_Flags...>, __convert_flag> ||
+ __value_preserving_convertible<ranges::range_value_t<_Range>, value_type>,
----------------
ldionne wrote:
```suggestion
static_assert(__value_preserving_convertible<ranges::range_value_t<_Range>, value_type> || __contains_type_v<__type_list<_Flags...>, __convert_flag>,
```
This feels a lot more natural to read.
https://github.com/llvm/llvm-project/pull/139919
More information about the libcxx-commits
mailing list