Skip to content

Commit 2099ce8

Browse files
committed
[libc++] <experimental/simd> Add binary operators for class simd
1 parent 512defe commit 2099ce8

File tree

5 files changed

+392
-0
lines changed

5 files changed

+392
-0
lines changed

libcxx/docs/Status/ParallelismProjects.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Section,Description,Dependencies,Assignee,Complete
3131
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd unary operators <https://github.com/llvm/llvm-project/pull/104764>`_", None, Yin Zhang, |Complete|
3232
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "Class template simd implementation", None, Yin Zhang, |In Progress|
3333
| `[parallel.simd.nonmembers] <https://wg21.link/N4808>`_, "simd non-member operations", None, Yin Zhang, |In Progress|
34+
| `[parallel.simd.nonmembers] <https://wg21.link/N4808>`_, "`simd non-member binary operations <https://github.com/llvm/llvm-project/pull/118744>`_", None, Yin Zhang, |Complete|
3435
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`Class template simd_mask declaration and alias <https://reviews.llvm.org/D144362>`_", [parallel.simd.abi], Yin Zhang, |Complete|
3536
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask<>::size() <https://reviews.llvm.org/D144363>`_", [parallel.simd.class] simd<>::size(), Yin Zhang, |Complete|
3637
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask default constructor <https://github.com/llvm/llvm-project/pull/70424>`_", None, Yin Zhang, |Complete|

libcxx/include/experimental/__simd/scalar.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,54 @@ struct __simd_operations<_Tp, simd_abi::__scalar> {
8282
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __unary_minus(_SimdStorage __s) noexcept {
8383
return {static_cast<_Tp>(-__s.__data)};
8484
}
85+
86+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __plus(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
87+
return {static_cast<_Tp>(__lhs.__data + __rhs.__data)};
88+
}
89+
90+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __minus(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
91+
return {static_cast<_Tp>(__lhs.__data - __rhs.__data)};
92+
}
93+
94+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __multiplies(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
95+
return {static_cast<_Tp>(__lhs.__data * __rhs.__data)};
96+
}
97+
98+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __divides(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
99+
return {static_cast<_Tp>(__lhs.__data / __rhs.__data)};
100+
}
101+
102+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __modulus(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
103+
return {static_cast<_Tp>(__lhs.__data % __rhs.__data)};
104+
}
105+
106+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __bitwise_and(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
107+
return {static_cast<_Tp>(__lhs.__data & __rhs.__data)};
108+
}
109+
110+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __bitwise_or(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
111+
return {static_cast<_Tp>(__lhs.__data | __rhs.__data)};
112+
}
113+
114+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __bitwise_xor(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
115+
return {static_cast<_Tp>(__lhs.__data ^ __rhs.__data)};
116+
}
117+
118+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __shift_left(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
119+
return {static_cast<_Tp>(__lhs.__data << __rhs.__data)};
120+
}
121+
122+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __shift_right(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
123+
return {static_cast<_Tp>(__lhs.__data >> __rhs.__data)};
124+
}
125+
126+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __shift_left(_SimdStorage __lhs, int __rhs) noexcept {
127+
return {static_cast<_Tp>(__lhs.__data << __rhs)};
128+
}
129+
130+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __shift_right(_SimdStorage __lhs, int __rhs) noexcept {
131+
return {static_cast<_Tp>(__lhs.__data >> __rhs)};
132+
}
85133
};
86134

87135
template <class _Tp>

libcxx/include/experimental/__simd/simd.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,39 @@ class __simd_int_operators<_Simd, _Impl, true> {
3737
_LIBCPP_HIDE_FROM_ABI _Simd operator~() const noexcept {
3838
return _Simd(_Impl::__bitwise_not((*static_cast<const _Simd*>(this)).__s_), _Simd::__storage_tag);
3939
}
40+
41+
// binary operators for integral _Tp
42+
friend _LIBCPP_HIDE_FROM_ABI _Simd operator%(const _Simd& __lhs, const _Simd& __rhs) noexcept {
43+
return _Simd(_Impl::__modulus(__lhs.__s_, __rhs.__s_), _Simd::__storage_tag);
44+
}
45+
46+
friend _LIBCPP_HIDE_FROM_ABI _Simd operator&(const _Simd& __lhs, const _Simd& __rhs) noexcept {
47+
return _Simd(_Impl::__bitwise_and(__lhs.__s_, __rhs.__s_), _Simd::__storage_tag);
48+
}
49+
50+
friend _LIBCPP_HIDE_FROM_ABI _Simd operator|(const _Simd& __lhs, const _Simd& __rhs) noexcept {
51+
return _Simd(_Impl::__bitwise_or(__lhs.__s_, __rhs.__s_), _Simd::__storage_tag);
52+
}
53+
54+
friend _LIBCPP_HIDE_FROM_ABI _Simd operator^(const _Simd& __lhs, const _Simd& __rhs) noexcept {
55+
return _Simd(_Impl::__bitwise_xor(__lhs.__s_, __rhs.__s_), _Simd::__storage_tag);
56+
}
57+
58+
friend _LIBCPP_HIDE_FROM_ABI _Simd operator<<(const _Simd& __lhs, const _Simd& __rhs) noexcept {
59+
return _Simd(_Impl::__shift_left(__lhs.__s_, __rhs.__s_), _Simd::__storage_tag);
60+
}
61+
62+
friend _LIBCPP_HIDE_FROM_ABI _Simd operator>>(const _Simd& __lhs, const _Simd& __rhs) noexcept {
63+
return _Simd(_Impl::__shift_right(__lhs.__s_, __rhs.__s_), _Simd::__storage_tag);
64+
}
65+
66+
friend _LIBCPP_HIDE_FROM_ABI _Simd operator<<(const _Simd& __lhs, int __rhs) noexcept {
67+
return _Simd(_Impl::__shift_left(__lhs.__s_, __rhs), _Simd::__storage_tag);
68+
}
69+
70+
friend _LIBCPP_HIDE_FROM_ABI _Simd operator>>(const _Simd& __lhs, int __rhs) noexcept {
71+
return _Simd(_Impl::__shift_right(__lhs.__s_, __rhs), _Simd::__storage_tag);
72+
}
4073
};
4174

