[libcxx-commits] [libcxx] e7a45c6 - [libcxx] <experimental/simd> Added internal storage type, constructors, subscript operators of class simd/simd_mask and related tests

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Sep 11 20:42:05 PDT 2023


Author: Zhangyin
Date: 2023-09-12T11:41:46+08:00
New Revision: e7a45c6d768b755644ce44e095332924009887a3

URL: https://github.com/llvm/llvm-project/commit/e7a45c6d768b755644ce44e095332924009887a3
DIFF: https://github.com/llvm/llvm-project/commit/e7a45c6d768b755644ce44e095332924009887a3.diff

LOG: [libcxx] <experimental/simd> Added internal storage type, constructors, subscript operators of class simd/simd_mask and related tests

[libcxx] <experimental/simd> Added internal storage type for class simd/simd_mask
[libcxx] <experimental/simd> Added all constructors of class simd/simd_mask and related tests
[libcxx] <experimental/simd> Added basic simd reference implementation, subscript operators of class simd/simd_mask and related tests

Reviewed By: #libc, philnik

Differential Revision: https://reviews.llvm.org/D144364

Added: 
    libcxx/include/experimental/__simd/internal_declaration.h
    libcxx/include/experimental/__simd/reference.h
    libcxx/test/std/experimental/simd/simd.reference/reference_alias.pass.cpp

Modified: 
    libcxx/include/CMakeLists.txt
    libcxx/include/experimental/__simd/scalar.h
    libcxx/include/experimental/__simd/simd.h
    libcxx/include/experimental/__simd/simd_mask.h
    libcxx/include/experimental/__simd/utility.h
    libcxx/include/experimental/__simd/vec_ext.h
    libcxx/test/std/experimental/simd/test_utils.h

Removed: 
    


################################################################################
diff  --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 0bcbad31d25ae08..7af9b85b974211f 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -906,6 +906,8 @@ set(files
   experimental/__simd/abi_tag.h
   experimental/__simd/aligned_tag.h
   experimental/__simd/declaration.h
+  experimental/__simd/internal_declaration.h
+  experimental/__simd/reference.h
   experimental/__simd/scalar.h
   experimental/__simd/simd.h
   experimental/__simd/simd_mask.h

diff  --git a/libcxx/include/experimental/__simd/internal_declaration.h b/libcxx/include/experimental/__simd/internal_declaration.h
new file mode 100644
index 000000000000000..294b54d63bb5d9f
--- /dev/null
+++ b/libcxx/include/experimental/__simd/internal_declaration.h
@@ -0,0 +1,34 @@
+// -*- 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_INTERNAL_DECLARATION_H
+#define _LIBCPP_EXPERIMENTAL___SIMD_INTERNAL_DECLARATION_H
+
+#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+inline namespace parallelism_v2 {
+
+template <class _Tp, class _Abi>
+struct __simd_storage;
+
+template <class _Tp, class _Abi>
+struct __mask_storage;
+
+template <class _Tp, class _Abi>
+struct __simd_operations;
+
+template <class _Tp, class _Abi>
+struct __mask_operations;
+
+} // namespace parallelism_v2
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL
+
+#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+#endif // _LIBCPP_EXPERIMENTAL___SIMD_INTERNAL_DECLARATION_H

