Skip to content

[libc++] <experimental/simd> Add implicit type conversion constructor for class simd/simd_mask #71132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libcxx/docs/Status/ParallelismProjects.csv
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Section,Description,Dependencies,Assignee,Complete
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd<>::size() <https://reviews.llvm.org/D144363>`_", [parallel.simd.traits] simd_size[_v], Yin Zhang, |Complete|
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd default constructor <https://github.com/llvm/llvm-project/pull/70424>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd broadcast constructor <https://reviews.llvm.org/D156225>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd implicit type conversion constructor <https://github.com/llvm/llvm-project/pull/71132>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd generate constructor <https://reviews.llvm.org/D159442>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd subscript operators <https://github.com/llvm/llvm-project/pull/68960>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "Class template simd implementation", None, Yin Zhang, |In Progress|
Expand All @@ -28,6 +29,7 @@ Section,Description,Dependencies,Assignee,Complete
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask<>::size() <https://reviews.llvm.org/D144363>`_", [parallel.simd.class] simd<>::size(), Yin Zhang, |Complete|
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask default constructor <https://github.com/llvm/llvm-project/pull/70424>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask broadcast constructor <https://reviews.llvm.org/D156225>`_", None, Yin Zhang, |Complete|
| `[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|
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask subscript operators <https://github.com/llvm/llvm-project/pull/68960>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "Class template simd_mask implementation", None, Yin Zhang, |In Progress|
| `[parallel.simd.mask.nonmembers] <https://wg21.link/N4808>`_, "simd_mask non-member operations", None, Yin Zhang, |In Progress|
11 changes: 11 additions & 0 deletions libcxx/include/experimental/__simd/simd.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ class simd {
template <class _Up, enable_if_t<__can_broadcast_v<value_type, __remove_cvref_t<_Up>>, int> = 0>
_LIBCPP_HIDE_FROM_ABI simd(_Up&& __v) noexcept : __s_(_Impl::__broadcast(static_cast<value_type>(__v))) {}

// implicit type conversion constructor
template <class _Up,
enable_if_t<!is_same_v<_Up, _Tp> && is_same_v<abi_type, simd_abi::fixed_size<size()>> &&
__is_non_narrowing_convertible_v<_Up, value_type>,
int> = 0>
_LIBCPP_HIDE_FROM_ABI simd(const simd<_Up, simd_abi::fixed_size<size()>>& __v) noexcept {
for (size_t __i = 0; __i < size(); __i++) {
(*this)[__i] = static_cast<value_type>(__v[__i]);
}
}

// generator constructor
template <class _Generator, enable_if_t<__can_generate_v<value_type, _Generator, size()>, int> = 0>
explicit _LIBCPP_HIDE_FROM_ABI simd(_Generator&& __g) noexcept
Expand Down
8 changes: 8 additions & 0 deletions libcxx/include/experimental/__simd/simd_mask.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ class simd_mask {
// broadcast constructor
_LIBCPP_HIDE_FROM_ABI explicit simd_mask(value_type __v) noexcept : __s_(_Impl::__broadcast(__v)) {}

// implicit type conversion constructor
template <class _Up, enable_if_t<!is_same_v<_Up, _Tp> && is_same_v<abi_type, simd_abi::fixed_size<size()>>, int> = 0>
_LIBCPP_HIDE_FROM_ABI simd_mask(const simd_mask<_Up, simd_abi::fixed_size<size()>>& __v) noexcept {
for (size_t __i = 0; __i < size(); __i++) {
(*this)[__i] = __v[__i];
}
}

// scalar access [simd.mask.subscr]
_LIBCPP_HIDE_FROM_ABI reference operator[](size_t __i) noexcept { return reference(__s_, __i); }
_LIBCPP_HIDE_FROM_ABI value_type operator[](size_t __i) const noexcept { return __s_.__get(__i); }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14

// <experimental/simd>
//
// [simd.class]
// template<class U> simd(const simd<U, simd_abi::fixed_size<size()>>&) noexcept;

#include "../test_utils.h"
#include <experimental/simd>

namespace ex = std::experimental::parallelism_v2;

template <class T, class SimdAbi, std::size_t array_size>
struct ConversionHelper {
const std::array<T, array_size>& expected_value;

ConversionHelper(const std::array<T, array_size>& value) : expected_value(value) {}

template <class U>
void operator()() const {
if constexpr (!std::is_same_v<U, T> && std::is_same_v<SimdAbi, ex::simd_abi::fixed_size<array_size>> &&
is_non_narrowing_convertible_v<U, T>) {
static_assert(noexcept(ex::simd<T, SimdAbi>(ex::simd<U, SimdAbi>{})));
ex::simd<U, SimdAbi> origin_simd([](U i) { return i; });
ex::simd<T, SimdAbi> simd_from_implicit_conversion(origin_simd);
assert_simd_values_equal<array_size>(simd_from_implicit_conversion, expected_value);
}
}
};

template <class T, std::size_t>
struct CheckConversionSimdCtor {
template <class SimdAbi>
void operator()() {
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
std::array<T, array_size> expected_value;
for (size_t i = 0; i < array_size; ++i)
expected_value[i] = static_cast<T>(i);

types::for_each(arithmetic_no_bool_types(), ConversionHelper<T, SimdAbi, array_size>(expected_value));
}
};

template <class T, class SimdAbi, std::size_t array_size>
struct CheckConversionSimdCtorTraitsHelper {
template <class U>
void operator()() {
if constexpr (!std::is_same_v<U, T>) {
if constexpr (std::is_same_v<SimdAbi, ex::simd_abi::fixed_size<array_size>> &&
is_non_narrowing_convertible_v<U, T>)
static_assert(std::is_convertible_v<ex::simd<U, SimdAbi>, ex::simd<T, SimdAbi>>);
else
static_assert(!std::is_convertible_v<ex::simd<U, SimdAbi>, ex::simd<T, SimdAbi>>);
}
}
};

template <class T, std::size_t>
struct CheckConversionSimdCtorTraits {
template <class SimdAbi>
void operator()() {
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;

types::for_each(arithmetic_no_bool_types(), CheckConversionSimdCtorTraitsHelper<T, SimdAbi, array_size>());
}
};

int main(int, char**) {
test_all_simd_abi<CheckConversionSimdCtor>();
test_all_simd_abi<CheckConversionSimdCtorTraits>();
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14

// <experimental/simd>
//
// [simd.class]
// template<class U> simd_mask(const simd_mask<U, simd_abi::fixed_size<size()>>&) noexcept;

#include "../test_utils.h"
#include <experimental/simd>

namespace ex = std::experimental::parallelism_v2;

template <class T, class SimdAbi, std::size_t array_size>
struct ConversionHelper {
const std::array<bool, array_size>& expected_value;

ConversionHelper(const std::array<bool, array_size>& value) : expected_value(value) {}

template <class U>
void operator()() const {
if constexpr (!std::is_same_v<U, T> && std::is_same_v<SimdAbi, ex::simd_abi::fixed_size<array_size>>) {
static_assert(noexcept(ex::simd_mask<T, SimdAbi>(ex::simd_mask<U, SimdAbi>{})));
ex::simd_mask<U, SimdAbi> origin_mask(false);
ex::simd_mask<T, SimdAbi> mask_from_implicit_conversion(origin_mask);
assert_simd_mask_values_equal<array_size>(mask_from_implicit_conversion, expected_value);
}
}
};

template <class T, std::size_t>
struct CheckConversionMaskCtor {
template <class SimdAbi>
void operator()() {
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
std::array<bool, array_size> expected_value{};

types::for_each(arithmetic_no_bool_types(), ConversionHelper<T, SimdAbi, array_size>(expected_value));
}
};

template <class T, class SimdAbi, std::size_t array_size>
struct CheckConversionMaskCtorTraitsHelper {
template <class U>
void operator()() {
if constexpr (!std::is_same_v<U, T>) {
if constexpr (std::is_same_v<SimdAbi, ex::simd_abi::fixed_size<array_size>>)
static_assert(std::is_convertible_v<ex::simd_mask<U, SimdAbi>, ex::simd_mask<T, SimdAbi>>);
else
static_assert(!std::is_convertible_v<ex::simd_mask<U, SimdAbi>, ex::simd_mask<T, SimdAbi>>);
}
}
};

template <class T, std::size_t>
struct CheckConversionMaskCtorTraits {
template <class SimdAbi>
void operator()() {
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;

types::for_each(arithmetic_no_bool_types(), CheckConversionMaskCtorTraitsHelper<T, SimdAbi, array_size>());
}
};

int main(int, char**) {
test_all_simd_abi<CheckConversionMaskCtor>();
test_all_simd_abi<CheckConversionMaskCtorTraits>();
return 0;
}