Skip to content

Commit 964c86f

Browse files
committed
[libc++] <experimental/simd> Add compound assignment operators for simd reference
1 parent 5c663aa commit 964c86f

File tree

4 files changed

+129
-5
lines changed

4 files changed

+129
-5
lines changed

libcxx/docs/Status/ParallelismProjects.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Section,Description,Dependencies,Assignee,Complete
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|
1818
| `[parallel.simd.reference] <https://wg21.link/N4808>`_, "`Element references operator= <https://github.com/llvm/llvm-project/pull/70020>`_", None, Yin Zhang, |Complete|
19+
| `[parallel.simd.reference] <https://wg21.link/N4808>`_, "`Element references compound assignment operators <https://github.com/llvm/llvm-project/pull/86761>`_", None, Yin Zhang, |Complete|
1920
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`Class template simd declaration and alias <https://reviews.llvm.org/D144362>`_", [parallel.simd.abi], Yin Zhang, |Complete|
2021
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd<>::size() <https://reviews.llvm.org/D144363>`_", [parallel.simd.traits] simd_size[_v], Yin Zhang, |Complete|
2122
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd default constructor <https://github.com/llvm/llvm-project/pull/70424>`_", None, Yin Zhang, |Complete|

libcxx/include/experimental/__simd/reference.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212

1313
#include <__type_traits/is_assignable.h>
1414
#include <__type_traits/is_same.h>
15+
#include <__type_traits/is_void.h>
16+
#include <__type_traits/void_t.h>
17+
#include <__utility/declval.h>
1518
#include <__utility/forward.h>
1619
#include <cstddef>
1720
#include <experimental/__config>
@@ -55,6 +58,24 @@ class __simd_reference {
5558
__set(static_cast<value_type>(std::forward<_Up>(__v)));
5659
return {__s_, __idx_};
5760
}
61+
62+
# define _LIBCXX_SIMD_REFERENCE_OP_(__op) \
63+
template <class _Up, class = decltype(std::declval<value_type&>() __op## = std::declval<_Up>())> \
64+
__simd_reference _LIBCPP_HIDE_FROM_ABI operator __op##=(_Up&& __v) && noexcept { \
65+
__set(__get() __op static_cast<value_type>(std::forward<_Up>(__v))); \
66+
return {__s_, __idx_}; \
67+
}
68+
_LIBCXX_SIMD_REFERENCE_OP_(+)
69+
_LIBCXX_SIMD_REFERENCE_OP_(-)
70+
_LIBCXX_SIMD_REFERENCE_OP_(*)
71+
_LIBCXX_SIMD_REFERENCE_OP_(/)
72+
_LIBCXX_SIMD_REFERENCE_OP_(%)
73+
_LIBCXX_SIMD_REFERENCE_OP_(&)
74+
_LIBCXX_SIMD_REFERENCE_OP_(|)
75+
_LIBCXX_SIMD_REFERENCE_OP_(^)
76+
_LIBCXX_SIMD_REFERENCE_OP_(<<)
77+
_LIBCXX_SIMD_REFERENCE_OP_(>>)
78+
# undef _LIBCXX_SIMD_REFERENCE_OP_
5879
};
5980

