timshen updated this revision to Diff 139039.
timshen added a comment.
Herald added a subscriber: christof.

Rebase.


https://reviews.llvm.org/D41415

Files:
  libcxx/include/experimental/simd
  libcxx/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp
  libcxx/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp
  libcxx/test/std/experimental/simd/simd.casts/to_compatible.pass.cpp
  libcxx/test/std/experimental/simd/simd.casts/to_fixed_size.pass.cpp
  libcxx/test/std/experimental/simd/simd.casts/to_native.pass.cpp

Index: libcxx/test/std/experimental/simd/simd.casts/to_native.pass.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/experimental/simd/simd.casts/to_native.pass.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <experimental/simd>
+//
+// [simd.casts]
+//
+// template <class T, size_t N>
+// native_simd<T> to_native(const fixed_size_simd<T, N>&) noexcept;
+//
+// template <class T, size_t N>
+// native_simd_mask<T> to_native(const fixed_size_simd_mask<T, N>&) noexcept;
+
+#include <experimental/simd>
+#include <cstdint>
+
+using namespace std::experimental::parallelism_v2;
+
+void test_to_native() {
+  auto v = to_native(
+      fixed_size_simd<int, native_simd<int>::size()>([](int i) { return i; }));
+  native_simd<int> w([](int i) { return i; });
+
+  static_assert(std::is_same<decltype(v), decltype(w)>::value, "");
+
+  for (size_t i = 0; i < v.size(); i++) {
+    assert(v[i] == w[i]);
+  }
+}
+
+void test_to_native_extension() {
+  auto arr = split_by<32 / native_simd<int>::size()>(
+      to_native(fixed_size_simd<int, 32>([](int i) { return i; })));
+  static_assert(
+      std::is_same<decltype(arr)::value_type, native_simd<int>>::value, "");
+  int v = 0;
+  for (size_t i = 0; i < arr.size(); i++) {
+    for (size_t j = 0; j < arr[0].size(); j++) {
+      assert(arr[i][j] == v);
+      v++;
+    }
+  }
+}
+
+int main() {
+  test_to_native();
+  test_to_native_extension();
+}
Index: libcxx/test/std/experimental/simd/simd.casts/to_fixed_size.pass.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/experimental/simd/simd.casts/to_fixed_size.pass.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <experimental/simd>
+//
+// [simd.casts]
+//
+// template <class T, class Abi>
+// fixed_size_simd<T, simd_size_v<T, Abi>>
+// to_fixed_size(const simd<T, Abi>&) noexcept;
+//
+// template <class T, class Abi>
+// fixed_size_simd_mask<T, simd_size_v<T, Abi>>
+// to_fixed_size(const simd_mask<T, Abi>&) noexcept;
+
+#include <experimental/simd>
+#include <cstdint>
+
+using namespace std::experimental::parallelism_v2;
+
+void test_to_fixed_size() {
+  auto v = to_fixed_size(native_simd<int>([](int i) { return i; }));
+  static_assert(std::is_same<fixed_size_simd<int, native_simd<int>::size()>,
+                             decltype(v)>::value,
+                "");
+
+  for (size_t i = 0; i < v.size(); i++) {
+    assert(v[i] == (int)i);
+  }
+}
+
+int main() { test_to_fixed_size(); }
Index: libcxx/test/std/experimental/simd/simd.casts/to_compatible.pass.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/experimental/simd/simd.casts/to_compatible.pass.cpp
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <experimental/simd>
+//
+// [simd.casts]
+//
+// template <class T, size_t N> simd<T>
+// to_compatible(const fixed_size_simd<T, N>&) noexcept;
+//
+// template <class T, size_t N> simd_mask<T>
+// to_compatible(const fixed_size_simd_mask<T, N>&) noexcept;
+
+#include <experimental/simd>
+#include <cstdint>
+
+using namespace std::experimental::parallelism_v2;
+
+void test_to_compatible() {
+  auto v = to_compatible(
+      fixed_size_simd<int, simd<int>::size()>([](int i) { return i; }));
+  simd<int> w([](int i) { return i; });
+
+  static_assert(std::is_same<decltype(v), decltype(w)>::value, "");
+
+  for (size_t i = 0; i < v.size(); i++) {
+    assert(v[i] == w[i]);
+  }
+}
+
+void test_to_compatible_extension() {
+  auto arr = split_by<32 / simd<int>::size()>(
+      to_compatible(fixed_size_simd<int, 32>([](int i) { return i; })));
+  static_assert(std::is_same<decltype(arr)::value_type, simd<int>>::value, "");
+  int v = 0;
+  for (size_t i = 0; i < arr.size(); i++) {
+    for (size_t j = 0; j < arr[0].size(); j++) {
+      assert(arr[i][j] == v);
+      v++;
+    }
+  }
+}
+
+int main() {
+  test_to_compatible();
+  test_to_compatible_extension();
+}
Index: libcxx/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp
===================================================================
--- libcxx/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp
+++ libcxx/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp
@@ -35,4 +35,27 @@
                  simd<float, simd_abi::scalar>>::value,
     "");
 
