-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc++] <experimental/simd> Add compound assignment operators for simd reference #86761
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
Conversation
@llvm/pr-subscribers-libcxx Author: ZhangYin (joy2myself) ChangesFull diff: https://github.com/llvm/llvm-project/pull/86761.diff 2 Files Affected:
diff --git a/libcxx/include/experimental/__simd/reference.h b/libcxx/include/experimental/__simd/reference.h
index 7efbba96ec71b1..ea8a3742901274 100644
--- a/libcxx/include/experimental/__simd/reference.h
+++ b/libcxx/include/experimental/__simd/reference.h
@@ -55,6 +55,26 @@ class __simd_reference {
__set(static_cast<value_type>(std::forward<_Up>(__v)));
return {__s_, __idx_};
}
+
+# define _LIBCXX_SIMD_REFERENCE_OP_(__op) \
+ template <class _Up> \
+ enable_if_t<is_void_v<void_t<decltype(std::declval<value_type&>() __op## = std::declval<_Up>())>>, \
+ __simd_reference> _LIBCPP_HIDE_FROM_ABI \
+ operator __op##=(_Up&& __v)&& noexcept { \
+ __set(__get() __op static_cast<value_type>(std::forward<_Up>(__v))); \
+ return {__s_, __idx_}; \
+ }
+ _LIBCXX_SIMD_REFERENCE_OP_(+)
+ _LIBCXX_SIMD_REFERENCE_OP_(-)
+ _LIBCXX_SIMD_REFERENCE_OP_(*)
+ _LIBCXX_SIMD_REFERENCE_OP_(/)
+ _LIBCXX_SIMD_REFERENCE_OP_(%)
+ _LIBCXX_SIMD_REFERENCE_OP_(&)
+ _LIBCXX_SIMD_REFERENCE_OP_(|)
+ _LIBCXX_SIMD_REFERENCE_OP_(^)
+ _LIBCXX_SIMD_REFERENCE_OP_(<<)
+ _LIBCXX_SIMD_REFERENCE_OP_(>>)
+# undef _LIBCXX_SIMD_REFERENCE_OP_
};
} // namespace parallelism_v2
diff --git a/libcxx/test/std/experimental/simd/simd.reference/reference_operators.pass.cpp b/libcxx/test/std/experimental/simd/simd.reference/reference_operators.pass.cpp
new file mode 100644
index 00000000000000..c6b5003ad49092
--- /dev/null
+++ b/libcxx/test/std/experimental/simd/simd.reference/reference_operators.pass.cpp
@@ -0,0 +1,106 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.reference]
+// template<class U> reference+=(U&& x) && noexcept;
+// template<class U> reference-=(U&& x) && noexcept;
+// template<class U> reference*=(U&& x) && noexcept;
+// template<class U> reference/=(U&& x) && noexcept;
+// template<class U> reference%=(U&& x) && noexcept;
+// template<class U> reference|=(U&& x) && noexcept;
+// template<class U> reference&=(U&& x) && noexcept;
+// template<class U> reference^=(U&& x) && noexcept;
+// template<class U> reference<<=(U&& x) && noexcept;
+// template<class U> reference>>=(U&& x) && noexcept;
+
+#include "../test_utils.h"
+#include <experimental/simd>
+#include <iostream>
+
+namespace ex = std::experimental::parallelism_v2;
+
+#define LIBCXX_SIMD_REFERENCE_OP_(op, name) \
+ template <class T, class SimdAbi> \
+ struct SimdReferenceOperatorHelper##name { \
+ template <class U> \
+ void operator()() const { \
+ ex::simd<T, SimdAbi> origin_simd(2); \
+ for (size_t i = 0; i < origin_simd.size(); ++i) { \
+ static_assert(noexcept(origin_simd[i] op## = static_cast<U>(i + 1))); \
+ origin_simd[i] op## = static_cast<U>(i + 1); \
+ assert((T)origin_simd[i] == (T)(static_cast<T>(2) op static_cast<T>(std::forward<U>(i + 1)))); \
+ } \
+ } \
+ };
+LIBCXX_SIMD_REFERENCE_OP_(+, Plus)
+LIBCXX_SIMD_REFERENCE_OP_(-, Minus)
+LIBCXX_SIMD_REFERENCE_OP_(*, Multiplies)
+LIBCXX_SIMD_REFERENCE_OP_(/, Divides)
+LIBCXX_SIMD_REFERENCE_OP_(%, Modulus)
+LIBCXX_SIMD_REFERENCE_OP_(&, BitAnd)
+LIBCXX_SIMD_REFERENCE_OP_(|, BitOr)
+LIBCXX_SIMD_REFERENCE_OP_(^, BitXor)
+LIBCXX_SIMD_REFERENCE_OP_(<<, ShiftLeft)
+LIBCXX_SIMD_REFERENCE_OP_(>>, ShiftRight)
+#undef LIBCXX_SIMD_REFERENCE_OP_
+
+#define LIBCXX_SIMD_MASK_REFERENCE_OP_(op, name) \
+ template <class T, class SimdAbi> \
+ struct MaskReferenceOperatorHelper##name { \
+ template <class U> \
+ void operator()() const { \
+ ex::simd<T, SimdAbi> origin_simd_mask(true); \
+ for (size_t i = 0; i < origin_simd_mask.size(); ++i) { \
+ static_assert(noexcept(origin_simd_mask[i] op## = static_cast<U>(i % 2))); \
+ origin_simd_mask[i] op## = static_cast<U>(i % 2); \
+ assert((bool)origin_simd_mask[i] == (bool)(true op static_cast<bool>(std::forward<U>(i % 2)))); \
+ } \
+ } \
+ };
+LIBCXX_SIMD_MASK_REFERENCE_OP_(&, BitAnd)
+LIBCXX_SIMD_MASK_REFERENCE_OP_(|, BitOr)
+LIBCXX_SIMD_MASK_REFERENCE_OP_(^, BitXor)
+#undef LIBCXX_SIMD_MASK_REFERENCE_OP_
+
+template <class T, std::size_t>
+struct CheckReferenceArithOperators {
+ template <class SimdAbi>
+ void operator()() {
+ types::for_each(simd_test_types(), SimdReferenceOperatorHelperPlus<T, SimdAbi>());
+ types::for_each(simd_test_types(), SimdReferenceOperatorHelperMinus<T, SimdAbi>());
+ types::for_each(simd_test_types(), SimdReferenceOperatorHelperMultiplies<T, SimdAbi>());
+ types::for_each(simd_test_types(), SimdReferenceOperatorHelperDivides<T, SimdAbi>());
+ }
+};
+
+template <class T, std::size_t>
+struct CheckReferenceIntOperators {
+ template <class SimdAbi>
+ void operator()() {
+ types::for_each(types::integer_types(), SimdReferenceOperatorHelperModulus<T, SimdAbi>());
+ types::for_each(types::integer_types(), SimdReferenceOperatorHelperBitAnd<T, SimdAbi>());
+ types::for_each(types::integer_types(), SimdReferenceOperatorHelperBitOr<T, SimdAbi>());
+ types::for_each(types::integer_types(), SimdReferenceOperatorHelperBitXor<T, SimdAbi>());
+ types::for_each(types::integer_types(), SimdReferenceOperatorHelperShiftLeft<T, SimdAbi>());
+ types::for_each(types::integer_types(), SimdReferenceOperatorHelperShiftRight<T, SimdAbi>());
+
+ types::for_each(types::integer_types(), MaskReferenceOperatorHelperBitAnd<T, SimdAbi>());
+ types::for_each(types::integer_types(), MaskReferenceOperatorHelperBitOr<T, SimdAbi>());
+ types::for_each(types::integer_types(), MaskReferenceOperatorHelperBitXor<T, SimdAbi>());
+ }
+};
+
+int main(int, char**) {
+ test_all_simd_abi<CheckReferenceArithOperators>();
+ types::for_each(types::integer_types(), TestAllSimdAbiFunctor<CheckReferenceIntOperators>());
+ return 0;
+}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
c3eab8e
to
9156a42
Compare
22a86a8
to
964c86f
Compare
@philnik777 Hi! This and the other two patches (#86478, #88091) are ready for review. |
@philnik777 Any comments here and #88091? The CI errors don't seem related. |
@philnik777 Gentle ping. |
Hi @philnik777, Just following up on this PR and #88091. Could you please take a look when you get a chance? I have some follow-up patches ready, but they may depend on these currently open PRs. It would be great if these two PRs could be merged soon. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the slow review, I didn't have a lot of time recently.
libcxx/test/std/experimental/simd/simd.reference/reference_operators.pass.cpp
Outdated
Show resolved
Hide resolved
fe8a3bb
to
7665eb8
Compare
7665eb8
to
85f7198
Compare
@philnik777 Hello, I have removed all macro definitions according to your comment. However, the compiler does not allow lambda expressions to be passed directly into the template, so I use struct to wrap lambda expressions to pass template parameters in test files. In addition, due to the error of insufficient memory or flash capacity in ARMv7 CI, I split the test cases into two test files. Any other comments? |
85f7198
to
663129b
Compare
No description provided.