1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H
11 #define _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H
12 
13 #include <__bit/bit_ceil.h>
14 #include <__utility/forward.h>
15 #include <__utility/integer_sequence.h>
16 #include <cstddef>
17 #include <experimental/__config>
18 #include <experimental/__simd/declaration.h>
19 #include <experimental/__simd/traits.h>
20 #include <experimental/__simd/utility.h>
21 
22 #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
23 
24 _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
25 inline namespace parallelism_v2 {
26 namespace simd_abi {
27 template <int _Np>
28 struct __vec_ext {
29   static constexpr size_t __simd_size = _Np;
30 };
31 } // namespace simd_abi
32 
33 template <int _Np>
34 inline constexpr bool is_abi_tag_v<simd_abi::__vec_ext<_Np>> = _Np > 0 && _Np <= 32;
35 
36 template <class _Tp, int _Np>
37 struct __simd_storage<_Tp, simd_abi::__vec_ext<_Np>> {
38   _Tp __data __attribute__((__vector_size__(std::__bit_ceil((sizeof(_Tp) * _Np)))));
39 
40   _LIBCPP_HIDE_FROM_ABI _Tp __get(size_t __idx) const noexcept {
41     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx >= 0 && __idx < _Np, "Index is out of bounds");
42     return __data[__idx];
43   }
44   _LIBCPP_HIDE_FROM_ABI void __set(size_t __idx, _Tp __v) noexcept {
45     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx >= 0 && __idx < _Np, "Index is out of bounds");
46     __data[__idx] = __v;
47   }
48 };
49 
50 template <class _Tp, int _Np>
51 struct __mask_storage<_Tp, simd_abi::__vec_ext<_Np>>
52     : __simd_storage<decltype(experimental::__choose_mask_type<_Tp>()), simd_abi::__vec_ext<_Np>> {};
53 
54 template <class _Tp, int _Np>
55 struct __simd_operations<_Tp, simd_abi::__vec_ext<_Np>> {
56   using _SimdStorage = __simd_storage<_Tp, simd_abi::__vec_ext<_Np>>;
57   using _MaskStorage = __mask_storage<_Tp, simd_abi::__vec_ext<_Np>>;
58 
59   static _LIBCPP_HIDE_FROM_ABI _SimdStorage __broadcast(_Tp __v) noexcept {
60     _SimdStorage __result;
61     for (int __i = 0; __i < _Np; ++__i) {
62       __result.__set(__i, __v);
63     }
64     return __result;
65   }
66 
67   template <class _Generator, size_t... _Is>
68   static _LIBCPP_HIDE_FROM_ABI _SimdStorage __generate_init(_Generator&& __g, std::index_sequence<_Is...>) {
69     return _SimdStorage{{__g(std::integral_constant<size_t, _Is>())...}};
70   }
71 
72   template <class _Generator>
73   static _LIBCPP_HIDE_FROM_ABI _SimdStorage __generate(_Generator&& __g) noexcept {
74     return __generate_init(std::forward<_Generator>(__g), std::make_index_sequence<_Np>());
75   }
76 
77   template <class _Up>
78   static _LIBCPP_HIDE_FROM_ABI void __load(_SimdStorage& __s, const _Up* __mem) noexcept {
79     for (size_t __i = 0; __i < _Np; __i++)
80       __s.__data[__i] = static_cast<_Tp>(__mem[__i]);
81   }
82 };
83 
84 template <class _Tp, int _Np>
85 struct __mask_operations<_Tp, simd_abi::__vec_ext<_Np>> {
86   using _MaskStorage = __mask_storage<_Tp, simd_abi::__vec_ext<_Np>>;
87 
88   static _LIBCPP_HIDE_FROM_ABI _MaskStorage __broadcast(bool __v) noexcept {
89     _MaskStorage __result;
90     auto __all_bits_v = experimental::__set_all_bits<_Tp>(__v);
91     for (int __i = 0; __i < _Np; ++__i) {
92       __result.__set(__i, __all_bits_v);
93     }
94     return __result;
95   }
96 
97   static _LIBCPP_HIDE_FROM_ABI void __load(_MaskStorage& __s, const bool* __mem) noexcept {
98     for (size_t __i = 0; __i < _Np; __i++)
99       __s.__data[__i] = experimental::__set_all_bits<_Tp>(__mem[__i]);
100   }
101 };
102 
103 } // namespace parallelism_v2
104 _LIBCPP_END_NAMESPACE_EXPERIMENTAL
105 
106 #endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
107 #endif // _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H
108