Skip to content

Commit c4184e4

Browse files
committed
[libc++] <experimental/simd> Add assignment operator of simd reference
1 parent f3b20cb commit c4184e4

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

libcxx/docs/Status/ParallelismProjects.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Section,Description,Dependencies,Assignee,Complete
1515
| `[parallel.simd.traits] <https://wg21.link/N4808>`_, "simd type traits resize_simd", None, Yin Zhang, |In Progress|
1616
| `[parallel.simd.whereexpr] <https://wg21.link/N4808>`_, "Where expression class templates", None, Yin Zhang, |In Progress|
1717
| `[parallel.simd.reference] <https://wg21.link/N4808>`_, "`Element references operator value_type() <https://github.com/llvm/llvm-project/pull/68960>`_", None, Yin Zhang, |Complete|
18+
| `[parallel.simd.reference] <https://wg21.link/N4808>`_, "`Element references operator= <https://github.com/llvm/llvm-project/pull/70020>`_", None, Yin Zhang, |Complete|
1819
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`Class template simd declaration and alias <https://reviews.llvm.org/D144362>`_", [parallel.simd.abi], Yin Zhang, |Complete|
1920
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd<>::size() <https://reviews.llvm.org/D144363>`_", [parallel.simd.traits] simd_size[_v], Yin Zhang, |Complete|
2021
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd broadcast constructor <https://reviews.llvm.org/D156225>`_", None, Yin Zhang, |Complete|

libcxx/include/experimental/__simd/reference.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#ifndef _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H
1111
#define _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H
1212

13+
#include <__type_traits/is_assignable.h>
1314
#include <experimental/__simd/utility.h>
1415

1516
#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
@@ -44,6 +45,12 @@ class __simd_reference {
4445
__simd_reference(const __simd_reference&) = delete;
4546

4647
_LIBCPP_HIDE_FROM_ABI operator value_type() const noexcept { return __get(); }
48+
49+
template <class _Up, enable_if_t<is_assignable_v<value_type&, _Up&&>, int> = 0>
50+
_LIBCPP_HIDE_FROM_ABI __simd_reference operator=(_Up&& __v) && noexcept {
51+
__set(static_cast<value_type>(std::forward<_Up>(__v)));
52+
return {__s_, __idx_};
53+
}
4754
};
4855

4956
} // namespace parallelism_v2
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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.reference]
14+
// template<class U> reference=(U&& x) && noexcept;
15+
//
16+
// XFAIL: LIBCXX-AIX-FIXME
17+
18+
#include "../test_utils.h"
19+
#include <experimental/simd>
20+
21+
namespace ex = std::experimental::parallelism_v2;
22+
23+
template <class T, class SimdAbi>
24+
struct CheckSimdReferenceAssignmentHelper {
25+
template <class U>
26+
void operator()() const {
27+
if constexpr (std::is_assignable_v<T&, U&&>) {
28+
ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
29+
for (size_t i = 0; i < origin_simd.size(); ++i) {
30+
static_assert(noexcept(origin_simd[i] = static_cast<U>(i + 1)));
31+
origin_simd[i] = static_cast<U>(i + 1);
32+
assert(origin_simd[i] == static_cast<T>(std::forward<U>(i + 1)));
33+
}
34+
}
35+
}
36+
};
37+
38+
template <class T, class SimdAbi>
39+
struct CheckMaskReferenceAssignmentHelper {
40+
template <class U>
41+
void operator()() const {
42+
if constexpr (std::is_assignable_v<bool&, U&&>) {
43+
ex::simd_mask<T, SimdAbi> origin_mask(true);
44+
for (size_t i = 0; i < origin_mask.size(); ++i) {
45+
static_assert(noexcept(origin_mask[i] = static_cast<U>(i + 1)));
46+
origin_mask[i] = static_cast<U>(i % 2);
47+
assert(origin_mask[i] == static_cast<T>(std::forward<U>(i % 2)));
48+
}
49+
}
50+
}
51+
};
52+
53+
template <class T, class SimdAbi>
54+
struct CheckReferenceAssignmentTraitsHelper {
55+
template <class U>
56+
void operator()() const {
57+
if constexpr (std::is_assignable_v<T&, U&&>)
58+
static_assert(std::is_assignable_v<typename ex::simd<T, SimdAbi>::reference&&, U&&>);
59+
else
60+
static_assert(!std::is_assignable_v<typename ex::simd<T, SimdAbi>::reference&&, U&&>);
61+
62+
if constexpr (std::is_assignable_v<bool&, U&&>)
63+
static_assert(std::is_assignable_v<typename ex::simd_mask<T, SimdAbi>::reference&&, U&&>);
64+
else
65+
static_assert(!std::is_assignable_v<typename ex::simd_mask<T, SimdAbi>::reference&&, U&&>);
66+
}
67+
};
68+
69+
template <class T, std::size_t>
70+
struct CheckReferenceAssignment {
71+
template <class SimdAbi>
72+
void operator()() {
73+
types::for_each(arithmetic_no_bool_types(), CheckSimdReferenceAssignmentHelper<T, SimdAbi>());
74+
types::for_each(arithmetic_no_bool_types(), CheckMaskReferenceAssignmentHelper<T, SimdAbi>());
75+
76+
types::for_each(arithmetic_no_bool_types(), CheckReferenceAssignmentTraitsHelper<T, SimdAbi>());
77+
}
78+
};
79+
80+
int main(int, char**) {
81+
test_all_simd_abi<CheckReferenceAssignment>();
82+
return 0;
83+
}

0 commit comments

Comments
 (0)