-int main() {}
+void test_int_float_convert() {
+  assert(static_simd_cast<float>(native_simd<int>(16))[0] == 16.);
+  assert(static_simd_cast<int>(native_simd<float>(15.2f))[0] == 15);
+  assert(static_simd_cast<int>(native_simd<float>(15.9f))[0] == 15);
+}
+
+void test_narrowing_convert() {
+  assert(static_simd_cast<unsigned char>(native_simd<signed char>(-10))[0] ==
+         246);
+  assert(static_simd_cast<signed char>(native_simd<unsigned char>(246))[0] ==
+         -10);
+  assert(static_simd_cast<unsigned char>(native_simd<signed char>(127))[0] ==
+         127);
+  assert(static_simd_cast<signed char>(native_simd<unsigned char>(127))[0] ==
+         127);
+  assert(static_simd_cast<unsigned char>(native_simd<unsigned int>(257))[0] ==
+         1);
+  assert(static_simd_cast<signed char>(native_simd<signed int>(254))[0] == -2);
+}
+
+int main() {
+  test_int_float_convert();
+  test_narrowing_convert();
+}
Index: libcxx/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp
===================================================================
--- libcxx/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp
+++ libcxx/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp
@@ -19,6 +19,10 @@
 
 using namespace std::experimental::parallelism_v2;
 
+template <class T, class... Args>
+auto unsupported_cast(Args&&... args)
+    -> decltype(simd_cast<T>(std::forward<Args>(args)...), void()) = delete;
+
 static_assert(std::is_same<decltype(simd_cast<int32_t>(native_simd<int32_t>())),
                            native_simd<int32_t>>::value,
               "");
@@ -38,4 +42,25 @@
                            simd<int64_t, simd_abi::scalar>>::value,
               "");
 
+template <class T>
+void unsupported_cast(...) {}
+
+void compile_narrowing_convert() {
+  unsupported_cast<float>(native_simd<int>());
+  unsupported_cast<int>(native_simd<float>());
+  unsupported_cast<int8_t>(native_simd<int32_t>());
+  unsupported_cast<bool>(native_simd<int32_t>());
+  unsupported_cast<fixed_size_simd<int, 2>>(fixed_size_simd<int, 4>());
+}
+
+void compile_abi_convert() {
+  constexpr size_t ratio = native_simd<int>::size() / simd<int>::size();
+  std::array<simd<int>, ratio> arr;
+
+  auto res = concat(arr);
+  static_assert(!std::is_same<decltype(res), native_simd<int>>::value, "");
+
+  (void)simd_cast<native_simd<int>>(res);
+}
+
 int main() {}
Index: libcxx/include/experimental/simd
===================================================================
--- libcxx/include/experimental/simd
+++ libcxx/include/experimental/simd
@@ -910,18 +910,23 @@
 _LIBCPP_INLINE_VAR constexpr size_t max_fixed_size = 32;
 #endif
 
-template <class _Tp>
-using compatible = fixed_size<16 / sizeof(_Tp)>;
+template <class _Tp, size_t _Np>
+using __compatible = fixed_size<_Np>;
 
-template <class _Tp>
-using native =
+template <class _Tp, size_t _Np>
+using __native =
 #ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION
-    __simd_abi<_StorageKind::_VecExt,
-               _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>;
+    __simd_abi<_StorageKind::_VecExt, _Np>;
 #else
-    fixed_size<_Tp, _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>;
+    __simd_abi<_StorageKind::_Array, _Np>;
 #endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION
 
+template <class _Tp>
+using compatible = __compatible<_Tp, 16 / sizeof(_Tp)>;
+
+template <class _Tp>
+using native = __native<_Tp, _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>;
+
 _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD_ABI
 _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD
 
