Skip to content

Commit e7a45c6

Browse files
committed
[libcxx] <experimental/simd> Added internal storage type, constructors, subscript operators of class simd/simd_mask and related tests
[libcxx] <experimental/simd> Added internal storage type for class simd/simd_mask [libcxx] <experimental/simd> Added all constructors of class simd/simd_mask and related tests [libcxx] <experimental/simd> Added basic simd reference implementation, subscript operators of class simd/simd_mask and related tests Reviewed By: #libc, philnik Differential Revision: https://reviews.llvm.org/D144364
1 parent a284d0c commit e7a45c6

File tree

10 files changed

+237
-2
lines changed

10 files changed

+237
-2
lines changed

libcxx/include/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,8 @@ set(files
906906
experimental/__simd/abi_tag.h
907907
experimental/__simd/aligned_tag.h
908908
experimental/__simd/declaration.h
909+
experimental/__simd/internal_declaration.h
910+
experimental/__simd/reference.h
909911
experimental/__simd/scalar.h
910912
experimental/__simd/simd.h
911913
experimental/__simd/simd_mask.h
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP_EXPERIMENTAL___SIMD_INTERNAL_DECLARATION_H
11+
#define _LIBCPP_EXPERIMENTAL___SIMD_INTERNAL_DECLARATION_H
12+
13+
#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
14+
15+
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
16+
inline namespace parallelism_v2 {
17+
18+
template <class _Tp, class _Abi>
19+
struct __simd_storage;
20+
21+
template <class _Tp, class _Abi>
22+
struct __mask_storage;
23+
24+
template <class _Tp, class _Abi>
25+
struct __simd_operations;
26+
27+
template <class _Tp, class _Abi>
28+
struct __mask_operations;
29+
30+
} // namespace parallelism_v2
31+
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
32+
33+
#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
34+
#endif // _LIBCPP_EXPERIMENTAL___SIMD_INTERNAL_DECLARATION_H
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H
11+
#define _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H
12+
13+
#include <experimental/__simd/utility.h>
14+
15+
#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
16+
17+
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
18+
inline namespace parallelism_v2 {
19+
template <class _Tp, class _Storage, class _Vp>
20+
class __simd_reference {
21+
template <class, class>
22+
friend class simd;
23+
template <class, class>
24+
friend class simd_mask;
25+
26+
_Storage& __s_;
27+
size_t __idx_;
28+
29+
_LIBCPP_HIDE_FROM_ABI _Vp __get() const { return __s_.__get(__idx_); }
30+
31+
_LIBCPP_HIDE_FROM_ABI void __set(_Vp __v) {
32+
if constexpr (is_same_v<_Vp, bool>)
33+
__s_.__set(__idx_, experimental::__set_all_bits<_Tp>(__v));
34+
else
35+
__s_.__set(__idx_, __v);
36+
}
37+
38+
public:
39+
using value_type = _Vp;
40+
41+
__simd_reference() = delete;
42+
__simd_reference(const __simd_reference&) = delete;
43+
};
44+
45+
} // namespace parallelism_v2
46+
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
47+
48+
#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
49+
#endif // _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H

libcxx/include/experimental/__simd/scalar.h

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define _LIBCPP_EXPERIMENTAL___SIMD_SCALAR_H
1212

1313
#include <cstddef>
14+
#include <experimental/__simd/internal_declaration.h>
1415

1516
#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
1617

@@ -20,8 +21,36 @@ namespace simd_abi {
2021
struct __scalar {
2122
static constexpr size_t __simd_size = 1;
2223
};
23-
2424
} // namespace simd_abi
25+
26+
template <class _Tp>
27+
struct __simd_storage<_Tp, simd_abi::__scalar> {
28+
_Tp __data;
29+
30+
_Tp __get([[maybe_unused]] size_t __idx) const noexcept {
31+
_LIBCPP_ASSERT_UNCATEGORIZED(__idx == 0, "Index is out of bounds");
32+
return __data;
33+
}
34+
void __set([[maybe_unused]] size_t __idx, _Tp __v) noexcept {
35+
_LIBCPP_ASSERT_UNCATEGORIZED(__idx == 0, "Index is out of bounds");
36+
__data = __v;
37+
}
38+
};
39+
40+
template <class _Tp>
41+
struct __mask_storage<_Tp, simd_abi::__scalar> : __simd_storage<bool, simd_abi::__scalar> {};
42+
43+
template <class _Tp>
44+
struct __simd_operations<_Tp, simd_abi::__scalar> {
45+
using _SimdStorage = __simd_storage<_Tp, simd_abi::__scalar>;
46+
using _MaskStorage = __mask_storage<_Tp, simd_abi::__scalar>;
47+
};
48+
49+
template <class _Tp>
50+
struct __mask_operations<_Tp, simd_abi::__scalar> {
51+
using _MaskStorage = __mask_storage<_Tp, simd_abi::__scalar>;
52+
};
53+
2554
} // namespace parallelism_v2
2655
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
2756

