Skip to content

Commit

Permalink
[libc++] <experimental/simd> Add default constructor for class simd/s…
Browse files Browse the repository at this point in the history
…imd_mask (llvm#70424)
  • Loading branch information
joy2myself authored Nov 1, 2023
1 parent 0a34aae commit e3c2eac
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 0 deletions.
2 changes: 2 additions & 0 deletions libcxx/docs/Status/ParallelismProjects.csv
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ Section,Description,Dependencies,Assignee,Complete
| `[parallel.simd.reference] <https://wg21.link/N4808>`_, "`Element references operator= <https://github.com/llvm/llvm-project/pull/70020>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`Class template simd declaration and alias <https://reviews.llvm.org/D144362>`_", [parallel.simd.abi], Yin Zhang, |Complete|
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd<>::size() <https://reviews.llvm.org/D144363>`_", [parallel.simd.traits] simd_size[_v], Yin Zhang, |Complete|
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd default constructor <https://github.com/llvm/llvm-project/pull/70424>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd broadcast constructor <https://reviews.llvm.org/D156225>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd generate constructor <https://reviews.llvm.org/D159442>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "`simd subscript operators <https://github.com/llvm/llvm-project/pull/68960>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.class] <https://wg21.link/N4808>`_, "Class template simd implementation", None, Yin Zhang, |In Progress|
| `[parallel.simd.nonmembers] <https://wg21.link/N4808>`_, "simd non-member operations", None, Yin Zhang, |In Progress|
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`Class template simd_mask declaration and alias <https://reviews.llvm.org/D144362>`_", [parallel.simd.abi], Yin Zhang, |Complete|
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask<>::size() <https://reviews.llvm.org/D144363>`_", [parallel.simd.class] simd<>::size(), Yin Zhang, |Complete|
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask default constructor <https://github.com/llvm/llvm-project/pull/70424>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask broadcast constructor <https://reviews.llvm.org/D156225>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "`simd_mask subscript operators <https://github.com/llvm/llvm-project/pull/68960>`_", None, Yin Zhang, |Complete|
| `[parallel.simd.mask.class] <https://wg21.link/N4808>`_, "Class template simd_mask implementation", None, Yin Zhang, |In Progress|
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/experimental/__simd/simd.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class simd {

static _LIBCPP_HIDE_FROM_ABI constexpr size_t size() noexcept { return simd_size_v<value_type, abi_type>; }

_LIBCPP_HIDE_FROM_ABI simd() noexcept = default;

// broadcast constructor
template <class _Up, enable_if_t<__can_broadcast_v<value_type, __remove_cvref_t<_Up>>, int> = 0>
_LIBCPP_HIDE_FROM_ABI simd(_Up&& __v) noexcept : __s_(_Impl::__broadcast(static_cast<value_type>(__v))) {}
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/experimental/__simd/simd_mask.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {}

Expand Down
Original file line number Diff line number Diff line change
@@ -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

// <experimental/simd>
//
// [simd.class]
// simd() noexcept = default;

#include "../test_utils.h"
#include <experimental/simd>

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 <class T, std::size_t>
struct CheckSimdDefaultCtor {
template <class SimdAbi>
void operator()() {
static_assert(std::is_nothrow_default_constructible_v<ex::simd<T, SimdAbi>>);
ex::simd<T, SimdAbi> pure_simd;
// trash value in default ctor
static_assert(pure_simd.size() > 0);
}
};

template <class T, std::size_t>
struct CheckSimdDefaultCopyCtor {
template <class SimdAbi>
void operator()() {
ex::simd<T, SimdAbi> pure_simd([](T i) { return i; });
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
std::array<T, array_size> 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<T, SimdAbi>>);
ex::simd<T, SimdAbi> from_copy_ctor(pure_simd);
assert_simd_values_equal<array_size>(from_copy_ctor, expected_value);
}
};

template <class T, std::size_t>
struct CheckSimdDefaultMoveCtor {
template <class SimdAbi>
void operator()() {
ex::simd<T, SimdAbi> pure_simd([](T i) { return i; });
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
std::array<T, array_size> 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<T, SimdAbi>>);
ex::simd<T, SimdAbi> from_move_ctor(std::move(pure_simd));
assert_simd_values_equal<array_size>(from_move_ctor, expected_value);
}
};

