[libcxx-commits] [libcxx] [libc++] <experimental/simd> Add compound assignment operators for simd reference (PR #86761)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Apr 2 01:13:01 PDT 2024
https://github.com/joy2myself updated https://github.com/llvm/llvm-project/pull/86761
>From e73bfe32ccc5e2ecc5c53f3b12a957a1f746378e Mon Sep 17 00:00:00 2001
From: Yin Zhang <zhangyin2018 at iscas.ac.cn>
Date: Tue, 9 Jan 2024 17:04:16 +0800
Subject: [PATCH] [libc++] <experimental/simd> Add compound assignment
operators for simd reference
---
.../include/experimental/__simd/reference.h | 21 ++++
.../reference_operators.pass.cpp | 106 ++++++++++++++++++
2 files changed, 127 insertions(+)
create mode 100644 libcxx/test/std/experimental/simd/simd.reference/reference_operators.pass.cpp
diff --git a/libcxx/include/experimental/__simd/reference.h b/libcxx/include/experimental/__simd/reference.h
index 7efbba96ec71b1..9eeb2582d6eb6d 100644
--- a/libcxx/include/experimental/__simd/reference.h
+++ b/libcxx/include/experimental/__simd/reference.h
@@ -12,6 +12,7 @@
#include <__type_traits/is_assignable.h>
#include <__type_traits/is_same.h>
+#include <__type_traits/is_void.h>
#include <__utility/forward.h>
#include <cstddef>
#include <experimental/__config>
@@ -55,6 +56,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;
+}
More information about the libcxx-commits
mailing list