diff --git a/libcxx/docs/Status/ParallelismProjects.csv b/libcxx/docs/Status/ParallelismProjects.csv --- a/libcxx/docs/Status/ParallelismProjects.csv +++ b/libcxx/docs/Status/ParallelismProjects.csv @@ -8,14 +8,16 @@ | `[parallel.simd.traits] `_, "`simd type traits is_simd[_v] `_", [parallel.simd.class] declaration and alias, Yin Zhang, |Complete| | `[parallel.simd.traits] `_, "`simd type traits is_simd_mask[_v] `_", [parallel.simd.mask.class] declaration and alias, Yin Zhang, |Complete| | `[parallel.simd.traits] `_, "simd type traits is_simd_flag_type", None, Yin Zhang, |In Progress| -| `[parallel.simd.traits] `_, "simd type traits simd_size", None, Yin Zhang, |In Progress| +| `[parallel.simd.traits] `_, "`simd type traits simd_size[_v] `_", [parallel.simd.traits] is_abi_tag[_v], Yin Zhang, |Complete| | `[parallel.simd.traits] `_, "simd type traits memory_alignment", None, Yin Zhang, |In Progress| | `[parallel.simd.traits] `_, "simd type traits rebind_simd", None, Yin Zhang, |In Progress| | `[parallel.simd.traits] `_, "simd type traits resize_simd", None, Yin Zhang, |In Progress| | `[parallel.simd.whereexpr] `_, "Where expression class templates", None, Yin Zhang, |In Progress| | `[parallel.simd.class] `_, "`Class template simd declaration and alias `_", [parallel.simd.abi], Yin Zhang, |Complete| +| `[parallel.simd.class] `_, "`simd<>::size() `_", [parallel.simd.traits] simd_size[_v], Yin Zhang, |Complete| | `[parallel.simd.class] `_, "Class template simd implementation", None, Yin Zhang, |In Progress| | `[parallel.simd.nonmembers] `_, "simd non-member operations", None, Yin Zhang, |In Progress| | `[parallel.simd.mask.class] `_, "`Class template simd_mask declaration and alias `_", [parallel.simd.abi], Yin Zhang, |Complete| +| `[parallel.simd.mask.class] `_, "`simd_mask<>::size() `_", [parallel.simd.class] simd<>::size(), Yin Zhang, |Complete| | `[parallel.simd.mask.class] `_, "Class template simd_mask implementation", None, Yin Zhang, |In Progress| | `[parallel.simd.mask.nonmembers] `_, "simd_mask non-member operations", None, Yin Zhang, |In Progress| diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -905,10 +905,12 @@ experimental/__config experimental/__memory experimental/__simd/abi_tag.h + experimental/__simd/declaration.h experimental/__simd/scalar.h experimental/__simd/simd.h experimental/__simd/simd_mask.h experimental/__simd/traits.h + experimental/__simd/utility.h experimental/__simd/vec_ext.h experimental/deque experimental/forward_list diff --git a/libcxx/include/experimental/__simd/simd.h b/libcxx/include/experimental/__simd/declaration.h copy from libcxx/include/experimental/__simd/simd.h copy to libcxx/include/experimental/__simd/declaration.h --- a/libcxx/include/experimental/__simd/simd.h +++ b/libcxx/include/experimental/__simd/declaration.h @@ -7,29 +7,22 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H -#define _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H - -#include +#ifndef _LIBCPP_EXPERIMENTAL___SIMD_DECLARATION_H +#define _LIBCPP_EXPERIMENTAL___SIMD_DECLARATION_H #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL inline namespace parallelism_v2 { -// class template simd [simd.class] -// TODO: implement simd class template > class simd; -template -using native_simd = simd<_Tp, simd_abi::native<_Tp>>; - -template -using fixed_size_simd = simd<_Tp, simd_abi::fixed_size<_Np>>; +template > +class simd_mask; } // namespace parallelism_v2 _LIBCPP_END_NAMESPACE_EXPERIMENTAL #endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) -#endif // _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H +#endif // _LIBCPP_EXPERIMENTAL___SIMD_DECLARATION_H diff --git a/libcxx/include/experimental/__simd/simd.h b/libcxx/include/experimental/__simd/simd.h --- a/libcxx/include/experimental/__simd/simd.h +++ b/libcxx/include/experimental/__simd/simd.h @@ -11,6 +11,8 @@ #define _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H #include +#include +#include #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) @@ -19,8 +21,15 @@ // class template simd [simd.class] // TODO: implement simd class -template > -class simd; +template +class simd { +public: + using value_type = _Tp; + using mask_type = simd_mask<_Tp, _Abi>; + using abi_type = _Abi; + + static _LIBCPP_HIDE_FROM_ABI constexpr size_t size() noexcept { return simd_size_v; } +}; template using native_simd = simd<_Tp, simd_abi::native<_Tp>>; diff --git a/libcxx/include/experimental/__simd/simd_mask.h b/libcxx/include/experimental/__simd/simd_mask.h --- a/libcxx/include/experimental/__simd/simd_mask.h +++ b/libcxx/include/experimental/__simd/simd_mask.h @@ -11,6 +11,7 @@ #define _LIBCPP_EXPERIMENTAL___SIMD_SIMD_MASK_H #include +#include #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) @@ -19,8 +20,15 @@ // class template simd_mask [simd.mask.class] // TODO: implement simd_mask class -template > -class simd_mask; +template +class simd_mask { +public: + using value_type = bool; + using simd_type = simd<_Tp, _Abi>; + using abi_type = _Abi; + + static _LIBCPP_HIDE_FROM_ABI constexpr size_t size() noexcept { return simd_type::size(); } +}; template using native_simd_mask = simd_mask<_Tp, simd_abi::native<_Tp>>; diff --git a/libcxx/include/experimental/__simd/traits.h b/libcxx/include/experimental/__simd/traits.h --- a/libcxx/include/experimental/__simd/traits.h +++ b/libcxx/include/experimental/__simd/traits.h @@ -11,8 +11,8 @@ #define _LIBCPP_EXPERIMENTAL___SIMD_TRAITS_H #include -#include -#include +#include +#include #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) @@ -50,6 +50,15 @@ template struct is_simd_mask : bool_constant> {}; +template , bool = (__is_vectorizable_v<_Tp> && is_abi_tag_v<_Abi>)> +struct simd_size : integral_constant {}; + +template +struct simd_size<_Tp, _Abi, false> {}; + +template > +inline constexpr size_t simd_size_v = simd_size<_Tp, _Abi>::value; + } // namespace parallelism_v2 _LIBCPP_END_NAMESPACE_EXPERIMENTAL diff --git a/libcxx/include/experimental/__simd/simd.h b/libcxx/include/experimental/__simd/utility.h copy from libcxx/include/experimental/__simd/simd.h copy to libcxx/include/experimental/__simd/utility.h --- a/libcxx/include/experimental/__simd/simd.h +++ b/libcxx/include/experimental/__simd/utility.h @@ -7,29 +7,23 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H -#define _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H +#ifndef _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H +#define _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H -#include +#include <__type_traits/is_arithmetic.h> +#include <__type_traits/is_const.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_volatile.h> #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL inline namespace parallelism_v2 { - -// class template simd [simd.class] -// TODO: implement simd class -template > -class simd; - template -using native_simd = simd<_Tp, simd_abi::native<_Tp>>; - -template -using fixed_size_simd = simd<_Tp, simd_abi::fixed_size<_Np>>; - +constexpr bool __is_vectorizable_v = + is_arithmetic_v<_Tp> && !is_const_v<_Tp> && !is_volatile_v<_Tp> && !is_same_v<_Tp, bool>; } // namespace parallelism_v2 _LIBCPP_END_NAMESPACE_EXPERIMENTAL #endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) -#endif // _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H +#endif // _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H diff --git a/libcxx/include/experimental/simd b/libcxx/include/experimental/simd --- a/libcxx/include/experimental/simd +++ b/libcxx/include/experimental/simd @@ -47,6 +47,10 @@ template struct is_simd_mask; template inline constexpr bool is_simd_mask_v = is_simd_mask::value; + template> struct simd_size; + template> + inline constexpr size_t simd_size_v = simd_size::value; + } // namespace parallelism_v2 } // namespace std::experimental diff --git a/libcxx/test/std/experimental/simd/simd.class/simd_alias.pass.cpp b/libcxx/test/std/experimental/simd/simd.class/simd_alias.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/experimental/simd/simd.class/simd_alias.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// Test the alias. +// template class simd { +// public: +// using value_type = T; +// using mask_type = simd_mask; +// using abi_type = Abi; +// }; + +#include "../test_utils.h" +#include + +namespace ex = std::experimental::parallelism_v2; + +template +struct CheckSimdAlias { + template + void operator()() { + static_assert(std::is_same_v::value_type, T>); + static_assert(std::is_same_v::mask_type, ex::simd_mask>); + static_assert(std::is_same_v::abi_type, SimdAbi>); + } +}; + +int main(int, char**) { + test_all_simd_abi(); + return 0; +} diff --git a/libcxx/test/std/experimental/simd/simd.class/simd_width.pass.cpp b/libcxx/test/std/experimental/simd/simd.class/simd_width.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/experimental/simd/simd.class/simd_width.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// +// +// [simd.class] +// static constexpr std::size_t size() noexcept; + +#include "../test_utils.h" + +namespace ex = std::experimental::parallelism_v2; + +template +struct CheckSimdWidth { + template + void operator()() { + static_assert(ex::simd::size() == ex::simd_size_v); + } +}; + +int main(int, char**) { + test_all_simd_abi(); + return 0; +} diff --git a/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_alias.pass.cpp b/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_alias.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_alias.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// Test the alias. +// template class simd_mask { +// public: +// using value_type = bool; +// using simd_type = simd; +// using abi_type = Abi; +// }; + +#include "../test_utils.h" +#include + +namespace ex = std::experimental::parallelism_v2; + +template +struct CheckSimdMaskAlias { + template + void operator()() { + static_assert(std::is_same_v::value_type, bool>); + static_assert(std::is_same_v::simd_type, ex::simd>); + static_assert(std::is_same_v::abi_type, SimdAbi>); + } +}; + +int main(int, char**) { + test_all_simd_abi(); + return 0; +} diff --git a/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_width.pass.cpp b/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_width.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_width.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// +// +// [simd.mask.class] +// static constexpr std::size_t size() noexcept; + +#include "../test_utils.h" + +namespace ex = std::experimental::parallelism_v2; + +template +struct CheckSimdMaskWidth { + template + void operator()() { + static_assert(ex::simd_mask::size() == ex::simd_size_v); + } +}; + +int main(int, char**) { + test_all_simd_abi(); + return 0; +} diff --git a/libcxx/test/std/experimental/simd/simd.traits/simd_size.pass.cpp b/libcxx/test/std/experimental/simd/simd.traits/simd_size.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/experimental/simd/simd.traits/simd_size.pass.cpp @@ -0,0 +1,92 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// +// +// [simd.traits] +//template > struct simd_size; +//template > +//inline constexpr std::size_t ex::simd_size_v = ex::simd_size::value; + +#include "../test_utils.h" + +namespace ex = std::experimental::parallelism_v2; + +struct CheckSimdSizeFixedDeduce { + template + void check() { + static_assert(ex::simd_size_v> == N, "Simd size mismatch with abi fixed_size"); + static_assert(ex::simd_size>::value == N, "Simd size mismatch with abi fixed_size"); + + static_assert(ex::simd_size_v> == N, "Simd size mismatch with abi deduce"); + static_assert(ex::simd_size>::value == N, "Simd size mismatch with abi deduce"); + } + + template + void performChecks(std::index_sequence) { + (check(), ...); + } + + template + void operator()() { + performChecks(std::make_index_sequence{}); + } +}; + +struct CheckSimdSizeScalarNativeCompatible { + template + void operator()() { + static_assert(ex::simd_size_v == 1); + static_assert(ex::simd_size::value == 1); + + LIBCPP_STATIC_ASSERT(ex::simd_size>::value == 16 / sizeof(T)); + LIBCPP_STATIC_ASSERT(ex::simd_size_v> == 16 / sizeof(T)); + + LIBCPP_STATIC_ASSERT( + ex::simd_size>::value == _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(T)); + LIBCPP_STATIC_ASSERT(ex::simd_size_v> == _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(T)); + } +}; + +template , class = void> +struct has_simd_size : std::false_type {}; + +template +struct has_simd_size::value)>> : std::true_type {}; + +struct CheckSimdSizeTraits { + template + void operator()() { + static_assert(has_simd_size::value); + static_assert(!has_simd_size>::value); + + static_assert(has_simd_size::value); + static_assert(has_simd_size>::value); + static_assert(has_simd_size>::value); + static_assert(has_simd_size>::value); + + static_assert(!has_simd_size, ex::simd_abi::native>::value); + static_assert(!has_simd_size, ex::simd_abi::native>::value); + static_assert(!has_simd_size, ex::simd_abi::native>::value); + static_assert(!has_simd_size, ex::simd_abi::native>::value); + + static_assert(!has_simd_size::value); + static_assert(!has_simd_size>::value); + static_assert(!has_simd_size>::value); + static_assert(!has_simd_size>::value); + } +}; + +int main(int, char**) { + types::for_each(arithmetic_no_bool_types(), CheckSimdSizeFixedDeduce()); + types::for_each(arithmetic_no_bool_types(), CheckSimdSizeScalarNativeCompatible()); + types::for_each(arithmetic_no_bool_types(), CheckSimdSizeTraits()); + return 0; +} diff --git a/libcxx/test/std/experimental/simd/simd.traits/simd_size.verify.cpp b/libcxx/test/std/experimental/simd/simd.traits/simd_size.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/experimental/simd/simd.traits/simd_size.verify.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// +// +// [simd.traits] +//template > struct simd_size; +//template > +//inline constexpr std::size_t ex::simd_size_v = ex::simd_size::value; + +#include + +namespace ex = std::experimental::parallelism_v2; + +int main(int, char**) { + ex::simd_size>::value; + // expected-error-re@* {{no member named 'value' in {{.*}}}} + ex::simd_size, ex::simd_abi::native>::value; + // expected-error-re@* {{no member named 'value' in {{.*}}}} + ex::simd_size::value; + // expected-error-re@* {{no member named 'value' in {{.*}}}} + ex::simd_size>::value; + // expected-error-re@* {{no member named 'value' in {{.*}}}} + + ex::simd_size_v>; + // expected-error-re@* {{no member named 'value' in {{.*}}}} + ex::simd_size_v, ex::simd_abi::native>; + // expected-error-re@* {{no member named 'value' in {{.*}}}} + ex::simd_size_v; + // expected-error-re@* {{no member named 'value' in {{.*}}}} + ex::simd_size_v>; + // expected-error-re@* {{no member named 'value' in {{.*}}}} + + return 0; +} diff --git a/libcxx/test/std/experimental/simd/test_utils.h b/libcxx/test/std/experimental/simd/test_utils.h --- a/libcxx/test/std/experimental/simd/test_utils.h +++ b/libcxx/test/std/experimental/simd/test_utils.h @@ -36,9 +36,10 @@ } }; +using arithmetic_no_bool_types = types::concatenate_t; + template