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 @@ -3,10 +3,19 @@ | `[parallel.execpol] `_, "Execution policies", None, unassigned, |Not Started| | `[parallel.alg] `_, "Parallel algorithms", None, unassigned, |Not Started| | `[parallel.taskblock] `_, "Task Block", None, unassigned, |Not Started| -| `[parallel.simd.abi] `_, "simd ABI tags", None, Yin Zhang, |In Progress| -| `[parallel.simd.traits] `_, "simd type traits", None, Yin Zhang, |In Progress| +| `[parallel.simd.abi] `_, "`simd ABI tags `_", [parallel.simd.class] [parallel.simd.mask.class] declarations and alias, Yin Zhang, |Complete| +| `[parallel.simd.traits] `_, "`simd type traits is_abi_tag[_v] `_", [parallel.simd.abi], Yin Zhang, |Complete| +| `[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 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", None, Yin Zhang, |In Progress| +| `[parallel.simd.class] `_, "`Class template simd declaration and alias `_", [parallel.simd.abi], 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", 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] `_, "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 @@ -802,6 +802,10 @@ expected experimental/__config experimental/__memory + experimental/__simd/declarations.h + experimental/__simd/scalar.h + experimental/__simd/traits.h + experimental/__simd/vec_ext.h experimental/deque experimental/forward_list experimental/iterator diff --git a/libcxx/include/experimental/__config b/libcxx/include/experimental/__config --- a/libcxx/include/experimental/__config +++ b/libcxx/include/experimental/__config @@ -32,4 +32,11 @@ #define _LIBCPP_END_NAMESPACE_LFTS_PMR _LIBCPP_END_NAMESPACE_LFTS } #define _VSTD_LFTS_PMR _VSTD_LFTS::pmr +// TODO: support more targets +#if defined(__AVX__) +#define _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES 32 +#else +#define _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES 16 +#endif + #endif diff --git a/libcxx/include/experimental/__simd/declarations.h b/libcxx/include/experimental/__simd/declarations.h new file mode 100644 --- /dev/null +++ b/libcxx/include/experimental/__simd/declarations.h @@ -0,0 +1,25 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_EXPERIMENTAL___SIMD_DECLARATIONS_H +#define _LIBCPP_EXPERIMENTAL___SIMD_DECLARATIONS_H + +#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) + +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL +inline namespace parallelism_v2 { +template +class simd; +template +class simd_mask; +} // namespace parallelism_v2 +_LIBCPP_END_NAMESPACE_EXPERIMENTAL + +#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) +#endif // _LIBCPP_EXPERIMENTAL___SIMD_DECLARATIONS_H diff --git a/libcxx/include/experimental/__simd/scalar.h b/libcxx/include/experimental/__simd/scalar.h new file mode 100644 --- /dev/null +++ b/libcxx/include/experimental/__simd/scalar.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_EXPERIMENTAL___SIMD_SCALAR_H +#define _LIBCPP_EXPERIMENTAL___SIMD_SCALAR_H + +#include +#include + +#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) + +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL +inline namespace parallelism_v2 { +namespace simd_abi { +struct __scalar { + static constexpr size_t __simd_size = 1; +}; +} // namespace simd_abi +// traits [simd.traits] +template <> +inline constexpr bool is_abi_tag_v = true; +} // namespace parallelism_v2 +_LIBCPP_END_NAMESPACE_EXPERIMENTAL + +#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) +#endif // _LIBCPP_EXPERIMENTAL___SIMD_SCALAR_H diff --git a/libcxx/include/experimental/__simd/traits.h b/libcxx/include/experimental/__simd/traits.h new file mode 100644 --- /dev/null +++ b/libcxx/include/experimental/__simd/traits.h @@ -0,0 +1,42 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_EXPERIMENTAL___SIMD_TRAITS_H +#define _LIBCPP_EXPERIMENTAL___SIMD_TRAITS_H + +#include + +#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) + +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL +inline namespace parallelism_v2 { +// traits [simd.traits] +template +inline constexpr bool is_abi_tag_v = false; +template +struct is_abi_tag : bool_constant> {}; + +template +inline constexpr bool is_simd_v = false; +template +inline constexpr bool is_simd_v> = true; +template +struct is_simd : bool_constant> {}; + +template +inline constexpr bool is_simd_mask_v = false; +template +inline constexpr bool is_simd_mask_v> = true; +template +struct is_simd_mask : bool_constant> {}; +} // namespace parallelism_v2 +_LIBCPP_END_NAMESPACE_EXPERIMENTAL + +#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) +#endif // _LIBCPP_EXPERIMENTAL___SIMD_TRAITS_H diff --git a/libcxx/include/experimental/__simd/vec_ext.h b/libcxx/include/experimental/__simd/vec_ext.h new file mode 100644 --- /dev/null +++ b/libcxx/include/experimental/__simd/vec_ext.h @@ -0,0 +1,33 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H +#define _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H + +#include +#include + +#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) + +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL +inline namespace parallelism_v2 { +namespace simd_abi { +template +struct __vec_ext { + static constexpr size_t __simd_size = _Np; +}; +} // namespace simd_abi +// traits [simd.traits] +template +inline constexpr bool is_abi_tag_v> = _Np > 0 && _Np <= 32; +} // namespace parallelism_v2 +_LIBCPP_END_NAMESPACE_EXPERIMENTAL + +#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) +#endif // _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H diff --git a/libcxx/include/experimental/simd b/libcxx/include/experimental/simd --- a/libcxx/include/experimental/simd +++ b/libcxx/include/experimental/simd @@ -10,6 +10,101 @@ #ifndef _LIBCPP_EXPERIMENTAL_SIMD #define _LIBCPP_EXPERIMENTAL_SIMD +/* + experimental/simd synopsis + +namespace std::experimental { +inline namespace parallelism_v2 { + namespace simd_abi { + using scalar = see below; + template using fixed_size = see below; + template inline constexpr int max_fixed_size = implementation-defined; + template using compatible = implementation-defined; + template using native = implementation-defined; + + template struct deduce { using type = see below; }; + template using deduce_t = + typename deduce::type; + } // namespace simd_abi + + // class template simd [simd.class] + template > class simd; + template using native_simd = simd>; + template using fixed_size_simd = simd>; + + // class template simd_mask [simd.mask.class] + template > class simd_mask; + template using native_simd_mask = simd_mask>; + template using fixed_size_simd_mask = simd_mask>; + + // traits [simd.traits] + template struct is_abi_tag; + template inline constexpr bool is_abi_tag_v = is_abi_tag::value; + + template struct is_simd; + template inline constexpr bool is_simd_v = is_simd::value; + + template struct is_simd_mask; + template inline constexpr bool is_simd_mask_v = is_simd_mask::value; + +} // namespace parallelism_v2 +} // namespace std::experimental + +*/ + #include <__assert> // all public C++ headers provide the assertion handler +#include +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) + +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL +inline namespace parallelism_v2 { +namespace simd_abi { +using scalar = __scalar; +template +using fixed_size = __vec_ext<_Np>; +template +inline constexpr int max_fixed_size = 32; +template +using compatible = __vec_ext<16 / sizeof(_Tp)>; +template +using native = __vec_ext<_LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>; + +// TODO: Refine implementation-defined deduce ABI +template +struct deduce { + using type = fixed_size<_Np>; +}; +template +using deduce_t = typename deduce<_Tp, _Np, _Abis...>::type; +} // namespace simd_abi + +// class template simd [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>>; + +// class template simd_mask [simd.mask.class] +template > +class simd_mask; +template +using native_simd_mask = simd_mask<_Tp, simd_abi::native<_Tp>>; +template +using fixed_size_simd_mask = simd_mask<_Tp, simd_abi::fixed_size<_Np>>; + +} // namespace parallelism_v2 +_LIBCPP_END_NAMESPACE_EXPERIMENTAL +#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) #endif /* _LIBCPP_EXPERIMENTAL_SIMD */ diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv --- a/libcxx/test/libcxx/transitive_includes/cxx03.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv @@ -252,6 +252,7 @@ experimental/regex regex experimental/set experimental/memory_resource experimental/set set +experimental/simd cstddef experimental/string experimental/memory_resource experimental/string string experimental/unordered_map algorithm diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv --- a/libcxx/test/libcxx/transitive_includes/cxx11.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv @@ -252,6 +252,7 @@ experimental/regex regex experimental/set experimental/memory_resource experimental/set set +experimental/simd cstddef experimental/string experimental/memory_resource experimental/string string experimental/unordered_map algorithm diff --git a/libcxx/test/libcxx/transitive_includes/cxx2b.csv b/libcxx/test/libcxx/transitive_includes/cxx2b.csv --- a/libcxx/test/libcxx/transitive_includes/cxx2b.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx2b.csv @@ -178,6 +178,7 @@ experimental/regex regex experimental/set experimental/memory_resource experimental/set set +experimental/simd cstddef experimental/string experimental/memory_resource experimental/string string experimental/type_traits initializer_list diff --git a/libcxx/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp b/libcxx/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// 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 is_abi_tag; +// template inline constexpr bool ex::is_abi_tag_v = ex::is_abi_tag::value; + +#include "../test_utils.h" +#include +#include + +namespace ex = std::experimental::parallelism_v2; + +struct CheckIsAbiTagTrue { + template + void operator()() { + static_assert(_Tp::value); + } +}; + +struct CheckIsAbiTagFalse { + template + void operator()() { + static_assert(!_Tp::value); + } +}; + +struct CheckIsAbiTagVTrue { + template + void operator()() { + static_assert(_Tp); + } +}; + +struct CheckIsAbiTagVFalse { + template + void operator()() { + static_assert(!_Tp); + } +}; + +template +void test_simd_abi() {} +template +void test_simd_abi() { + if constexpr (std::is_same::value) { + F{}.template operator()>(); + } else if constexpr (std::is_same::value) { + F{}.template operator()>(); + F{}.template operator()>>(); + F{}.template operator()>>(); + } else if constexpr (std::is_same::value) { + F{}.template operator()>(); + } else { + F{}.template operator()>(); + F{}.template operator()>>(); + F{}.template operator()>>(); + } + + test_simd_abi(); +} + +int main(int, char**) { + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + return 0; +} diff --git a/libcxx/test/std/experimental/simd/simd.traits/is_simd.pass.cpp b/libcxx/test/std/experimental/simd/simd.traits/is_simd.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/experimental/simd/simd.traits/is_simd.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// 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 ex::is_simd; +// template inline constexpr bool ex::is_simd_v = ex::is_simd::value; + +#include "../test_utils.h" +#include +#include + +namespace ex = std::experimental::parallelism_v2; + +struct CheckIsSimdTrue { + template + void operator()() { + static_assert(_Tp::value); + } +}; + +struct CheckIsSimdFalse { + template + void operator()() { + static_assert(!_Tp::value); + } +}; + +struct CheckIsSimdVTrue { + template + void operator()() { + static_assert(_Tp); + } +}; + +struct CheckIsSimdVFalse { + template + void operator()() { + static_assert(!_Tp); + } +}; + +template +void test_simd_abi() {} +template +void test_simd_abi() { + if constexpr (std::is_same::value) { + F{}.template operator()>>(); + F{}.template operator()>>(); + F{}.template operator()>>(); + F{}.template operator()>>(); + } else if constexpr (std::is_same::value) { + F{}.template operator()>(); + F{}.template operator()>>(); + } else if constexpr (std::is_same::value) { + F{}.template operator()>>(); + F{}.template operator()>>(); + F{}.template operator()>>(); + F{}.template operator()>>(); + } else { + F{}.template operator()>(); + F{}.template operator()>>(); + } + + test_simd_abi(); +} + +int main(int, char**) { + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + return 0; +} diff --git a/libcxx/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp b/libcxx/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// 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 ex::is_simd_mask; +// template inline constexpr bool ex::is_simd_mask_v = ex::is_simd_mask::value; + +#include "../test_utils.h" +#include +#include + +namespace ex = std::experimental::parallelism_v2; + +struct CheckIsSimdMaskTrue { + template + void operator()() { + static_assert(_Tp::value); + } +}; + +struct CheckIsSimdMaskFalse { + template + void operator()() { + static_assert(!_Tp::value); + } +}; + +struct CheckIsSimdMaskVTrue { + template + void operator()() { + static_assert(_Tp); + } +}; + +struct CheckIsSimdMaskVFalse { + template + void operator()() { + static_assert(!_Tp); + } +}; + +template +void test_simd_abi() {} +template +void test_simd_abi() { + if constexpr (std::is_same::value) { + F{}.template operator()>>(); + F{}.template operator()>>(); + F{}.template operator()>>(); + F{}.template operator()>>(); + } else if constexpr (std::is_same::value) { + F{}.template operator()>(); + F{}.template operator()>>(); + } else if constexpr (std::is_same::value) { + F{}.template operator()>>(); + F{}.template operator()>>(); + F{}.template operator()>>(); + F{}.template operator()>>(); + } else { + F{}.template operator()>(); + F{}.template operator()>>(); + } + + test_simd_abi(); +} + +int main(int, char**) { + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + return 0; +} diff --git a/libcxx/test/std/experimental/simd/test_utils.h b/libcxx/test/std/experimental/simd/test_utils.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/experimental/simd/test_utils.h @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_UTIL_H +#define TEST_UTIL_H + +#include +#include +#include "type_algorithms.h" + +namespace ex = std::experimental::parallelism_v2; + +constexpr std::size_t max_simd_size = 32; + +using integral_no_bool_types = + types::concatenate_t; +using arithmetic_no_bool_types = types::concatenate_t; + +template +void test_simd_abi(); + +template +void test_native_compatible_scalar() { + using namespace ex; + test_simd_abi, simd_abi::compatible<_Tp>>(); +} + +template +void test_fixed_size_deduce_t(std::integer_sequence) { + using namespace ex; + + (test_simd_abi, simd_abi::deduce_t<_Tp, _Np + 1>>(), ...); +} + +template +void test_all_simd_abi() { + test_native_compatible_scalar(); + + constexpr static auto integer_seq_from_make_integer = std::make_integer_sequence(); + + test_fixed_size_deduce_t(integer_seq_from_make_integer); +} + +template +void test_all_simd_abi() { + types::for_each(arithmetic_no_bool_types(), []() { test_all_simd_abi(); }); +} + +#endif // TEST_UTIL_H diff --git a/libcxx/utils/data/ignore_format.txt b/libcxx/utils/data/ignore_format.txt --- a/libcxx/utils/data/ignore_format.txt +++ b/libcxx/utils/data/ignore_format.txt @@ -322,7 +322,6 @@ libcxx/include/experimental/propagate_const libcxx/include/experimental/regex libcxx/include/experimental/set -libcxx/include/experimental/simd libcxx/include/experimental/string libcxx/include/experimental/type_traits libcxx/include/experimental/unordered_map