Skip to content

Commit 593521b

Browse files
authored
[libcxx] <experimental/simd> Add generate constructor of class simd (#66737)
Differential Revision: https://reviews.llvm.org/D159442
1 parent 30faaaf commit 593521b

File tree

6 files changed

+97
-0
lines changed

6 files changed

+97
-0
lines changed

libcxx/docs/Status/ParallelismProjects.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Section,Description,Dependencies,Assignee,Complete
1717
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`Class template simd declaration and alias <https://reviews.llvm.org/D144362>`_", [parallel.simd.abi], Yin Zhang, |Complete|
1818
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd<>::size() <https://reviews.llvm.org/D144363>`_", [parallel.simd.traits] simd_size[_v], Yin Zhang, |Complete|
1919
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd broadcast constructor <https://reviews.llvm.org/D156225>`_", None, Yin Zhang, |Complete|
20+
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd generate constructor <https://reviews.llvm.org/D159442>`_", None, Yin Zhang, |Complete|
2021
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "Class template simd implementation", None, Yin Zhang, |In Progress|
2122
| `[parallel.simd.nonmembers] <https://wg21.link/N4808>`_, "simd non-member operations", None, Yin Zhang, |In Progress|
2223
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`Class template simd_mask declaration and alias <https://reviews.llvm.org/D144362>`_", [parallel.simd.abi], Yin Zhang, |Complete|

libcxx/include/experimental/__simd/scalar.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ struct __simd_operations<_Tp, simd_abi::__scalar> {
4646
using _MaskStorage = __mask_storage<_Tp, simd_abi::__scalar>;
4747

4848
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __broadcast(_Tp __v) noexcept { return {__v}; }
49+
50+
template <class _Generator>
51+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __generate(_Generator&& __g) noexcept {
52+
return {__g(std::integral_constant<size_t, 0>())};
53+
}
4954
};
5055

5156
template <class _Tp>

libcxx/include/experimental/__simd/simd.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class simd {
4444
template <class _Up, enable_if_t<__can_broadcast_v<value_type, __remove_cvref_t<_Up>>, int> = 0>
4545
_LIBCPP_HIDE_FROM_ABI simd(_Up&& __v) noexcept : __s_(_Impl::__broadcast(static_cast<value_type>(__v))) {}
4646

47+
// generator constructor
48+
template <class _Generator, enable_if_t<__can_generate_v<value_type, _Generator, size()>, int> = 0>
49+
explicit _LIBCPP_HIDE_FROM_ABI simd(_Generator&& __g) : __s_(_Impl::__generate(std::forward<_Generator>(__g))) {}
50+
4751
// scalar access [simd.subscr]
4852
// Add operator[] temporarily to test braodcast. Add test for it in later patch.
4953
_LIBCPP_HIDE_FROM_ABI value_type operator[](size_t __i) const { return __s_.__get(__i); }

libcxx/include/experimental/__simd/utility.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <__type_traits/is_volatile.h>
2020
#include <__type_traits/void_t.h>
2121
#include <__utility/declval.h>
22+
#include <__utility/integer_sequence.h>
2223
#include <cstdint>
2324
#include <limits>
2425

@@ -71,6 +72,25 @@ inline constexpr bool __can_broadcast_v =
7172
(!__is_vectorizable_v<_Up> && is_convertible_v<_Up, _Tp>) || is_same_v<_Up, int> ||
7273
(is_same_v<_Up, unsigned int> && is_unsigned_v<_Tp>);
7374

75+
template <class _Tp, class _Generator, std::size_t _Idx, class = void>
76+
inline constexpr bool __is_well_formed = false;
77+
78+
template <class _Tp, class _Generator, std::size_t _Idx>
79+
inline constexpr bool
80+
__is_well_formed<_Tp,
81+
_Generator,
82+
_Idx,
83+
std::void_t<decltype(std::declval<_Generator>()(integral_constant<size_t, _Idx>()))>> =
84+
__can_broadcast_v<_Tp, decltype(std::declval<_Generator>()(integral_constant<size_t, _Idx>()))>;
85+
86+
template <class _Tp, class _Generator, std::size_t... _Idxes>
87+
_LIBCPP_HIDE_FROM_ABI constexpr bool __can_generate(index_sequence<_Idxes...>) {
88+
return (true && ... && __is_well_formed<_Tp, _Generator, _Idxes>);
89+
}
90+
91+
template <class _Tp, class _Generator, std::size_t _Size>
92+
inline constexpr bool __can_generate_v = experimental::__can_generate<_Tp, _Generator>(make_index_sequence<_Size>());
93+
7494
} // namespace parallelism_v2
7595
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
7696

libcxx/include/experimental/__simd/vec_ext.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H
1212

1313
#include <__bit/bit_ceil.h>
14+
#include <__utility/forward.h>
1415
#include <cstddef>
1516
#include <experimental/__simd/internal_declaration.h>
1617
#include <experimental/__simd/utility.h>
@@ -56,6 +57,16 @@ struct __simd_operations<_Tp, simd_abi::__vec_ext<_Np>> {
5657
}
5758
return __result;
5859
}
60+
61+
template <class _Generator, size_t... _Is>
62+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __generate_init(_Generator&& __g, std::index_sequence<_Is...>) {
63+
return _SimdStorage{{__g(std::integral_constant<size_t, _Is>())...}};
64+
}
65+
66+
template <class _Generator>
67+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __generate(_Generator&& __g) noexcept {
68+
return __generate_init(std::forward<_Generator>(__g), std::make_index_sequence<_Np>());
69+
}
5970
};
6071

6172
template <class _Tp, int _Np>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14
10+
11+
// <experimental/simd>
12+
//
13+
// [simd.class]
14+
// template<class G> explicit simd(G&& gen) noexcept;
15+
16+
#include "../test_utils.h"
17+
#include <experimental/simd>
18+
19+
namespace ex = std::experimental::parallelism_v2;
20+
21+
template <class T, std::size_t>
22+
struct CheckGenerateSimdCtor {
23+
template <class SimdAbi>
24+
void operator()() {
25+
ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
26+
constexpr size_t array_size = origin_simd.size();
27+
std::array<T, array_size> expected_value;
28+
for (size_t i = 0; i < array_size; ++i)
29+
expected_value[i] = static_cast<T>(i);
30+
assert_simd_values_equal<array_size>(origin_simd, expected_value);
31+
}
32+
};
33+
34+
template <class U, class T, class SimdAbi = ex::simd_abi::compatible<T>, class = void>
35+
struct has_generate_ctor : std::false_type {};
36+
37+
template <class U, class T, class SimdAbi>
38+
struct has_generate_ctor<U, T, SimdAbi, std::void_t<decltype(ex::simd<T, SimdAbi>(std::declval<U>()))>>
39+
: std::true_type {};
40+
41+
template <class T, std::size_t>
42+
struct CheckGenerateCtorTraits {
43+
template <class SimdAbi>
44+
void operator()() {
45+
static_assert(!has_generate_ctor<SimdAbi, T, SimdAbi>::value);
46+
47+
auto func = [](T i) { return i; };
48+
static_assert(has_generate_ctor<decltype(func), T, SimdAbi>::value);
49+
}
50+
};
51+
52+
int main(int, char**) {
53+
test_all_simd_abi<CheckGenerateSimdCtor>();
54+
test_all_simd_abi<CheckGenerateCtorTraits>();
55+
return 0;
56+
}

0 commit comments

Comments
 (0)