diff  --git a/libcxx/include/experimental/__simd/reference.h b/libcxx/include/experimental/__simd/reference.h
new file mode 100644
index 000000000000000..a9c17a230458d61
--- /dev/null
+++ b/libcxx/include/experimental/__simd/reference.h
@@ -0,0 +1,49 @@
+// -*- 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_REFERENCE_H
+#define _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H
+
+#include <experimental/__simd/utility.h>
+
+#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+inline namespace parallelism_v2 {
+template <class _Tp, class _Storage, class _Vp>
+class __simd_reference {
+  template <class, class>
+  friend class simd;
+  template <class, class>
+  friend class simd_mask;
+
+  _Storage& __s_;
+  size_t __idx_;
+
+  _LIBCPP_HIDE_FROM_ABI _Vp __get() const { return __s_.__get(__idx_); }
+
+  _LIBCPP_HIDE_FROM_ABI void __set(_Vp __v) {
+    if constexpr (is_same_v<_Vp, bool>)
+      __s_.__set(__idx_, experimental::__set_all_bits<_Tp>(__v));
+    else
+      __s_.__set(__idx_, __v);
+  }
+
+public:
+  using value_type = _Vp;
+
+  __simd_reference()                        = delete;
+  __simd_reference(const __simd_reference&) = delete;
+};
+
+} // namespace parallelism_v2
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL
+
+#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+#endif // _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H

diff  --git a/libcxx/include/experimental/__simd/scalar.h b/libcxx/include/experimental/__simd/scalar.h
index d96299e658a0ff2..76bd4d041163a2a 100644
--- a/libcxx/include/experimental/__simd/scalar.h
+++ b/libcxx/include/experimental/__simd/scalar.h
@@ -11,6 +11,7 @@
 #define _LIBCPP_EXPERIMENTAL___SIMD_SCALAR_H
 
 #include <cstddef>
+#include <experimental/__simd/internal_declaration.h>
 
 #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
 
@@ -20,8 +21,36 @@ namespace simd_abi {
 struct __scalar {
   static constexpr size_t __simd_size = 1;
 };
-
 } // namespace simd_abi
+
+template <class _Tp>
+struct __simd_storage<_Tp, simd_abi::__scalar> {
+  _Tp __data;
+
+  _Tp __get([[maybe_unused]] size_t __idx) const noexcept {
+    _LIBCPP_ASSERT_UNCATEGORIZED(__idx == 0, "Index is out of bounds");
+    return __data;
+  }
+  void __set([[maybe_unused]] size_t __idx, _Tp __v) noexcept {
+    _LIBCPP_ASSERT_UNCATEGORIZED(__idx == 0, "Index is out of bounds");
+    __data = __v;
+  }
+};
+
+template <class _Tp>
+struct __mask_storage<_Tp, simd_abi::__scalar> : __simd_storage<bool, simd_abi::__scalar> {};
+
+template <class _Tp>
+struct __simd_operations<_Tp, simd_abi::__scalar> {
+  using _SimdStorage = __simd_storage<_Tp, simd_abi::__scalar>;
+  using _MaskStorage = __mask_storage<_Tp, simd_abi::__scalar>;
+};
+
+template <class _Tp>
+struct __mask_operations<_Tp, simd_abi::__scalar> {
+  using _MaskStorage = __mask_storage<_Tp, simd_abi::__scalar>;
+};
+
 } // namespace parallelism_v2
 _LIBCPP_END_NAMESPACE_EXPERIMENTAL
 

diff  --git a/libcxx/include/experimental/__simd/simd.h b/libcxx/include/experimental/__simd/simd.h
index 5bbc3e6993a57a2..371e8a65d730a01 100644
--- a/libcxx/include/experimental/__simd/simd.h
+++ b/libcxx/include/experimental/__simd/simd.h
@@ -12,7 +12,10 @@
 
 #include <experimental/__simd/abi_tag.h>
 #include <experimental/__simd/declaration.h>
+#include <experimental/__simd/reference.h>
+#include <experimental/__simd/scalar.h>
 #include <experimental/__simd/traits.h>
+#include <experimental/__simd/vec_ext.h>
 
 #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
 