template <class T, std::size_t>
struct CheckSimdDefaultCopyAssignment {
template <class SimdAbi>
void operator()() {
ex::simd<T, SimdAbi> pure_simd([](T i) { return i; });
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
std::array<T, array_size> 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<T, SimdAbi>>);
ex::simd<T, SimdAbi> from_copy_assignment;
from_copy_assignment = pure_simd;
assert_simd_values_equal<array_size>(from_copy_assignment, expected_value);
}
};

template <class T, std::size_t>
struct CheckSimdDefaultMoveAssignment {
template <class SimdAbi>
void operator()() {
ex::simd<T, SimdAbi> pure_simd([](T i) { return i; });
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
std::array<T, array_size> 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<T, SimdAbi>>);
ex::simd<T, SimdAbi> from_move_assignment;
from_move_assignment = std::move(pure_simd);
assert_simd_values_equal<array_size>(from_move_assignment, expected_value);
}
};

int main(int, char**) {
test_all_simd_abi<CheckSimdDefaultCtor>();
test_all_simd_abi<CheckSimdDefaultCopyCtor>();
test_all_simd_abi<CheckSimdDefaultMoveCtor>();
test_all_simd_abi<CheckSimdDefaultCopyAssignment>();
test_all_simd_abi<CheckSimdDefaultMoveAssignment>();
return 0;
}
Original file line number Diff line number Diff line change
@@ -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

// <experimental/simd>
//
// [simd.mask.class]
// simd_mask() noexcept = default;

#include "../test_utils.h"
#include <experimental/simd>

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 <class T, std::size_t>
struct CheckSimdMaskDefaultCtor {
template <class SimdAbi>
void operator()() {
ex::simd_mask<T, SimdAbi> pure_mask;
// trash value in default ctor
static_assert(pure_mask.size() > 0);
}
};

template <class T, std::size_t>
struct CheckSimdMaskDefaultCopyCtor {
template <class SimdAbi>
void operator()() {
ex::simd_mask<T, SimdAbi> pure_mask;
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
std::array<bool, array_size> 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<T, SimdAbi> from_copy_ctor(pure_mask);
assert_simd_mask_values_equal<array_size>(from_copy_ctor, expected_value);
}
};

template <class T, std::size_t>
struct CheckSimdMaskDefaultMoveCtor {
template <class SimdAbi>
void operator()() {
ex::simd_mask<T, SimdAbi> pure_mask;
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
std::array<bool, array_size> 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<T, SimdAbi> from_move_ctor(std::move(pure_mask));
assert_simd_mask_values_equal<array_size>(from_move_ctor, expected_value);
}
};

template <class T, std::size_t>
struct CheckSimdMaskDefaultCopyAssignment {
template <class SimdAbi>
void operator()() {
ex::simd_mask<T, SimdAbi> pure_mask;
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
std::array<bool, array_size> 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<T, SimdAbi> from_copy_assignment;
from_copy_assignment = pure_mask;
assert_simd_mask_values_equal<array_size>(from_copy_assignment, expected_value);
}
};

template <class T, std::size_t>
struct CheckSimdMaskDefaultMoveAssignment {
template <class SimdAbi>
void operator()() {
ex::simd_mask<T, SimdAbi> pure_mask;
constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
std::array<bool, array_size> 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<T, SimdAbi> from_move_assignment;
from_move_assignment = std::move(pure_mask);
assert_simd_mask_values_equal<array_size>(from_move_assignment, expected_value);
}
};

int main(int, char**) {
test_all_simd_abi<CheckSimdMaskDefaultCtor>();
test_all_simd_abi<CheckSimdMaskDefaultCopyCtor>();
test_all_simd_abi<CheckSimdMaskDefaultMoveCtor>();
test_all_simd_abi<CheckSimdMaskDefaultCopyAssignment>();
test_all_simd_abi<CheckSimdMaskDefaultMoveAssignment>();
return 0;
}

0 comments on commit e3c2eac

Please sign in to comment.