Skip to content

Commit a18ff21

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

File tree

4 files changed

+106
-0
lines changed

4 files changed

+106
-0
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 swap functions <https://github.com/llvm/llvm-project/pull/86478>`_", 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: 33 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,39 @@ class __simd_reference {
5559
__set(static_cast<value_type>(std::forward<_Up>(__v)));
5660
return {__s_, __idx_};
5761
}
62+
63+
friend void swap(__simd_reference<_Tp, _Storage, _Vp>&& __a, __simd_reference<_Tp, _Storage, _Vp>&& __b) noexcept;
64+
friend void swap(_Vp& __a, __simd_reference<_Tp, _Storage, _Vp>&& __b) noexcept;
65+
friend void swap(__simd_reference<_Tp, _Storage, _Vp>&& __a, _Vp& __b) noexcept;
5866
};
5967

68+
template <class _Tp, class _Storage, class _Vp>
69+
_LIBCPP_HIDE_FROM_ABI void
70+
swap(__simd_reference<_Tp, _Storage, _Vp>&& __a, __simd_reference<_Tp, _Storage, _Vp>&& __b) noexcept {
71+
_Vp __tmp(std::move(__a));
72+
std::move(__a) = std::move(__b);
73+
std::move(__b) = std::move(__tmp);
74+
}
75+
76+
template <class _Tp, class _Storage, class _Vp>
77+
_LIBCPP_HIDE_FROM_ABI void swap(_Vp& __a, __simd_reference<_Tp, _Storage, _Vp>&& __b) noexcept {
78+
_Vp __tmp(std::move(__a));
79+
__a = std::move(__b);
80+
std::move(__b) = std::move(__tmp);
81+
}
82+
83+
template <class _Tp, class _Storage, class _Vp>
84+
_LIBCPP_HIDE_FROM_ABI void swap(__simd_reference<_Tp, _Storage, _Vp>&& __a, _Vp& __b) noexcept {
85+
_Vp __tmp(std::move(__a));
86+
std::move(__a) = std::move(__b);
87+
__b = std::move(__tmp);
88+
}
89+
6090
} // namespace parallelism_v2
6191
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
6292

6393
#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
94+
95+
_LIBCPP_POP_MACROS
96+
6497
#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(ex::swap(std::move(origin_simd_1[0]), std::move(origin_simd_2[0]))));
32+
ex::swap(std::move(origin_simd_1[0]), std::move(origin_simd_2[0]));
33+
assert((origin_simd_1[0] == 2) && (origin_simd_2[0] == 1));
34+
35+
static_assert(noexcept(ex::swap(std::move(origin_simd_1[0]), value)));
36+
ex::swap(std::move(origin_simd_1[0]), value);
37+
assert((origin_simd_1[0] == 3) && (value == 2));
38+
39+
static_assert(noexcept(ex::swap(value, std::move(origin_simd_2[0]))));
40+
ex::swap(value, std::move(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(ex::swap(std::move(origin_mask_1[0]), std::move(origin_mask_2[0]))));
54+
ex::swap(std::move(origin_mask_1[0]), std::move(origin_mask_2[0]));
55+
assert((origin_mask_1[0] == false) && (origin_mask_2[0] == true));
56+
57+
static_assert(noexcept(ex::swap(std::move(origin_mask_1[0]), value)));
58+
ex::swap(std::move(origin_mask_1[0]), value);
59+
assert((origin_mask_1[0] == true) && (value == false));
60+
61+
static_assert(noexcept(ex::swap(value, std::move(origin_mask_2[0]))));
62+
ex::swap(value, std::move(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)