[libcxx-commits] [libcxx] a284d0c - [libcxx] <experimental/simd> Added aliagned flag types, traits is_simd_flag_type[_v], memory_alignment[_v] and related tests
via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Sep 11 20:42:03 PDT 2023
Author: Zhangyin
Date: 2023-09-12T11:41:44+08:00
New Revision: a284d0cc9c698cf84f5b8e3407a079128f8875de
URL: https://github.com/llvm/llvm-project/commit/a284d0cc9c698cf84f5b8e3407a079128f8875de
DIFF: https://github.com/llvm/llvm-project/commit/a284d0cc9c698cf84f5b8e3407a079128f8875de.diff
LOG: [libcxx] <experimental/simd> Added aliagned flag types, traits is_simd_flag_type[_v], memory_alignment[_v] and related tests
Reviewed By: #libc, philnik
Differential Revision: https://reviews.llvm.org/D153319
Added:
libcxx/include/experimental/__simd/aligned_tag.h
libcxx/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp
libcxx/test/std/experimental/simd/simd.traits/memory_alignment.pass.cpp
libcxx/test/std/experimental/simd/simd.traits/memory_alignment.verify.cpp
Modified:
libcxx/docs/Status/ParallelismProjects.csv
libcxx/include/CMakeLists.txt
libcxx/include/__bit/bit_ceil.h
libcxx/include/__memory/assume_aligned.h
libcxx/include/experimental/__simd/traits.h
libcxx/include/experimental/__simd/utility.h
libcxx/include/experimental/simd
libcxx/test/libcxx/transitive_includes/cxx03.csv
libcxx/test/libcxx/transitive_includes/cxx11.csv
libcxx/test/libcxx/transitive_includes/cxx14.csv
libcxx/test/libcxx/transitive_includes/cxx17.csv
libcxx/test/libcxx/transitive_includes/cxx20.csv
libcxx/test/libcxx/transitive_includes/cxx23.csv
libcxx/test/libcxx/transitive_includes/cxx26.csv
libcxx/test/std/experimental/simd/test_utils.h
Removed:
################################################################################
diff --git a/libcxx/docs/Status/ParallelismProjects.csv b/libcxx/docs/Status/ParallelismProjects.csv
index 1c0ee558c9bcf8c..451ace90d6cdc29 100644
--- a/libcxx/docs/Status/ParallelismProjects.csv
+++ b/libcxx/docs/Status/ParallelismProjects.csv
@@ -4,12 +4,13 @@ Section,Description,Dependencies,Assignee,Complete
| `[parallel.alg] <https://wg21.link/N4808>`_, "Parallel algorithms", None, unassigned, |Not Started|
| `[parallel.taskblock] <https://wg21.link/N4808>`_, "Task Block", None, unassigned, |Not Started|
| `[parallel.simd.abi] <https://wg21.link/N4808>`_, "`simd ABI tags <https://reviews.llvm.org/D144362>`_", [parallel.simd.class] [parallel.simd.mask.class] declarations and alias, Yin Zhang, |Complete|
+| `[parallel.simd.synopsis] <https://wg21.link/N4808>`_, "`simd aligned tags <https://reviews.llvm.org/D153319>`_", [parallel.simd.class] [parallel.simd.mask.class] declarations, Yin Zhang, |Complete|
| `[parallel.simd.traits] <https://wg21.link/N4808>`_, "`simd type traits is_abi_tag[_v] <https://reviews.llvm.org/D144362>`_", [parallel.simd.abi], Yin Zhang, |Complete|
| `[parallel.simd.traits] <https://wg21.link/N4808>`_, "`simd type traits is_simd[_v] <https://reviews.llvm.org/D144362>`_", [parallel.simd.class] declaration and alias, Yin Zhang, |Complete|
| `[parallel.simd.traits] <https://wg21.link/N4808>`_, "`simd type traits is_simd_mask[_v] <https://reviews.llvm.org/D144362>`_", [parallel.simd.mask.class] declaration and alias, Yin Zhang, |Complete|
| `[parallel.simd.traits] <https://wg21.link/N4808>`_, "simd type traits is_simd_flag_type", None, Yin Zhang, |In Progress|
| `[parallel.simd.traits] <https://wg21.link/N4808>`_, "`simd type traits simd_size[_v] <https://reviews.llvm.org/D144363>`_", [parallel.simd.traits] is_abi_tag[_v], Yin Zhang, |Complete|
-| `[parallel.simd.traits] <https://wg21.link/N4808>`_, "simd type traits memory_alignment", None, Yin Zhang, |In Progress|
+| `[parallel.simd.traits] <https://wg21.link/N4808>`_, "`simd type traits memory_alignment <https://reviews.llvm.org/D153319>`_", [parallel.simd.aligned] simd aligned tags, Yin Zhang, |Complete|
| `[parallel.simd.traits] <https://wg21.link/N4808>`_, "simd type traits rebind_simd", None, Yin Zhang, |In Progress|
| `[parallel.simd.traits] <https://wg21.link/N4808>`_, "simd type traits resize_simd", None, Yin Zhang, |In Progress|
| `[parallel.simd.whereexpr] <https://wg21.link/N4808>`_, "Where expression class templates", None, Yin Zhang, |In Progress|
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index e2088c7cbdec2af..0bcbad31d25ae08 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -904,6 +904,7 @@ set(files
experimental/__config
experimental/__memory
experimental/__simd/abi_tag.h
+ experimental/__simd/aligned_tag.h
experimental/__simd/declaration.h
experimental/__simd/scalar.h
experimental/__simd/simd.h
diff --git a/libcxx/include/__bit/bit_ceil.h b/libcxx/include/__bit/bit_ceil.h
index 706d446359dd94f..9eae5c391a835f9 100644
--- a/libcxx/include/__bit/bit_ceil.h
+++ b/libcxx/include/__bit/bit_ceil.h
@@ -21,13 +21,13 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER >= 20
+#if _LIBCPP_STD_VER >= 17
-template <__libcpp_unsigned_integer _Tp>
-_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept {
+template <class _Tp>
+_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_ceil(_Tp __t) noexcept {
if (__t < 2)
return 1;
- const unsigned __n = numeric_limits<_Tp>::digits - std::countl_zero((_Tp)(__t - 1u));
+ const unsigned __n = numeric_limits<_Tp>::digits - std::__countl_zero((_Tp)(__t - 1u));
_LIBCPP_ASSERT_UNCATEGORIZED(__n != numeric_limits<_Tp>::digits, "Bad input to bit_ceil");
if constexpr (sizeof(_Tp) >= sizeof(unsigned))
@@ -39,7 +39,15 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noex
}
}
-#endif // _LIBCPP_STD_VER >= 20
+# if _LIBCPP_STD_VER >= 20
+
+template <__libcpp_unsigned_integer _Tp>
+_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept {
+ return std::__bit_ceil(__t);
+}
+
+# endif // _LIBCPP_STD_VER >= 20
+#endif // _LIBCPP_STD_VER >= 17
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__memory/assume_aligned.h b/libcxx/include/__memory/assume_aligned.h
index 00c2928dcce04e8..bce00bf02a718c0 100644
--- a/libcxx/include/__memory/assume_aligned.h
+++ b/libcxx/include/__memory/assume_aligned.h
@@ -22,16 +22,12 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER >= 20
-
template <size_t _Np, class _Tp>
-[[nodiscard]]
-_LIBCPP_HIDE_FROM_ABI
-constexpr _Tp* assume_aligned(_Tp* __ptr) {
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __assume_aligned(_Tp* __ptr) {
static_assert(_Np != 0 && (_Np & (_Np - 1)) == 0,
"std::assume_aligned<N>(p) requires N to be a power of two");
- if (is_constant_evaluated()) {
+ if (__libcpp_is_constant_evaluated()) {
return __ptr;
} else {
_LIBCPP_ASSERT_UNCATEGORIZED(reinterpret_cast<uintptr_t>(__ptr) % _Np == 0, "Alignment assumption is violated");
@@ -39,6 +35,13 @@ constexpr _Tp* assume_aligned(_Tp* __ptr) {
}
}
+#if _LIBCPP_STD_VER >= 20
+
+template <size_t _Np, class _Tp>
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp* assume_aligned(_Tp* __ptr) {
+ return std::__assume_aligned<_Np>(__ptr);
+}
+
#endif // _LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/experimental/__simd/aligned_tag.h b/libcxx/include/experimental/__simd/aligned_tag.h
new file mode 100644
index 000000000000000..d3816ae1b0717d7
--- /dev/null
+++ b/libcxx/include/experimental/__simd/aligned_tag.h
@@ -0,0 +1,64 @@
+// -*- 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_ALIGNED_TAG_H
+#define _LIBCPP_EXPERIMENTAL___SIMD_ALIGNED_TAG_H
+
+#include <__bit/bit_ceil.h>
+#include <__memory/assume_aligned.h>
+#include <cstdint>
+
+#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+inline namespace parallelism_v2 {
+// memory alignment
+struct element_aligned_tag {
+ template <class _Tp, class _Up = typename _Tp::value_type>
+ static constexpr size_t __alignment = alignof(_Up);
+
+ template <class _Tp, class _Up>
+ static _LIBCPP_HIDE_FROM_ABI constexpr _Up* __apply(_Up* __ptr) {
+ return __ptr;
+ }
+};
+
+struct vector_aligned_tag {
+ template <class _Tp, class _Up = typename _Tp::value_type>
+ static constexpr size_t __alignment = std::__bit_ceil(sizeof(_Up) * _Tp::size());
+
+ template <class _Tp, class _Up>
+ static _LIBCPP_HIDE_FROM_ABI constexpr _Up* __apply(_Up* __ptr) {
+ return std::__assume_aligned<__alignment<_Tp, _Up>, _Up>(__ptr);
+ }
+};
+
+template <size_t _Np>
+struct overaligned_tag {
+ template <class _Tp, class _Up = typename _Tp::value_type>
+ static constexpr size_t __alignment = _Np;
+
+ template <class _Tp, class _Up>
+ static _LIBCPP_HIDE_FROM_ABI constexpr _Up* __apply(_Up* __ptr) {
+ return std::__assume_aligned<__alignment<_Tp, _Up>, _Up>(__ptr);
+ }
+};
+
+inline constexpr element_aligned_tag element_aligned{};
+
+inline constexpr vector_aligned_tag vector_aligned{};
+
+template <size_t _Np>
+inline constexpr overaligned_tag<_Np> overaligned{};
+
+} // namespace parallelism_v2
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL
+
+#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+#endif // _LIBCPP_EXPERIMENTAL___SIMD_ALIGNED_TAG_H
diff --git a/libcxx/include/experimental/__simd/traits.h b/libcxx/include/experimental/__simd/traits.h
index 907da33c9f15e86..db6ecfa98c86480 100644
--- a/libcxx/include/experimental/__simd/traits.h
+++ b/libcxx/include/experimental/__simd/traits.h
@@ -11,6 +11,7 @@
#define _LIBCPP_EXPERIMENTAL___SIMD_TRAITS_H
#include <experimental/__simd/abi_tag.h>
+#include <experimental/__simd/aligned_tag.h>
#include <experimental/__simd/declaration.h>
#include <experimental/__simd/utility.h>
@@ -50,6 +51,21 @@ inline constexpr bool is_simd_mask_v<simd_mask<_Tp, _Abi>> = true;
template <class _Tp>
struct is_simd_mask : bool_constant<is_simd_mask_v<_Tp>> {};
+template <class _Tp>
+inline constexpr bool is_simd_flag_type_v = false;
+
+template <>
+inline constexpr bool is_simd_flag_type_v<element_aligned_tag> = true;
+
+template <>
+inline constexpr bool is_simd_flag_type_v<vector_aligned_tag> = true;
+
+template <size_t _Np>
+inline constexpr bool is_simd_flag_type_v<overaligned_tag<_Np>> = true;
+
+template <class _Tp>
+struct is_simd_flag_type : bool_constant<is_simd_flag_type_v<_Tp>> {};
+
template <class _Tp, class _Abi = simd_abi::compatible<_Tp>, bool = (__is_vectorizable_v<_Tp> && is_abi_tag_v<_Abi>)>
struct simd_size : integral_constant<size_t, _Abi::__simd_size> {};
@@ -59,6 +75,17 @@ struct simd_size<_Tp, _Abi, false> {};
template <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
inline constexpr size_t simd_size_v = simd_size<_Tp, _Abi>::value;
+template <class _Tp,
+ class _Up = typename _Tp::value_type,
+ bool = (is_simd_v<_Tp> && __is_vectorizable_v<_Up>) || (is_simd_mask_v<_Tp> && is_same_v<_Up, bool>)>
+struct memory_alignment : integral_constant<size_t, vector_aligned_tag::__alignment<_Tp, _Up>> {};
+
+template <class _Tp, class _Up>
+struct memory_alignment<_Tp, _Up, false> {};
+
+template <class _Tp, class _Up = typename _Tp::value_type>
+inline constexpr size_t memory_alignment_v = memory_alignment<_Tp, _Up>::value;
+
} // namespace parallelism_v2
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
diff --git a/libcxx/include/experimental/__simd/utility.h b/libcxx/include/experimental/__simd/utility.h
index 2f77fda49cf57f7..9f1948bfd1a405c 100644
--- a/libcxx/include/experimental/__simd/utility.h
+++ b/libcxx/include/experimental/__simd/utility.h
@@ -12,6 +12,7 @@
#include <__type_traits/is_arithmetic.h>
#include <__type_traits/is_const.h>
+#include <__type_traits/is_constant_evaluated.h>
#include <__type_traits/is_same.h>
#include <__type_traits/is_volatile.h>
diff --git a/libcxx/include/experimental/simd b/libcxx/include/experimental/simd
index e82eb380c05613b..56858832857c17d 100644
--- a/libcxx/include/experimental/simd
+++ b/libcxx/include/experimental/simd
@@ -37,6 +37,14 @@ inline namespace parallelism_v2 {
template <class T> using native_simd_mask = simd_mask<T, simd_abi::native<T>>;
template <class T, int N> using fixed_size_simd_mask = simd_mask<T, simd_abi::fixed_size<N>>;
+ // memory alignment
+ struct element_aligned_tag {};
+ struct vector_aligned_tag {};
+ template <size_t> struct overaligned_tag {};
+ inline constexpr element_aligned_tag element_aligned{};
+ inline constexpr vector_aligned_tag vector_aligned{};
+ template <size_t N> inline constexpr overaligned_tag<N> overaligned{};
+
// traits [simd.traits]
template<class T> struct is_abi_tag;
template<class T> inline constexpr bool is_abi_tag_v = is_abi_tag<T>::value;
@@ -47,10 +55,17 @@ inline namespace parallelism_v2 {
template <class T> struct is_simd_mask;
template <class T> inline constexpr bool is_simd_mask_v = is_simd_mask<T>::value;
+ template<class T> struct is_simd_flag_type;
+ template<class T> inline constexpr bool is_simd_flag_type_v = is_simd_flag_type<T>::value;
+
template<class T, class Abi = simd_abi::compatible<T>> struct simd_size;
template<class T, class Abi = simd_abi::compatible<T>>
inline constexpr size_t simd_size_v = simd_size<T,Abi>::value;
+ template<class T, class U = typename T::value_type> struct memory_alignment;
+ template<class T, class U = typename T::value_type>
+ inline constexpr size_t memory_alignment_v = memory_alignment<T,U>::value;
+
} // namespace parallelism_v2
} // namespace std::experimental
@@ -64,6 +79,8 @@ inline namespace parallelism_v2 {
#include <experimental/__config>
#include <experimental/__simd/abi_tag.h>
+#include <experimental/__simd/aligned_tag.h>
+#include <experimental/__simd/declaration.h>
#include <experimental/__simd/scalar.h>
#include <experimental/__simd/simd.h>
#include <experimental/__simd/simd_mask.h>
diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index 004ea6f78194341..f78345656175f56 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -265,6 +265,8 @@ experimental/regex regex
experimental/set experimental/memory_resource
experimental/set set
experimental/simd cstddef
+experimental/simd cstdint
+experimental/simd limits
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
index 4b40ea668ac13a4..2518c2bcafc99de 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -266,6 +266,8 @@ experimental/regex regex
experimental/set experimental/memory_resource
experimental/set set
experimental/simd cstddef
+experimental/simd cstdint
+experimental/simd limits
experimental/string experimental/memory_resource
experimental/string string
experimental/unordered_map algorithm
diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index 98e5cd784273a70..4191094251f0633 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -266,6 +266,8 @@ experimental/regex regex
experimental/set experimental/memory_resource
experimental/set set
experimental/simd cstddef
+experimental/simd cstdint
+experimental/simd limits
experimental/string experimental/memory_resource
experimental/string string
experimental/type_traits initializer_list
diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index 98e5cd784273a70..4191094251f0633 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -266,6 +266,8 @@ experimental/regex regex
experimental/set experimental/memory_resource
experimental/set set
experimental/simd cstddef
+experimental/simd cstdint
+experimental/simd limits
experimental/string experimental/memory_resource
experimental/string string
experimental/type_traits initializer_list
diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index 2b7feb5d06cde69..2cfb6e9e3861cc6 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -272,6 +272,8 @@ experimental/regex regex
experimental/set experimental/memory_resource
experimental/set set
experimental/simd cstddef
+experimental/simd cstdint
+experimental/simd limits
experimental/string experimental/memory_resource
experimental/string string
experimental/type_traits initializer_list
diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index d977ebbaf44625a..b77ffa499f8cca3 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -185,6 +185,8 @@ experimental/regex regex
experimental/set experimental/memory_resource
experimental/set set
experimental/simd cstddef
+experimental/simd cstdint
+experimental/simd limits
experimental/string experimental/memory_resource
experimental/string string
experimental/type_traits initializer_list
diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index d977ebbaf44625a..b77ffa499f8cca3 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -185,6 +185,8 @@ experimental/regex regex
experimental/set experimental/memory_resource
experimental/set set
experimental/simd cstddef
+experimental/simd cstdint
+experimental/simd limits
experimental/string experimental/memory_resource
experimental/string string
experimental/type_traits initializer_list
diff --git a/libcxx/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp b/libcxx/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp
new file mode 100644
index 000000000000000..b41569abc9a3149
--- /dev/null
+++ b/libcxx/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.traits]
+// template <class T> struct is_simd_flag_type;
+// template <class T> inline constexpr bool ex::is_simd_flag_type_v = ex::is_simd_flag_type<T>::value;
+
+#include "../test_utils.h"
+
+namespace ex = std::experimental::parallelism_v2;
+
+template <class T, std::size_t N>
+struct CheckIsSimdFlagType {
+ template <class SimdAbi>
+ void operator()() {
+ static_assert(ex::is_simd_flag_type<ex::element_aligned_tag>::value);
+ static_assert(ex::is_simd_flag_type<ex::vector_aligned_tag>::value);
+ static_assert(ex::is_simd_flag_type<ex::overaligned_tag<N>>::value);
+
+ static_assert(!ex::is_simd_flag_type<T>::value);
+ static_assert(!ex::is_simd_flag_type<ex::simd<T, SimdAbi>>::value);
+ static_assert(!ex::is_simd_flag_type<ex::simd_mask<T, SimdAbi>>::value);
+
+ static_assert(ex::is_simd_flag_type_v<ex::element_aligned_tag>);
+ static_assert(ex::is_simd_flag_type_v<ex::vector_aligned_tag>);
+ static_assert(ex::is_simd_flag_type_v<ex::overaligned_tag<N>>);
+
+ static_assert(!ex::is_simd_flag_type_v<T>);
+ static_assert(!ex::is_simd_flag_type_v<ex::simd<T, SimdAbi>>);
+ static_assert(!ex::is_simd_flag_type_v<ex::simd_mask<T, SimdAbi>>);
+ }
+};
+
+int main(int, char**) {
+ test_all_simd_abi<CheckIsSimdFlagType>();
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/simd/simd.traits/memory_alignment.pass.cpp b/libcxx/test/std/experimental/simd/simd.traits/memory_alignment.pass.cpp
new file mode 100644
index 000000000000000..360428a59daa315
--- /dev/null
+++ b/libcxx/test/std/experimental/simd/simd.traits/memory_alignment.pass.cpp
@@ -0,0 +1,119 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.traits]
+// template <class T, class U = typename T::value_type> struct memory_alignment;
+// template <class T, class U = typename T::value_type>
+// inline constexpr std::size_t memory_alignment_v = memory_alignment<T, U>::value;
+
+#include "../test_utils.h"
+
+namespace ex = std::experimental::parallelism_v2;
+
+template <class T, std::size_t N>
+struct CheckMemoryAlignmentMask {
+ template <class SimdAbi>
+ void operator()() {
+ LIBCPP_STATIC_ASSERT(
+ ex::memory_alignment<ex::simd_mask<T, SimdAbi>>::value == bit_ceil(sizeof(bool) * ex::simd_size_v<T, SimdAbi>));
+ LIBCPP_STATIC_ASSERT(
+ ex::memory_alignment_v<ex::simd_mask<T, SimdAbi>> == bit_ceil(sizeof(bool) * ex::simd_size_v<T, SimdAbi>));
+ }
+};
+
+template <class T, std::size_t N>
+struct CheckMemoryAlignmentLongDouble {
+ template <class SimdAbi>
+ void operator()() {
+ if constexpr (std::is_same_v<T, long double>) {
+ // on i686-w64-mingw32-clang++, the size of long double is 12 bytes. Disambiguation is needed.
+ static_assert(
+ ex::memory_alignment<ex::simd<T, SimdAbi>>::value == bit_ceil(sizeof(T) * ex::simd_size_v<T, SimdAbi>));
+ static_assert(ex::memory_alignment_v<ex::simd<T, SimdAbi>> == bit_ceil(sizeof(T) * ex::simd_size_v<T, SimdAbi>));
+ }
+ }
+};
+
+struct CheckMemAlignmentFixedDeduce {
+ template <class T, std::size_t N>
+ void check() {
+ if constexpr (!std::is_same_v<T, long double>) {
+ static_assert(ex::memory_alignment_v<ex::simd<T, ex::simd_abi::fixed_size<N>>> == sizeof(T) * bit_ceil(N),
+ "Memory Alignment mismatch with abi fixed_size");
+ static_assert(ex::memory_alignment<ex::simd<T, ex::simd_abi::fixed_size<N>>>::value == sizeof(T) * bit_ceil(N),
+ "Memory Alignment mismatch with abi fixed_size");
+
+ static_assert(ex::memory_alignment_v<ex::simd<T, ex::simd_abi::deduce_t<T, N>>> == sizeof(T) * bit_ceil(N),
+ "Memory Alignment mismatch with abi deduce");
+ static_assert(ex::memory_alignment<ex::simd<T, ex::simd_abi::deduce_t<T, N>>>::value == sizeof(T) * bit_ceil(N),
+ "Memory Alignment mismatch with abi deduce");
+ }
+ }
+
+ template <class T, std::size_t... N>
+ void performChecks(std::index_sequence<N...>) {
+ (check<T, N + 1>(), ...);
+ }
+
+ template <class T>
+ void operator()() {
+ performChecks<T>(std::make_index_sequence<max_simd_size>{});
+ }
+};
+
+struct CheckMemAlignmentScalarNativeCompatible {
+ template <class T>
+ void operator()() {
+ if constexpr (!std::is_same_v<T, long double>) {
+ static_assert(ex::memory_alignment<ex::simd<T, ex::simd_abi::scalar>>::value == sizeof(T));
+ static_assert(ex::memory_alignment_v<ex::simd<T, ex::simd_abi::scalar>> == sizeof(T));
+
+ LIBCPP_STATIC_ASSERT(ex::memory_alignment<ex::simd<T, ex::simd_abi::compatible<T>>>::value == 16);
+ LIBCPP_STATIC_ASSERT(ex::memory_alignment_v<ex::simd<T, ex::simd_abi::compatible<T>>> == 16);
+
+ LIBCPP_STATIC_ASSERT(
+ ex::memory_alignment<ex::simd<T, ex::simd_abi::native<T>>>::value == _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES);
+ LIBCPP_STATIC_ASSERT(
+ ex::memory_alignment_v<ex::simd<T, ex::simd_abi::native<T>>> == _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES);
+ }
+ }
+};
+
+template <class T, class U = typename T::value_type, class = void>
+struct has_memory_alignment : std::false_type {};
+
+template <class T, class U>
+struct has_memory_alignment<T, U, std::void_t<decltype(ex::memory_alignment<T, U>::value)>> : std::true_type {};
+
+struct CheckMemoryAlignmentTraits {
+ template <class T>
+ void operator()() {
+ static_assert(has_memory_alignment<ex::native_simd<T>>::value);
+ static_assert(has_memory_alignment<ex::fixed_size_simd_mask<T, 4>>::value);
+ static_assert(has_memory_alignment<ex::native_simd<T>, T>::value);
+ static_assert(has_memory_alignment<ex::fixed_size_simd_mask<T, 4>, bool>::value);
+
+ static_assert(!has_memory_alignment<T, T>::value);
+ static_assert(!has_memory_alignment<T, bool>::value);
+ static_assert(!has_memory_alignment<ex::native_simd<T>, bool>::value);
+ static_assert(!has_memory_alignment<ex::fixed_size_simd_mask<T, 4>, T>::value);
+ }
+};
+
+int main(int, char**) {
+ types::for_each(arithmetic_no_bool_types(), CheckMemAlignmentFixedDeduce());
+ types::for_each(arithmetic_no_bool_types(), CheckMemAlignmentScalarNativeCompatible());
+ test_all_simd_abi<CheckMemoryAlignmentMask>();
+ test_all_simd_abi<CheckMemoryAlignmentLongDouble>();
+ types::for_each(arithmetic_no_bool_types(), CheckMemoryAlignmentTraits());
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/simd/simd.traits/memory_alignment.verify.cpp b/libcxx/test/std/experimental/simd/simd.traits/memory_alignment.verify.cpp
new file mode 100644
index 000000000000000..ff7e05334f264a6
--- /dev/null
+++ b/libcxx/test/std/experimental/simd/simd.traits/memory_alignment.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
+
+// <experimental/simd>
+//
+// [simd.traits]
+// template <class T, class U = typename T::value_type> struct memory_alignment;
+// template <class T, class U = typename T::value_type>
+// inline constexpr std::size_t memory_alignment_v = memory_alignment<T, U>::value;
+
+#include <experimental/simd>
+
+namespace ex = std::experimental::parallelism_v2;
+
+int main(int, char**) {
+ (void)ex::memory_alignment<ex::native_simd<bool>, bool>::value;
+ // expected-error-re@* {{no member named 'value' in {{.*}}}}
+ (void)ex::memory_alignment<int, int>::value;
+ // expected-error-re@* {{no member named 'value' in {{.*}}}}
+ (void)ex::memory_alignment<ex::native_simd_mask<int>, int>::value;
+ // expected-error-re@* {{no member named 'value' in {{.*}}}}
+ (void)ex::memory_alignment<ex::native_simd<int>, bool>::value;
+ // expected-error-re@* {{no member named 'value' in {{.*}}}}
+
+ (void)ex::memory_alignment_v<ex::native_simd<bool>, bool>;
+ // expected-error-re@* {{no member named 'value' in {{.*}}}}
+ (void)ex::memory_alignment_v<int, int>;
+ // expected-error-re@* {{no member named 'value' in {{.*}}}}
+ (void)ex::memory_alignment_v<ex::native_simd_mask<int>, int>;
+ // expected-error-re@* {{no member named 'value' in {{.*}}}}
+ (void)ex::memory_alignment_v<ex::native_simd<int>, bool>;
+ // 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
index 0116412e8a6294a..003d7153122673b 100644
--- a/libcxx/test/std/experimental/simd/test_utils.h
+++ b/libcxx/test/std/experimental/simd/test_utils.h
@@ -43,4 +43,11 @@ void test_all_simd_abi() {
types::for_each(arithmetic_no_bool_types(), TestAllSimdAbiFunctor<Func>());
}
+constexpr size_t bit_ceil(size_t val) {
+ size_t pow = 1;
+ while (pow < val)
+ pow <<= 1;
+ return pow;
+}
+
#endif // TEST_UTIL_H
More information about the libcxx-commits
mailing list