[libcxx-commits] [libcxx] [libcxx] <experimental/simd> Add generate constructor of class simd (PR #66737)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Oct 12 03:41:07 PDT 2023


https://github.com/joy2myself updated https://github.com/llvm/llvm-project/pull/66737

>From 4dc65d2a7f416b5018e5faf654ab0da3f963159e Mon Sep 17 00:00:00 2001
From: Yin Zhang <zhangyin2018 at iscas.ac.cn>
Date: Sat, 7 Oct 2023 13:41:29 +0800
Subject: [PATCH] [libcxx] <experimental/simd> Add generate constructor of
 class simd

Differential Revision: https://reviews.llvm.org/D159442
---
 libcxx/docs/Status/ParallelismProjects.csv    |  1 +
 libcxx/include/experimental/__simd/scalar.h   |  5 ++
 libcxx/include/experimental/__simd/simd.h     |  4 ++
 libcxx/include/experimental/__simd/utility.h  | 20 +++++++
 libcxx/include/experimental/__simd/vec_ext.h  | 11 ++++
 .../simd.class/simd_ctor_generator.pass.cpp   | 56 +++++++++++++++++++
 6 files changed, 97 insertions(+)
 create mode 100644 libcxx/test/std/experimental/simd/simd.class/simd_ctor_generator.pass.cpp

diff --git a/libcxx/docs/Status/ParallelismProjects.csv b/libcxx/docs/Status/ParallelismProjects.csv
index 8ce6403c27b4062..be3663bf087b47e 100644
--- a/libcxx/docs/Status/ParallelismProjects.csv
+++ b/libcxx/docs/Status/ParallelismProjects.csv
@@ -17,6 +17,7 @@ Section,Description,Dependencies,Assignee,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 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>`_, "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|
diff --git a/libcxx/include/experimental/__simd/scalar.h b/libcxx/include/experimental/__simd/scalar.h
index 341292612e049f4..479809392f81539 100644
--- a/libcxx/include/experimental/__simd/scalar.h
+++ b/libcxx/include/experimental/__simd/scalar.h
@@ -46,6 +46,11 @@ struct __simd_operations<_Tp, simd_abi::__scalar> {
   using _MaskStorage = __mask_storage<_Tp, simd_abi::__scalar>;
 
   static _LIBCPP_HIDE_FROM_ABI _SimdStorage __broadcast(_Tp __v) noexcept { return {__v}; }
+
+  template <class _Generator>
+  static _LIBCPP_HIDE_FROM_ABI _SimdStorage __generate(_Generator&& __g) noexcept {
+    return {__g(std::integral_constant<size_t, 0>())};
+  }
 };
 
 template <class _Tp>
diff --git a/libcxx/include/experimental/__simd/simd.h b/libcxx/include/experimental/__simd/simd.h
index 30856f4b03c9db0..954f94c90784e2f 100644
--- a/libcxx/include/experimental/__simd/simd.h
+++ b/libcxx/include/experimental/__simd/simd.h
@@ -44,6 +44,10 @@ class simd {
   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))) {}
 
+  // generator constructor
+  template <class _Generator, enable_if_t<__can_generate_v<value_type, _Generator, size()>, int> = 0>
+  explicit _LIBCPP_HIDE_FROM_ABI simd(_Generator&& __g) : __s_(_Impl::__generate(std::forward<_Generator>(__g))) {}
+
   // scalar access [simd.subscr]
   // Add operator[] temporarily to test braodcast. Add test for it in later patch.
   _LIBCPP_HIDE_FROM_ABI value_type operator[](size_t __i) const { return __s_.__get(__i); }
diff --git a/libcxx/include/experimental/__simd/utility.h b/libcxx/include/experimental/__simd/utility.h
index 0dba345e05377a3..847d006629c8d3b 100644
--- a/libcxx/include/experimental/__simd/utility.h
+++ b/libcxx/include/experimental/__simd/utility.h
@@ -19,6 +19,7 @@
 #include <__type_traits/is_volatile.h>
 #include <__type_traits/void_t.h>
 #include <__utility/declval.h>
+#include <__utility/integer_sequence.h>
 #include <cstdint>
 #include <limits>
 
@@ -71,6 +72,25 @@ inline constexpr bool __can_broadcast_v =
     (!__is_vectorizable_v<_Up> && is_convertible_v<_Up, _Tp>) || is_same_v<_Up, int> ||
     (is_same_v<_Up, unsigned int> && is_unsigned_v<_Tp>);
 
+template <class _Tp, class _Generator, std::size_t _Idx, class = void>
+inline constexpr bool __is_well_formed = false;
+
+template <class _Tp, class _Generator, std::size_t _Idx>
+inline constexpr bool
+    __is_well_formed<_Tp,
+                     _Generator,
+                     _Idx,
+                     std::void_t<decltype(std::declval<_Generator>()(integral_constant<size_t, _Idx>()))>> =
+        __can_broadcast_v<_Tp, decltype(std::declval<_Generator>()(integral_constant<size_t, _Idx>()))>;
+
+template <class _Tp, class _Generator, std::size_t... _Idxes>
+_LIBCPP_HIDE_FROM_ABI constexpr bool __can_generate(index_sequence<_Idxes...>) {
+  return (true && ... && __is_well_formed<_Tp, _Generator, _Idxes>);
+}
+
+template <class _Tp, class _Generator, std::size_t _Size>
+inline constexpr bool __can_generate_v = experimental::__can_generate<_Tp, _Generator>(make_index_sequence<_Size>());
+
 } // namespace parallelism_v2
 _LIBCPP_END_NAMESPACE_EXPERIMENTAL
 
diff --git a/libcxx/include/experimental/__simd/vec_ext.h b/libcxx/include/experimental/__simd/vec_ext.h
index 44a1f481ab7985f..4b23bfe384477ed 100644
--- a/libcxx/include/experimental/__simd/vec_ext.h
+++ b/libcxx/include/experimental/__simd/vec_ext.h
@@ -11,6 +11,7 @@
 #define _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H
 
 #include <__bit/bit_ceil.h>
+#include <__utility/forward.h>
 #include <cstddef>
 #include <experimental/__simd/internal_declaration.h>
 #include <experimental/__simd/utility.h>
@@ -56,6 +57,16 @@ struct __simd_operations<_Tp, simd_abi::__vec_ext<_Np>> {
     }
     return __result;
   }
+
+  template <class _Generator, size_t... _Is>
+  static _LIBCPP_HIDE_FROM_ABI _SimdStorage __generate_init(_Generator&& __g, std::index_sequence<_Is...>) {
+    return _SimdStorage{{__g(std::integral_constant<size_t, _Is>())...}};
+  }
+
+  template <class _Generator>
+  static _LIBCPP_HIDE_FROM_ABI _SimdStorage __generate(_Generator&& __g) noexcept {
+    return __generate_init(std::forward<_Generator>(__g), std::make_index_sequence<_Np>());
+  }
 };
 
 template <class _Tp, int _Np>
diff --git a/libcxx/test/std/experimental/simd/simd.class/simd_ctor_generator.pass.cpp b/libcxx/test/std/experimental/simd/simd.class/simd_ctor_generator.pass.cpp
new file mode 100644
index 000000000000000..6349d2f1a1b323c
--- /dev/null
+++ b/libcxx/test/std/experimental/simd/simd.class/simd_ctor_generator.pass.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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]
+// template<class G> explicit simd(G&& gen) noexcept;
+
+#include "../test_utils.h"
+#include <experimental/simd>
+
+namespace ex = std::experimental::parallelism_v2;
+
+template <class T, std::size_t>
+struct CheckGenerateSimdCtor {
+  template <class SimdAbi>
+  void operator()() {
+    ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
+    constexpr size_t array_size = origin_simd.size();
+    std::array<T, array_size> expected_value;
+    for (size_t i = 0; i < array_size; ++i)
+      expected_value[i] = static_cast<T>(i);
+    assert_simd_values_equal<array_size>(origin_simd, expected_value);
+  }
+};
+
+template <class U, class T, class SimdAbi = ex::simd_abi::compatible<T>, class = void>
+struct has_generate_ctor : std::false_type {};
+
+template <class U, class T, class SimdAbi>
+struct has_generate_ctor<U, T, SimdAbi, std::void_t<decltype(ex::simd<T, SimdAbi>(std::declval<U>()))>>
+    : std::true_type {};
+
+template <class T, std::size_t>
+struct CheckGenerateCtorTraits {
+  template <class SimdAbi>
+  void operator()() {
+    static_assert(!has_generate_ctor<SimdAbi, T, SimdAbi>::value);
+
+    auto func = [](T i) { return i; };
+    static_assert(has_generate_ctor<decltype(func), T, SimdAbi>::value);
+  }
+};
+
+int main(int, char**) {
+  test_all_simd_abi<CheckGenerateSimdCtor>();
+  test_all_simd_abi<CheckGenerateCtorTraits>();
+  return 0;
+}



More information about the libcxx-commits mailing list