@@ -23,8 +26,14 @@ inline namespace parallelism_v2 {
 // TODO: implement simd class
 template <class _Tp, class _Abi>
 class simd {
+  using _Impl    = __simd_operations<_Tp, _Abi>;
+  using _Storage = typename _Impl::_SimdStorage;
+
+  _Storage __s_;
+
 public:
   using value_type = _Tp;
+  using reference  = __simd_reference<_Tp, _Storage, value_type>;
   using mask_type  = simd_mask<_Tp, _Abi>;
   using abi_type   = _Abi;
 

diff  --git a/libcxx/include/experimental/__simd/simd_mask.h b/libcxx/include/experimental/__simd/simd_mask.h
index 4ef585f64d54abd..1fe42dca0dfc20f 100644
--- a/libcxx/include/experimental/__simd/simd_mask.h
+++ b/libcxx/include/experimental/__simd/simd_mask.h
@@ -12,6 +12,9 @@
 
 #include <experimental/__simd/abi_tag.h>
 #include <experimental/__simd/declaration.h>
+#include <experimental/__simd/reference.h>
+#include <experimental/__simd/scalar.h>
+#include <experimental/__simd/vec_ext.h>
 
 #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
 
@@ -22,8 +25,14 @@ inline namespace parallelism_v2 {
 // TODO: implement simd_mask class
 template <class _Tp, class _Abi>
 class simd_mask {
+  using _Impl    = __mask_operations<_Tp, _Abi>;
+  using _Storage = typename _Impl::_MaskStorage;
+
+  _Storage __s_;
+
 public:
   using value_type = bool;
+  using reference  = __simd_reference<_Tp, _Storage, value_type>;
   using simd_type  = simd<_Tp, _Abi>;
   using abi_type   = _Abi;
 

diff  --git a/libcxx/include/experimental/__simd/utility.h b/libcxx/include/experimental/__simd/utility.h
index 9f1948bfd1a405c..7676ff240f6a7ab 100644
--- a/libcxx/include/experimental/__simd/utility.h
+++ b/libcxx/include/experimental/__simd/utility.h
@@ -15,6 +15,11 @@
 #include <__type_traits/is_constant_evaluated.h>
 #include <__type_traits/is_same.h>
 #include <__type_traits/is_volatile.h>
+#include <cstdint>
+#include <limits>
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
 
 #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
 
@@ -23,8 +28,37 @@ inline namespace parallelism_v2 {
 template <class _Tp>
 constexpr bool __is_vectorizable_v =
     is_arithmetic_v<_Tp> && !is_const_v<_Tp> && !is_volatile_v<_Tp> && !is_same_v<_Tp, bool>;
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI auto __choose_mask_type() {
+  if constexpr (sizeof(_Tp) == 1) {
+    return uint8_t{};
+  } else if constexpr (sizeof(_Tp) == 2) {
+    return uint16_t{};
+  } else if constexpr (sizeof(_Tp) == 4) {
+    return uint32_t{};
+  } else if constexpr (sizeof(_Tp) == 8) {
+    return uint64_t{};
+  }
+#  ifndef _LIBCPP_HAS_NO_INT128
+  else if constexpr (sizeof(_Tp) == 16) {
+    return __uint128_t{};
+  }
+#  endif
+  else
+    static_assert(sizeof(_Tp) == 0, "Unexpected size");
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI auto constexpr __set_all_bits(bool __v) {
+  return __v ? (numeric_limits<decltype(__choose_mask_type<_Tp>())>::max()) : 0;
+}
+
 } // namespace parallelism_v2
 _LIBCPP_END_NAMESPACE_EXPERIMENTAL
 
 #endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+_LIBCPP_POP_MACROS
+
 #endif // _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H

diff  --git a/libcxx/include/experimental/__simd/vec_ext.h b/libcxx/include/experimental/__simd/vec_ext.h
index 4ece1dc2cda7983..c50f49252124e21 100644
--- a/libcxx/include/experimental/__simd/vec_ext.h
+++ b/libcxx/include/experimental/__simd/vec_ext.h
@@ -10,7 +10,10 @@
 #ifndef _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H
 #define _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H
 
+#include <__bit/bit_ceil.h>
 #include <cstddef>
+#include <experimental/__simd/internal_declaration.h>
+#include <experimental/__simd/utility.h>
 
 #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
 
@@ -21,8 +24,37 @@ template <int _Np>
 struct __vec_ext {
   static constexpr size_t __simd_size = _Np;
 };
-
 } // namespace simd_abi
+
+template <class _Tp, int _Np>
+struct __simd_storage<_Tp, simd_abi::__vec_ext<_Np>> {
+  _Tp __data __attribute__((__vector_size__(std::__bit_ceil((sizeof(_Tp) * _Np)))));
+
+  _Tp __get(size_t __idx) const noexcept {
+    _LIBCPP_ASSERT_UNCATEGORIZED(__idx > 0 && __idx <= _Np, "Index is out of bounds");
+    return __data[__idx];
+  }
+  void __set(size_t __idx, _Tp __v) noexcept {
+    _LIBCPP_ASSERT_UNCATEGORIZED(__idx > 0 && __idx <= _Np, "Index is out of bounds");
+    __data[__idx] = __v;
+  }
+};
+
+template <class _Tp, int _Np>
+struct __mask_storage<_Tp, simd_abi::__vec_ext<_Np>>
+    : __simd_storage<decltype(experimental::__choose_mask_type<_Tp>()), simd_abi::__vec_ext<_Np>> {};
+
+template <class _Tp, int _Np>
+struct __simd_operations<_Tp, simd_abi::__vec_ext<_Np>> {
+  using _SimdStorage = __simd_storage<_Tp, simd_abi::__vec_ext<_Np>>;
+  using _MaskStorage = __mask_storage<_Tp, simd_abi::__vec_ext<_Np>>;
+};
+
+template <class _Tp, int _Np>
+struct __mask_operations<_Tp, simd_abi::__vec_ext<_Np>> {
+  using _MaskStorage = __mask_storage<_Tp, simd_abi::__vec_ext<_Np>>;
+};
+
 } // namespace parallelism_v2
 _LIBCPP_END_NAMESPACE_EXPERIMENTAL
 

diff  --git a/libcxx/test/std/experimental/simd/simd.reference/reference_alias.pass.cpp b/libcxx/test/std/experimental/simd/simd.reference/reference_alias.pass.cpp
new file mode 100644
index 000000000000000..31e6319032d2080
--- /dev/null
+++ b/libcxx/test/std/experimental/simd/simd.reference/reference_alias.pass.cpp
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+// simd::reference::value_type
+// simd_mask::reference::value_type
+
+#include "../test_utils.h"
+#include <experimental/simd>
+
+namespace ex = std::experimental::parallelism_v2;
+
+template <class T, std::size_t>
+struct CheckRefAlias {
+  template <class SimdAbi>
+  void operator()() {
+    static_assert(std::is_same_v<typename ex::simd<T, SimdAbi>::reference::value_type, T>);
+    static_assert(std::is_same_v<typename ex::simd_mask<T, SimdAbi>::reference::value_type, bool>);
+  }
+};
+
+int main(int, char**) {
+  test_all_simd_abi<CheckRefAlias>();
+  return 0;
+}

diff  --git a/libcxx/test/std/experimental/simd/test_utils.h b/libcxx/test/std/experimental/simd/test_utils.h
index 003d7153122673b..6b9fa146b5364c1 100644
--- a/libcxx/test/std/experimental/simd/test_utils.h
+++ b/libcxx/test/std/experimental/simd/test_utils.h
@@ -36,7 +36,12 @@ struct TestAllSimdAbiFunctor {
   }
 };
 
+// TODO: Support long double (12 bytes) for MinGW (DLL, i686)
+#ifdef __MINGW32__
+using arithmetic_no_bool_types = types::concatenate_t<types::integer_types, types::type_list<float, double>>;
+#else
 using arithmetic_no_bool_types = types::concatenate_t<types::integer_types, types::floating_point_types>;
+#endif
 
 template <template <class T, std::size_t N> class Func>
 void test_all_simd_abi() {


        


More information about the libcxx-commits mailing list