Skip to content

Commit ba89749

Browse files
authored
[libc++] <experimental/simd> Add implicit type conversion constructor for class simd/simd_mask (#71132)
1 parent c4779ea commit ba89749

File tree

5 files changed

+177
-0
lines changed

5 files changed

+177
-0
lines changed

libcxx/docs/Status/ParallelismProjects.csv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Section,Description,Dependencies,Assignee,Complete
2020
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd<>::size() <https://reviews.llvm.org/D144363>`_", [parallel.simd.traits] simd_size[_v], Yin Zhang, |Complete|
2121
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd default constructor <https://github.com/llvm/llvm-project/pull/70424>`_", None, Yin Zhang, |Complete|
2222
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd broadcast constructor <https://reviews.llvm.org/D156225>`_", None, Yin Zhang, |Complete|
23+
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd implicit type conversion constructor <https://github.com/llvm/llvm-project/pull/71132>`_", None, Yin Zhang, |Complete|
2324
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd generate constructor <https://reviews.llvm.org/D159442>`_", None, Yin Zhang, |Complete|
2425
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd subscript operators <https://github.com/llvm/llvm-project/pull/68960>`_", None, Yin Zhang, |Complete|
2526
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "Class template simd implementation", None, Yin Zhang, |In Progress|
@@ -28,6 +29,7 @@ Section,Description,Dependencies,Assignee,Complete
2829
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask<>::size() <https://reviews.llvm.org/D144363>`_", [parallel.simd.class] simd<>::size(), Yin Zhang, |Complete|
2930
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask default constructor <https://github.com/llvm/llvm-project/pull/70424>`_", None, Yin Zhang, |Complete|
3031
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask broadcast constructor <https://reviews.llvm.org/D156225>`_", None, Yin Zhang, |Complete|
32+
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask implicit type conversion constructor <https://github.com/llvm/llvm-project/pull/71132>`_", None, Yin Zhang, |Complete|
3133
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask subscript operators <https://github.com/llvm/llvm-project/pull/68960>`_", None, Yin Zhang, |Complete|
3234
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "Class template simd_mask implementation", None, Yin Zhang, |In Progress|
3335
| `[parallel.simd.mask.nonmembers] <https://wg21.link/N4808>`_, "simd_mask non-member operations", None, Yin Zhang, |In Progress|

libcxx/include/experimental/__simd/simd.h

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

49+
// implicit type conversion constructor
50+
template <class _Up,
51+
enable_if_t<!is_same_v<_Up, _Tp> && is_same_v<abi_type, simd_abi::fixed_size<size()>> &&
52+
__is_non_narrowing_convertible_v<_Up, value_type>,
53+
int> = 0>
54+
_LIBCPP_HIDE_FROM_ABI simd(const simd<_Up, simd_abi::fixed_size<size()>>& __v) noexcept {
55+
for (size_t __i = 0; __i < size(); __i++) {
56+
(*this)[__i] = static_cast<value_type>(__v[__i]);
57+
}
58+
}
59+
4960
// generator constructor
5061
template <class _Generator, enable_if_t<__can_generate_v<value_type, _Generator, size()>, int> = 0>
5162
explicit _LIBCPP_HIDE_FROM_ABI simd(_Generator&& __g) noexcept

libcxx/include/experimental/__simd/simd_mask.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ class simd_mask {
4343
// broadcast constructor
4444
_LIBCPP_HIDE_FROM_ABI explicit simd_mask(value_type __v) noexcept : __s_(_Impl::__broadcast(__v)) {}
4545

46+
// implicit type conversion constructor
47+
template <class _Up, enable_if_t<!is_same_v<_Up, _Tp> && is_same_v<abi_type, simd_abi::fixed_size<size()>>, int> = 0>
48+
_LIBCPP_HIDE_FROM_ABI simd_mask(const simd_mask<_Up, simd_abi::fixed_size<size()>>& __v) noexcept {
49+
for (size_t __i = 0; __i < size(); __i++) {
50+
(*this)[__i] = __v[__i];
51+
}
52+
}
53+
4654
// scalar access [simd.mask.subscr]
4755
_LIBCPP_HIDE_FROM_ABI reference operator[](size_t __i) noexcept { return reference(__s_, __i); }
4856
_LIBCPP_HIDE_FROM_ABI value_type operator[](size_t __i) const noexcept { return __s_.__get(__i); }
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
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 U> simd(const simd<U, simd_abi::fixed_size<size()>>&) noexcept;
15+
16+
#include "../test_utils.h"
17+
#include <experimental/simd>
18+
19+
namespace ex = std::experimental::parallelism_v2;
20+
21+
template <class T, class SimdAbi, std::size_t array_size>
22+
struct ConversionHelper {
23+
const std::array<T, array_size>& expected_value;
24+
25+
ConversionHelper(const std::array<T, array_size>& value) : expected_value(value) {}
26+
27+
template <class U>
28+
void operator()() const {
29+
if constexpr (!std::is_same_v<U, T> && std::is_same_v<SimdAbi, ex::simd_abi::fixed_size<array_size>> &&
30+
is_non_narrowing_convertible_v<U, T>) {
31+
static_assert(noexcept(ex::simd<T, SimdAbi>(ex::simd<U, SimdAbi>{})));
32+
ex::simd<U, SimdAbi> origin_simd([](U i) { return i; });
33+
ex::simd<T, SimdAbi> simd_from_implicit_conversion(origin_simd);
34+
assert_simd_values_equal<array_size>(simd_from_implicit_conversion, expected_value);
35+
}
36+
}
37+
};
38+
39+
template <class T, std::size_t>
40+
struct CheckConversionSimdCtor {
41+
template <class SimdAbi>
42+
void operator()() {
43+
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
44+
std::array<T, array_size> expected_value;
45+
for (size_t i = 0; i < array_size; ++i)
46+
expected_value[i] = static_cast<T>(i);
47+
48+
types::for_each(arithmetic_no_bool_types(), ConversionHelper<T, SimdAbi, array_size>(expected_value));
49+
}
50+
};
51+
52+
template <class T, class SimdAbi, std::size_t array_size>
53+
struct CheckConversionSimdCtorTraitsHelper {
54+
template <class U>
55+
void operator()() {
56+
if constexpr (!std::is_same_v<U, T>) {
57+
if constexpr (std::is_same_v<SimdAbi, ex::simd_abi::fixed_size<array_size>> &&
58+
is_non_narrowing_convertible_v<U, T>)
59+
static_assert(std::is_convertible_v<ex::simd<U, SimdAbi>, ex::simd<T, SimdAbi>>);
60+
else
61+
static_assert(!std::is_convertible_v<ex::simd<U, SimdAbi>, ex::simd<T, SimdAbi>>);
62+
}
63+
}
64+
};
65+
66+
template <class T, std::size_t>
67+
struct CheckConversionSimdCtorTraits {
68+
template <class SimdAbi>
69+
void operator()() {
70+
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
71+
72+
types::for_each(arithmetic_no_bool_types(), CheckConversionSimdCtorTraitsHelper<T, SimdAbi, array_size>());
73+
}
74+
};
75+
76+
int main(int, char**) {
77+
test_all_simd_abi<CheckConversionSimdCtor>();
78+
test_all_simd_abi<CheckConversionSimdCtorTraits>();
79+
return 0;
80+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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 U> simd_mask(const simd_mask<U, simd_abi::fixed_size<size()>>&) noexcept;
15+
16+
#include "../test_utils.h"
17+
#include <experimental/simd>
18+
19+
namespace ex = std::experimental::parallelism_v2;
20+
21+
template <class T, class SimdAbi, std::size_t array_size>
22+
struct ConversionHelper {
23+
const std::array<bool, array_size>& expected_value;
24+
25+
ConversionHelper(const std::array<bool, array_size>& value) : expected_value(value) {}
26+
27+
template <class U>
28+
void operator()() const {
29+
if constexpr (!std::is_same_v<U, T> && std::is_same_v<SimdAbi, ex::simd_abi::fixed_size<array_size>>) {
30+
static_assert(noexcept(ex::simd_mask<T, SimdAbi>(ex::simd_mask<U, SimdAbi>{})));
31+
ex::simd_mask<U, SimdAbi> origin_mask(false);
32+
ex::simd_mask<T, SimdAbi> mask_from_implicit_conversion(origin_mask);
33+
assert_simd_mask_values_equal<array_size>(mask_from_implicit_conversion, expected_value);
34+
}
35+
}
36+
};
37+
38+
template <class T, std::size_t>
39+
struct CheckConversionMaskCtor {
40+
template <class SimdAbi>
41+
void operator()() {
42+
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
43+
std::array<bool, array_size> expected_value{};
44+
45+
types::for_each(arithmetic_no_bool_types(), ConversionHelper<T, SimdAbi, array_size>(expected_value));
46+
}
47+
};
48+
49+
template <class T, class SimdAbi, std::size_t array_size>
50+
struct CheckConversionMaskCtorTraitsHelper {
51+
template <class U>
52+
void operator()() {
53+
if constexpr (!std::is_same_v<U, T>) {
54+
if constexpr (std::is_same_v<SimdAbi, ex::simd_abi::fixed_size<array_size>>)
55+
static_assert(std::is_convertible_v<ex::simd_mask<U, SimdAbi>, ex::simd_mask<T, SimdAbi>>);
56+
else
57+
static_assert(!std::is_convertible_v<ex::simd_mask<U, SimdAbi>, ex::simd_mask<T, SimdAbi>>);
58+
}
59+
}
60+
};
61+
62+
template <class T, std::size_t>
63+
struct CheckConversionMaskCtorTraits {
64+
template <class SimdAbi>
65+
void operator()() {
66+
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
67+
68+
types::for_each(arithmetic_no_bool_types(), CheckConversionMaskCtorTraitsHelper<T, SimdAbi, array_size>());
69+
}
70+
};
71+
72+
int main(int, char**) {
73+
test_all_simd_abi<CheckConversionMaskCtor>();
74+
test_all_simd_abi<CheckConversionMaskCtorTraits>();
75+
return 0;
76+
}

0 commit comments

Comments
 (0)