libcxx/include/experimental/__simd/simd.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212

1313
#include <experimental/__simd/abi_tag.h>
1414
#include <experimental/__simd/declaration.h>
15+
#include <experimental/__simd/reference.h>
16+
#include <experimental/__simd/scalar.h>
1517
#include <experimental/__simd/traits.h>
18+
#include <experimental/__simd/vec_ext.h>
1619

1720
#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
1821

@@ -23,8 +26,14 @@ inline namespace parallelism_v2 {
2326
// TODO: implement simd class
2427
template <class _Tp, class _Abi>
2528
class simd {
29+
using _Impl = __simd_operations<_Tp, _Abi>;
30+
using _Storage = typename _Impl::_SimdStorage;
31+
32+
_Storage __s_;
33+
2634
public:
2735
using value_type = _Tp;
36+
using reference = __simd_reference<_Tp, _Storage, value_type>;
2837
using mask_type = simd_mask<_Tp, _Abi>;
2938
using abi_type = _Abi;
3039

libcxx/include/experimental/__simd/simd_mask.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212

1313
#include <experimental/__simd/abi_tag.h>
1414
#include <experimental/__simd/declaration.h>
15+
#include <experimental/__simd/reference.h>
16+
#include <experimental/__simd/scalar.h>
17+
#include <experimental/__simd/vec_ext.h>
1518

1619
#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
1720

@@ -22,8 +25,14 @@ inline namespace parallelism_v2 {
2225
// TODO: implement simd_mask class
2326
template <class _Tp, class _Abi>
2427
class simd_mask {
28+
using _Impl = __mask_operations<_Tp, _Abi>;
29+
using _Storage = typename _Impl::_MaskStorage;
30+
31+
_Storage __s_;
32+
2533
public:
2634
using value_type = bool;
35+
using reference = __simd_reference<_Tp, _Storage, value_type>;
2736
using simd_type = simd<_Tp, _Abi>;
2837
using abi_type = _Abi;
2938

libcxx/include/experimental/__simd/utility.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
#include <__type_traits/is_constant_evaluated.h>
1616
#include <__type_traits/is_same.h>
1717
#include <__type_traits/is_volatile.h>
18+
#include <cstdint>
19+
#include <limits>
20+
21+
_LIBCPP_PUSH_MACROS
22+
#include <__undef_macros>
1823

1924
#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
2025

@@ -23,8 +28,37 @@ inline namespace parallelism_v2 {
2328
template <class _Tp>
2429
constexpr bool __is_vectorizable_v =
2530
is_arithmetic_v<_Tp> && !is_const_v<_Tp> && !is_volatile_v<_Tp> && !is_same_v<_Tp, bool>;
31+
32+
template <class _Tp>
33+
_LIBCPP_HIDE_FROM_ABI auto __choose_mask_type() {
34+
if constexpr (sizeof(_Tp) == 1) {
35+
return uint8_t{};
36+
} else if constexpr (sizeof(_Tp) == 2) {
37+
return uint16_t{};
38+
} else if constexpr (sizeof(_Tp) == 4) {
39+
return uint32_t{};
40+
} else if constexpr (sizeof(_Tp) == 8) {
41+
return uint64_t{};
42+
}
43+
# ifndef _LIBCPP_HAS_NO_INT128
44+
else if constexpr (sizeof(_Tp) == 16) {
45+
return __uint128_t{};
46+
}
47+
# endif
48+
else
49+
static_assert(sizeof(_Tp) == 0, "Unexpected size");
50+
}
51+
52+
template <class _Tp>
53+
_LIBCPP_HIDE_FROM_ABI auto constexpr __set_all_bits(bool __v) {
54+
return __v ? (numeric_limits<decltype(__choose_mask_type<_Tp>())>::max()) : 0;
55+
}
56+
2657
} // namespace parallelism_v2
2758
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
2859

2960
#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
61+
62+
_LIBCPP_POP_MACROS
63+
3064
#endif // _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H

libcxx/include/experimental/__simd/vec_ext.h

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010
#ifndef _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H
1111
#define _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H
1212

13+
#include <__bit/bit_ceil.h>
1314
#include <cstddef>
15+
#include <experimental/__simd/internal_declaration.h>
16+
#include <experimental/__simd/utility.h>
1417

1518
#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
1619

@@ -21,8 +24,37 @@ template <int _Np>
2124
struct __vec_ext {
2225
static constexpr size_t __simd_size = _Np;
2326
};
24-
2527
} // namespace simd_abi
28+
29+
template <class _Tp, int _Np>
30+
struct __simd_storage<_Tp, simd_abi::__vec_ext<_Np>> {
31+
_Tp __data __attribute__((__vector_size__(std::__bit_ceil((sizeof(_Tp) * _Np)))));
32+
33+
_Tp __get(size_t __idx) const noexcept {
34+
_LIBCPP_ASSERT_UNCATEGORIZED(__idx > 0 && __idx <= _Np, "Index is out of bounds");
35+
return __data[__idx];
36+
}
37+
void __set(size_t __idx, _Tp __v) noexcept {
38+
_LIBCPP_ASSERT_UNCATEGORIZED(__idx > 0 && __idx <= _Np, "Index is out of bounds");
39+
__data[__idx] = __v;
40+
}
41+
};
42+
43+
template <class _Tp, int _Np>
44+
struct __mask_storage<_Tp, simd_abi::__vec_ext<_Np>>
45+
: __simd_storage<decltype(experimental::__choose_mask_type<_Tp>()), simd_abi::__vec_ext<_Np>> {};
46+
47+
template <class _Tp, int _Np>
48+
struct __simd_operations<_Tp, simd_abi::__vec_ext<_Np>> {
49+
using _SimdStorage = __simd_storage<_Tp, simd_abi::__vec_ext<_Np>>;
50+
using _MaskStorage = __mask_storage<_Tp, simd_abi::__vec_ext<_Np>>;
51+
};
52+
53+
template <class _Tp, int _Np>
54+
struct __mask_operations<_Tp, simd_abi::__vec_ext<_Np>> {
55+
using _MaskStorage = __mask_storage<_Tp, simd_abi::__vec_ext<_Np>>;
56+
};
57+
2658
} // namespace parallelism_v2
2759
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
2860

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
// Test the alias.
12+
// simd::reference::value_type
13+
// simd_mask::reference::value_type
14+
15+
#include "../test_utils.h"
16+
#include <experimental/simd>
17+
18+
namespace ex = std::experimental::parallelism_v2;
19+
20+
template <class T, std::size_t>
21+
struct CheckRefAlias {
22+
template <class SimdAbi>
23+
void operator()() {
24+
static_assert(std::is_same_v<typename ex::simd<T, SimdAbi>::reference::value_type, T>);
25+
static_assert(std::is_same_v<typename ex::simd_mask<T, SimdAbi>::reference::value_type, bool>);
26+
}
27+
};
28+
29+
int main(int, char**) {
30+
test_all_simd_abi<CheckRefAlias>();
31+
return 0;
32+
}

libcxx/test/std/experimental/simd/test_utils.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,12 @@ struct TestAllSimdAbiFunctor {
3636
}
3737
};
3838

39+
// TODO: Support long double (12 bytes) for MinGW (DLL, i686)
40+
#ifdef __MINGW32__
41+
using arithmetic_no_bool_types = types::concatenate_t<types::integer_types, types::type_list<float, double>>;
42+
#else
3943
using arithmetic_no_bool_types = types::concatenate_t<types::integer_types, types::floating_point_types>;
44+
#endif
4045

4146
template <template <class T, std::size_t N> class Func>
4247
void test_all_simd_abi() {

0 commit comments

Comments
 (0)