From 8078fd8e6502a77f02f57fbce0c30ddaea0b4cdf Mon Sep 17 00:00:00 2001 From: Yin Zhang Date: Sun, 8 Oct 2023 16:13:20 +0800 Subject: [PATCH] [libc++] Add default constructor for class simd/simd_mask --- libcxx/docs/Status/ParallelismProjects.csv | 2 + libcxx/include/experimental/__simd/simd.h | 2 + .../include/experimental/__simd/simd_mask.h | 2 + .../simd.class/simd_ctor_default.pass.cpp | 108 +++++++++++++++ .../simd_mask_ctor_default.pass.cpp | 123 ++++++++++++++++++ 5 files changed, 237 insertions(+) create mode 100644 libcxx/test/std/experimental/simd/simd.class/simd_ctor_default.pass.cpp create mode 100644 libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_ctor_default.pass.cpp diff --git a/libcxx/docs/Status/ParallelismProjects.csv b/libcxx/docs/Status/ParallelismProjects.csv index 05a66080823d42..d4ce43365707f2 100644 --- a/libcxx/docs/Status/ParallelismProjects.csv +++ b/libcxx/docs/Status/ParallelismProjects.csv @@ -18,6 +18,7 @@ Section,Description,Dependencies,Assignee,Complete | `[parallel.simd.reference] `_, "`Element references operator= `_", None, Yin Zhang, |Complete| | `[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] `_, "`simd default constructor `_", None, Yin Zhang, |Complete| | `[parallel.simd.class] `_, "`simd broadcast constructor `_", None, Yin Zhang, |Complete| | `[parallel.simd.class] `_, "`simd generate constructor `_", None, Yin Zhang, |Complete| | `[parallel.simd.class] `_, "`simd subscript operators `_", None, Yin Zhang, |Complete| @@ -25,6 +26,7 @@ Section,Description,Dependencies,Assignee,Complete | `[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] `_, "`simd_mask default constructor `_", None, Yin Zhang, |Complete| | `[parallel.simd.mask.class] `_, "`simd_mask broadcast constructor `_", None, Yin Zhang, |Complete| | `[parallel.simd.mask.class] `_, "`simd_mask subscript operators `_", None, Yin Zhang, |Complete| | `[parallel.simd.mask.class] `_, "Class template simd_mask implementation", None, Yin Zhang, |In Progress| diff --git a/libcxx/include/experimental/__simd/simd.h b/libcxx/include/experimental/__simd/simd.h index c71dd625e46c61..29a566608603d6 100644 --- a/libcxx/include/experimental/__simd/simd.h +++ b/libcxx/include/experimental/__simd/simd.h @@ -40,6 +40,8 @@ class simd { static _LIBCPP_HIDE_FROM_ABI constexpr size_t size() noexcept { return simd_size_v; } + _LIBCPP_HIDE_FROM_ABI simd() noexcept = default; + // broadcast constructor template >, int> = 0> _LIBCPP_HIDE_FROM_ABI simd(_Up&& __v) noexcept : __s_(_Impl::__broadcast(static_cast(__v))) {} diff --git a/libcxx/include/experimental/__simd/simd_mask.h b/libcxx/include/experimental/__simd/simd_mask.h index 946338542ca0dd..2e47b678913f85 100644 --- a/libcxx/include/experimental/__simd/simd_mask.h +++ b/libcxx/include/experimental/__simd/simd_mask.h @@ -38,6 +38,8 @@ class simd_mask { static _LIBCPP_HIDE_FROM_ABI constexpr size_t size() noexcept { return simd_type::size(); } + _LIBCPP_HIDE_FROM_ABI simd_mask() noexcept = default; + // broadcast constructor _LIBCPP_HIDE_FROM_ABI explicit simd_mask(value_type __v) noexcept : __s_(_Impl::__broadcast(__v)) {} diff --git a/libcxx/test/std/experimental/simd/simd.class/simd_ctor_default.pass.cpp b/libcxx/test/std/experimental/simd/simd.class/simd_ctor_default.pass.cpp new file mode 100644 index 00000000000000..697a947f2fa4f3 --- /dev/null +++ b/libcxx/test/std/experimental/simd/simd.class/simd_ctor_default.pass.cpp @@ -0,0 +1,108 @@ +//===----------------------------------------------------------------------===// +// +// 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] +// simd() noexcept = default; + +#include "../test_utils.h" +#include + +namespace ex = std::experimental::parallelism_v2; + +// See https://www.open-std.org/jtc1/sc22/WG21/docs/papers/2019/n4808.pdf +// Default intialization performs no initialization of the elements; value-initialization initializes each element with T(). +// Thus, default initialization leaves the elements in an indeterminate state. +template +struct CheckSimdDefaultCtor { + template + void operator()() { + static_assert(std::is_nothrow_default_constructible_v>); + ex::simd pure_simd; + // trash value in default ctor + static_assert(pure_simd.size() > 0); + } +}; + +template +struct CheckSimdDefaultCopyCtor { + template + void operator()() { + ex::simd pure_simd([](T i) { return i; }); + constexpr std::size_t array_size = ex::simd_size_v; + std::array expected_value; + for (size_t i = 0; i < array_size; ++i) + expected_value[i] = pure_simd[i]; + + static_assert(std::is_nothrow_copy_constructible_v>); + ex::simd from_copy_ctor(pure_simd); + assert_simd_values_equal(from_copy_ctor, expected_value); + } +}; + +template +struct CheckSimdDefaultMoveCtor { + template + void operator()() { + ex::simd pure_simd([](T i) { return i; }); + constexpr std::size_t array_size = ex::simd_size_v; + std::array expected_value; + for (size_t i = 0; i < array_size; ++i) + expected_value[i] = pure_simd[i]; + + static_assert(std::is_nothrow_move_constructible_v>); + ex::simd from_move_ctor(std::move(pure_simd)); + assert_simd_values_equal(from_move_ctor, expected_value); + } +}; + +template +struct CheckSimdDefaultCopyAssignment { + template + void operator()() { + ex::simd pure_simd([](T i) { return i; }); + constexpr std::size_t array_size = ex::simd_size_v; + std::array expected_value; + for (size_t i = 0; i < array_size; ++i) + expected_value[i] = pure_simd[i]; + + static_assert(std::is_nothrow_copy_assignable_v>); + ex::simd from_copy_assignment; + from_copy_assignment = pure_simd; + assert_simd_values_equal(from_copy_assignment, expected_value); + } +}; + +template +struct CheckSimdDefaultMoveAssignment { + template + void operator()() { + ex::simd pure_simd([](T i) { return i; }); + constexpr std::size_t array_size = ex::simd_size_v; + std::array expected_value; + for (size_t i = 0; i < array_size; ++i) + expected_value[i] = pure_simd[i]; + + static_assert(std::is_nothrow_move_assignable_v>); + ex::simd from_move_assignment; + from_move_assignment = std::move(pure_simd); + assert_simd_values_equal(from_move_assignment, expected_value); + } +}; + +int main(int, char**) { + test_all_simd_abi(); + 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.mask.class/simd_mask_ctor_default.pass.cpp b/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_ctor_default.pass.cpp new file mode 100644 index 00000000000000..8401e7efd3824e --- /dev/null +++ b/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_ctor_default.pass.cpp @@ -0,0 +1,123 @@ +//===----------------------------------------------------------------------===// +// +// 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] +// simd_mask() noexcept = default; + +#include "../test_utils.h" +#include + +namespace ex = std::experimental::parallelism_v2; + +// See https://www.open-std.org/jtc1/sc22/WG21/docs/papers/2019/n4808.pdf +// Default intialization performs no initialization of the elements; value-initialization initializes each element with T(). +// Thus, default initialization leaves the elements in an indeterminate state. +template +struct CheckSimdMaskDefaultCtor { + template + void operator()() { + ex::simd_mask pure_mask; + // trash value in default ctor + static_assert(pure_mask.size() > 0); + } +}; + +template +struct CheckSimdMaskDefaultCopyCtor { + template + void operator()() { + ex::simd_mask pure_mask; + constexpr std::size_t array_size = ex::simd_size_v; + std::array expected_value; + for (size_t i = 0; i < array_size; ++i) { + if (i % 2 == 0) + pure_mask[i] = true; + else + pure_mask[i] = false; + expected_value[i] = pure_mask[i]; + } + + ex::simd_mask from_copy_ctor(pure_mask); + assert_simd_mask_values_equal(from_copy_ctor, expected_value); + } +}; + +template +struct CheckSimdMaskDefaultMoveCtor { + template + void operator()() { + ex::simd_mask pure_mask; + constexpr std::size_t array_size = ex::simd_size_v; + std::array expected_value; + for (size_t i = 0; i < array_size; ++i) { + if (i % 2 == 0) + pure_mask[i] = true; + else + pure_mask[i] = false; + expected_value[i] = pure_mask[i]; + } + + ex::simd_mask from_move_ctor(std::move(pure_mask)); + assert_simd_mask_values_equal(from_move_ctor, expected_value); + } +}; + +template +struct CheckSimdMaskDefaultCopyAssignment { + template + void operator()() { + ex::simd_mask pure_mask; + constexpr std::size_t array_size = ex::simd_size_v; + std::array expected_value; + for (size_t i = 0; i < array_size; ++i) { + if (i % 2 == 0) + pure_mask[i] = true; + else + pure_mask[i] = false; + expected_value[i] = pure_mask[i]; + } + + ex::simd_mask from_copy_assignment; + from_copy_assignment = pure_mask; + assert_simd_mask_values_equal(from_copy_assignment, expected_value); + } +}; + +template +struct CheckSimdMaskDefaultMoveAssignment { + template + void operator()() { + ex::simd_mask pure_mask; + constexpr std::size_t array_size = ex::simd_size_v; + std::array expected_value; + for (size_t i = 0; i < array_size; ++i) { + if (i % 2 == 0) + pure_mask[i] = true; + else + pure_mask[i] = false; + expected_value[i] = pure_mask[i]; + } + + ex::simd_mask from_move_assignment; + from_move_assignment = std::move(pure_mask); + assert_simd_mask_values_equal(from_move_assignment, expected_value); + } +}; + +int main(int, char**) { + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + return 0; +}