4275
// class template simd [simd.class]
@@ -137,6 +170,23 @@ class simd : public __simd_int_operators<simd<_Tp, _Abi>, __simd_operations<_Tp,
137170
_LIBCPP_HIDE_FROM_ABI simd operator+() const noexcept { return *this; }
138171

139172
_LIBCPP_HIDE_FROM_ABI simd operator-() const noexcept { return simd(_Impl::__unary_minus(__s_), __storage_tag); }
173+
174+
// binary operators
175+
friend _LIBCPP_HIDE_FROM_ABI simd operator+(const simd& __lhs, const simd& __rhs) noexcept {
176+
return simd(_Impl::__plus(__lhs.__s_, __rhs.__s_), __storage_tag);
177+
}
178+
179+
friend _LIBCPP_HIDE_FROM_ABI simd operator-(const simd& __lhs, const simd& __rhs) noexcept {
180+
return simd(_Impl::__minus(__lhs.__s_, __rhs.__s_), __storage_tag);
181+
}
182+
183+
friend _LIBCPP_HIDE_FROM_ABI simd operator*(const simd& __lhs, const simd& __rhs) noexcept {
184+
return simd(_Impl::__multiplies(__lhs.__s_, __rhs.__s_), __storage_tag);
185+
}
186+
187+
friend _LIBCPP_HIDE_FROM_ABI simd operator/(const simd& __lhs, const simd& __rhs) noexcept {
188+
return simd(_Impl::__divides(__lhs.__s_, __rhs.__s_), __storage_tag);
189+
}
140190
};
141191

142192
template <class _Tp, class _Abi>

libcxx/include/experimental/__simd/vec_ext.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ template <class _Tp, int _Np>
3939
struct __simd_storage<_Tp, simd_abi::__vec_ext<_Np>> {
4040
_Tp __data __attribute__((__vector_size__(std::__bit_ceil((sizeof(_Tp) * _Np)))));
4141

42+
static constexpr bool __is_partial_v = (_Np < (sizeof(__data) / sizeof(_Tp)));
43+
4244
_LIBCPP_HIDE_FROM_ABI _Tp __get(size_t __idx) const noexcept {
4345
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx < _Np, "Index is out of bounds");
4446
return __data[__idx];
@@ -47,6 +49,17 @@ struct __simd_storage<_Tp, simd_abi::__vec_ext<_Np>> {
4749
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx < _Np, "Index is out of bounds");
4850
__data[__idx] = __v;
4951
}
52+
53+
_LIBCPP_HIDE_FROM_ABI __simd_storage __make_padding_nonzero() const noexcept {
54+
__simd_storage __result = *this;
55+
if constexpr (__is_partial_v) {
56+
constexpr size_t __full_size = sizeof(__data) / sizeof(_Tp);
57+
for (size_t __i = _Np; __i < __full_size; ++__i) {
58+
__result.__data[__i] = _Tp(1);
59+
}
60+
}
61+
return __result;
62+
}
5063
};
5164

5265
template <class _Tp, int _Np>
@@ -97,6 +110,60 @@ struct __simd_operations<_Tp, simd_abi::__vec_ext<_Np>> {
97110
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __bitwise_not(_SimdStorage __s) noexcept { return {~__s.__data}; }
98111

99112
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __unary_minus(_SimdStorage __s) noexcept { return {-__s.__data}; }
113+
114+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __plus(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
115+
return {__lhs.__data + __rhs.__data};
116+
}
117+
118+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __minus(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
119+
return {__lhs.__data - __rhs.__data};
120+
}
121+
122+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __multiplies(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
123+
return {__lhs.__data * __rhs.__data};
124+
}
125+
126+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __divides(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
127+
if constexpr (!_SimdStorage::__is_partial_v)
128+
return {__lhs.__data / __rhs.__data};
129+
else
130+
return {__lhs.__data / __rhs.__make_padding_nonzero().__data};
131+
}
132+
133+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __modulus(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
134+
if constexpr (!_SimdStorage::__is_partial_v)
135+
return {__lhs.__data % __rhs.__data};
136+
else
137+
return {__lhs.__data % __rhs.__make_padding_nonzero().__data};
138+
}
139+
140+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __bitwise_and(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
141+
return {__lhs.__data & __rhs.__data};
142+
}
143+
144+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __bitwise_or(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
145+
return {__lhs.__data | __rhs.__data};
146+
}
147+
148+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __bitwise_xor(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
149+
return {__lhs.__data ^ __rhs.__data};
150+
}
151+
152+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __shift_left(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
153+
return {__lhs.__data << __rhs.__data};
154+
}
155+
156+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __shift_right(_SimdStorage __lhs, _SimdStorage __rhs) noexcept {
157+
return {__lhs.__data >> __rhs.__data};
158+
}
159+
160+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __shift_left(_SimdStorage __lhs, int __rhs) noexcept {
161+
return {__lhs.__data << __rhs};
162+
}
163+
164+
static _LIBCPP_HIDE_FROM_ABI _SimdStorage __shift_right(_SimdStorage __lhs, int __rhs) noexcept {
165+
return {__lhs.__data >> __rhs};
166+
}
100167
};
101168

102169
template <class _Tp, int _Np>

0 commit comments

Comments
 (0)