Skip to content

Commit 0285c34

Browse files
committed
[libc++] <experimental/simd> Add swap functions of simd reference
1 parent 3a146d5 commit 0285c34

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

libcxx/include/experimental/__simd/reference.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,14 @@
1313
#include <__type_traits/is_assignable.h>
1414
#include <__type_traits/is_same.h>
1515
#include <__utility/forward.h>
16+
#include <__utility/move.h>
1617
#include <cstddef>
1718
#include <experimental/__config>
1819
#include <experimental/__simd/utility.h>
1920

21+
_LIBCPP_PUSH_MACROS
22+
#include <__undef_macros>
23+
2024
#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
2125

2226
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
@@ -55,10 +59,31 @@ class __simd_reference {
5559
__set(static_cast<value_type>(std::forward<_Up>(__v)));
5660
return {__s_, __idx_};
5761
}
62+
63+
friend _LIBCPP_HIDE_FROM_ABI void swap(__simd_reference&& __a, __simd_reference&& __b) noexcept {
64+
value_type __tmp(std::move(__a.__get()));
65+
__a.__set(std::move(__b.__get()));
66+
__b.__set(std::move(__tmp));
67+
}
68+
69+
friend _LIBCPP_HIDE_FROM_ABI void swap(value_type& __a, __simd_reference&& __b) noexcept {
70+
value_type __tmp(std::move(__a));
71+
__a = std::move(__b.__get());
72+
__b.__set(std::move(__tmp));
73+
}
74+
75+
friend _LIBCPP_HIDE_FROM_ABI void swap(__simd_reference&& __a, value_type& __b) noexcept {
76+
value_type __tmp(std::move(__a.__get()));
77+
__a.__set(std::move(__b));
78+
__b = std::move(__tmp);
79+
}
5880
};
5981

6082
} // namespace parallelism_v2
6183
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
6284

6385
#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
86+
87+
_LIBCPP_POP_MACROS
88+
6489
#endif // _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H

libcxx/include/experimental/simd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ inline namespace parallelism_v2 {
7878
#include <experimental/__config>
7979
#include <experimental/__simd/aligned_tag.h>
8080
#include <experimental/__simd/declaration.h>
81+
#include <experimental/__simd/reference.h>
8182
#include <experimental/__simd/scalar.h>
8283
#include <experimental/__simd/simd.h>
8384
#include <experimental/__simd/simd_mask.h>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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+
// friend void swap(reference&& a, reference&& b) noexcept;
15+
// friend void swap(value_type& a, reference&& b) noexcept;
16+
// friend void swap(reference&& a, value_type& b) noexcept;
17+
18+
#include "../test_utils.h"
19+
#include <experimental/simd>
20+
21+
namespace ex = std::experimental::parallelism_v2;
22+
23+
template <class T, std::size_t>
24+
struct CheckSimdRefSwap {
25+
template <class SimdAbi>
26+
void operator()() {
27+
ex::simd<T, SimdAbi> origin_simd_1(1);
28+
ex::simd<T, SimdAbi> origin_simd_2(2);
29+
T value = 3;
30+
31+
static_assert(noexcept(swap(origin_simd_1[0], origin_simd_2[0])));
32+
swap(origin_simd_1[0], origin_simd_2[0]);
33+
assert((origin_simd_1[0] == 2) && (origin_simd_2[0] == 1));
34+
35+
static_assert(noexcept(swap(origin_simd_1[0], value)));
36+
swap(origin_simd_1[0], value);
37+
assert((origin_simd_1[0] == 3) && (value == 2));
38+
39+
static_assert(noexcept(swap(value, origin_simd_2[0])));
40+
swap(value, origin_simd_2[0]);
41+
assert((value == 1) && (origin_simd_2[0] == 2));
42+
}
43+
};
44+
45+
template <class T, std::size_t>
46+
struct CheckMaskRefSwap {
47+
template <class SimdAbi>
48+
void operator()() {
49+
ex::simd_mask<T, SimdAbi> origin_mask_1(true);
50+
ex::simd_mask<T, SimdAbi> origin_mask_2(false);
51+
bool value = true;
52+
53+
static_assert(noexcept(swap(origin_mask_1[0], origin_mask_2[0])));
54+
swap(origin_mask_1[0], origin_mask_2[0]);
55+
assert((origin_mask_1[0] == false) && (origin_mask_2[0] == true));
56+
57+
static_assert(noexcept(swap(origin_mask_1[0], value)));
58+
swap(origin_mask_1[0], value);
59+
assert((origin_mask_1[0] == true) && (value == false));
60+
61+
static_assert(noexcept(swap(value, origin_mask_2[0])));
62+
swap(value, origin_mask_2[0]);
63+
assert((value == true) && (origin_mask_2[0] == false));
64+
}
65+
};
66+
67+
int main(int, char**) {
68+
test_all_simd_abi<CheckSimdRefSwap>();
69+
test_all_simd_abi<CheckMaskRefSwap>();
70+
return 0;
71+
}

0 commit comments

Comments
 (0)