6081
} // namespace parallelism_v2
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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+
// template<class U> reference-=(U&& x) && noexcept;
16+
// template<class U> reference*=(U&& x) && noexcept;
17+
// template<class U> reference/=(U&& x) && noexcept;
18+
// template<class U> reference%=(U&& x) && noexcept;
19+
// template<class U> reference|=(U&& x) && noexcept;
20+
// template<class U> reference&=(U&& x) && noexcept;
21+
// template<class U> reference^=(U&& x) && noexcept;
22+
// template<class U> reference<<=(U&& x) && noexcept;
23+
// template<class U> reference>>=(U&& x) && noexcept;
24+
25+
#include "../test_utils.h"
26+
#include <experimental/simd>
27+
28+
namespace ex = std::experimental::parallelism_v2;
29+
30+
#define LIBCXX_SIMD_REFERENCE_OP_(op, name) \
31+
template <class T, class SimdAbi> \
32+
struct SimdReferenceOperatorHelper##name { \
33+
template <class U> \
34+
void operator()() const { \
35+
ex::simd<T, SimdAbi> origin_simd(static_cast<T>(3)); \
36+
static_assert(noexcept(origin_simd[0] op## = static_cast<U>(2))); \
37+
origin_simd[0] op## = static_cast<U>(2); \
38+
assert((T)origin_simd[0] == (T)(static_cast<T>(3) op static_cast<T>(std::forward<U>(2)))); \
39+
} \
40+
};
41+
LIBCXX_SIMD_REFERENCE_OP_(+, Plus)
42+
LIBCXX_SIMD_REFERENCE_OP_(-, Minus)
43+
LIBCXX_SIMD_REFERENCE_OP_(*, Multiplies)
44+
LIBCXX_SIMD_REFERENCE_OP_(/, Divides)
45+
LIBCXX_SIMD_REFERENCE_OP_(%, Modulus)
46+
LIBCXX_SIMD_REFERENCE_OP_(&, BitAnd)
47+
LIBCXX_SIMD_REFERENCE_OP_(|, BitOr)
48+
LIBCXX_SIMD_REFERENCE_OP_(^, BitXor)
49+
LIBCXX_SIMD_REFERENCE_OP_(<<, ShiftLeft)
50+
LIBCXX_SIMD_REFERENCE_OP_(>>, ShiftRight)
51+
#undef LIBCXX_SIMD_REFERENCE_OP_
52+
53+
#define LIBCXX_SIMD_MASK_REFERENCE_OP_(op, name) \
54+
template <class T, class SimdAbi> \
55+
struct MaskReferenceOperatorHelper##name { \
56+
template <class U> \
57+
void operator()() const { \
58+
ex::simd<T, SimdAbi> origin_simd_mask(true); \
59+
static_assert(noexcept(origin_simd_mask[0] op## = static_cast<U>(false))); \
60+
origin_simd_mask[0] op## = static_cast<U>(false); \
61+
assert((bool)origin_simd_mask[0] == (bool)(true op static_cast<bool>(std::forward<U>(false)))); \
62+
} \
63+
};
64+
LIBCXX_SIMD_MASK_REFERENCE_OP_(&, BitAnd)
65+
LIBCXX_SIMD_MASK_REFERENCE_OP_(|, BitOr)
66+
LIBCXX_SIMD_MASK_REFERENCE_OP_(^, BitXor)
67+
#undef LIBCXX_SIMD_MASK_REFERENCE_OP_
68+
69+
template <class T, std::size_t>
70+
struct CheckReferenceArithOperators {
71+
template <class SimdAbi>
72+
void operator()() {
73+
types::for_each(simd_test_types(), SimdReferenceOperatorHelperPlus<T, SimdAbi>());
74+
types::for_each(simd_test_types(), SimdReferenceOperatorHelperMinus<T, SimdAbi>());
75+
types::for_each(simd_test_types(), SimdReferenceOperatorHelperMultiplies<T, SimdAbi>());
76+
types::for_each(simd_test_types(), SimdReferenceOperatorHelperDivides<T, SimdAbi>());
77+
}
78+
};
79+
80+
template <class T, std::size_t>
81+
struct CheckReferenceIntOperators {
82+
template <class SimdAbi>
83+
void operator()() {
84+
types::for_each(simd_test_integer_types(), SimdReferenceOperatorHelperModulus<T, SimdAbi>());
85+
types::for_each(simd_test_integer_types(), SimdReferenceOperatorHelperBitAnd<T, SimdAbi>());
86+
types::for_each(simd_test_integer_types(), SimdReferenceOperatorHelperBitOr<T, SimdAbi>());
87+
types::for_each(simd_test_integer_types(), SimdReferenceOperatorHelperBitXor<T, SimdAbi>());
88+
types::for_each(simd_test_integer_types(), SimdReferenceOperatorHelperShiftLeft<T, SimdAbi>());
89+
types::for_each(simd_test_integer_types(), SimdReferenceOperatorHelperShiftRight<T, SimdAbi>());
90+
91+
types::for_each(simd_test_integer_types(), MaskReferenceOperatorHelperBitAnd<T, SimdAbi>());
92+
types::for_each(simd_test_integer_types(), MaskReferenceOperatorHelperBitOr<T, SimdAbi>());
93+
types::for_each(simd_test_integer_types(), MaskReferenceOperatorHelperBitXor<T, SimdAbi>());
94+
}
95+
};
96+
97+
int main(int, char**) {
98+
test_all_simd_abi<CheckReferenceArithOperators>();
99+
types::for_each(types::integer_types(), TestAllSimdAbiFunctor<CheckReferenceIntOperators>());
100+
return 0;
101+
}

libcxx/test/std/experimental/simd/test_utils.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,16 @@ using arithmetic_no_bool_types = types::concatenate_t<types::integer_types, type
5050

5151
// For interfaces with vectorizable type template parameters, we only use some common or boundary types
5252
// as template parameters for testing to ensure that the compilation time of a single test does not exceed.
53-
using simd_test_types =
53+
using simd_test_integer_types =
5454
types::type_list<char,
5555
unsigned,
56-
int,
56+
int
5757
#ifndef TEST_HAS_NO_INT128
58-
__int128_t,
58+
,
59+
__int128_t
5960
#endif
60-
float,
61-
double>;
61+
>;
62+
using simd_test_types = types::concatenate_t<simd_test_integer_types, types::type_list<float, double>>;
6263

6364
template <template <class T, std::size_t N> class Func>
6465
void test_all_simd_abi() {

0 commit comments

Comments
 (0)