@@ -1051,25 +1056,35 @@
 template <class _Tp>
 struct __static_simd_cast_traits {
   template <class _Up, class _Abi>
-  static simd<_Tp, _Abi> __apply(const simd<_Up, _Abi>& __v);
+  static simd<_Tp, _Abi> __apply(const simd<_Up, _Abi>& __v) {
+    return __static_simd_cast_traits<simd<_Tp, _Abi>>::__apply(__v);
+  }
 };
 
 template <class _Tp, class _NewAbi>
 struct __static_simd_cast_traits<simd<_Tp, _NewAbi>> {
   template <class _Up, class _Abi>
   static typename std::enable_if<simd<_Up, _Abi>::size() ==
                                      simd<_Tp, _NewAbi>::size(),
                                  simd<_Tp, _NewAbi>>::type
-  __apply(const simd<_Up, _Abi>& __v);
+  __apply(const simd<_Up, _Abi>& __v) {
+    simd<_Tp, _NewAbi> __ret;
+    for (size_t __i = 0; __i < __v.size(); __i++) {
+      __ret[__i] = static_cast<_Tp>(__v[__i]);
+    }
+    return __ret;
+  }
 };
 
 template <class _Tp>
 struct __simd_cast_traits {
   template <class _Up, class _Abi>
   static typename std::enable_if<
       __is_non_narrowing_arithmetic_convertible<_Up, _Tp>(),
       simd<_Tp, _Abi>>::type
-  __apply(const simd<_Up, _Abi>& __v);
+  __apply(const simd<_Up, _Abi>& __v) {
+    return __static_simd_cast_traits<_Tp>::__apply(__v);
+  }
 };
 
 template <class _Tp, class _NewAbi>
@@ -1079,7 +1094,9 @@
       __is_non_narrowing_arithmetic_convertible<_Up, _Tp>() &&
           simd<_Up, _Abi>::size() == simd<_Tp, _NewAbi>::size(),
       simd<_Tp, _NewAbi>>::type
-  __apply(const simd<_Up, _Abi>& __v);
+  __apply(const simd<_Up, _Abi>& __v) {
+    return __static_simd_cast_traits<simd<_Tp, _NewAbi>>::__apply(__v);
+  }
 };
 
 template <class _Tp, class _Up, class _Abi>
@@ -1096,22 +1113,34 @@
 
 template <class _Tp, class _Abi>
 fixed_size_simd<_Tp, simd_size<_Tp, _Abi>::value>
-to_fixed_size(const simd<_Tp, _Abi>&) noexcept;
+to_fixed_size(const simd<_Tp, _Abi>& __v) noexcept {
+  return simd_cast<fixed_size_simd<_Tp, simd_size<_Tp, _Abi>::value>>(__v);
+}
 
 template <class _Tp, class _Abi>
 fixed_size_simd_mask<_Tp, simd_size<_Tp, _Abi>::value>
 to_fixed_size(const simd_mask<_Tp, _Abi>&) noexcept;
 
-template <class _Tp, size_t _Np>
-native_simd<_Tp> to_native(const fixed_size_simd<_Tp, _Np>&) noexcept;
+// NOTE: As an extension, allow transforming to a native type with a size
+// that's not native_simd<T>::size().
+template <class _Tp, int _Np>
+simd<_Tp, simd_abi::__native<_Tp, _Np>>
+to_native(const fixed_size_simd<_Tp, _Np>& __v) noexcept {
+  return simd_cast<simd<_Tp, simd_abi::__native<_Tp, _Np>>>(__v);
+}
 
-template <class _Tp, size_t _Np>
+template <class _Tp, int _Np>
 native_simd_mask<_Tp> to_native(const fixed_size_simd_mask<_Tp, _Np>&) noexcept;
 
-template <class _Tp, size_t _Np>
-simd<_Tp> to_compatible(const fixed_size_simd<_Tp, _Np>&) noexcept;
+// NOTE: As an extension, allow transforming to a compatible type with a size
+// that's not simd<T>::size().
+template <class _Tp, int _Np>
+simd<_Tp, simd_abi::__compatible<_Tp, _Np>>
+to_compatible(const fixed_size_simd<_Tp, _Np>& __v) noexcept {
+  return simd_cast<simd<_Tp, simd_abi::__compatible<_Tp, _Np>>>(__v);
+}
 
-template <class _Tp, size_t _Np>
+template <class _Tp, int _Np>
 simd_mask<_Tp> to_compatible(const fixed_size_simd_mask<_Tp, _Np>&) noexcept;
 
 template <class _TupleType, class _Tp, size_t... __indices>
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to