timshen updated this revision to Diff 127639.
timshen added a comment.
s/_LIBCPP_HAS_VECTOR_EXTENSION/_LIBCPP_HAS_NO_VECTOR_EXTENSION/
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
@@ -606,13 +606,13 @@
_VecExt,
};
-template <_StorageKind __kind, int _Np>
+template <_StorageKind __kind, size_t _Np>
struct __simd_abi {};
template <class _Tp, class _Abi>
class __simd_storage {};
-template <class _Tp, int __num_element>
+template <class _Tp, size_t __num_element>
class __simd_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> {
std::array<_Tp, __num_element> __storage_;
@@ -684,7 +684,7 @@
#undef _SPECIALIZE_VEC_EXT_32
#undef _SPECIALIZE_VEC_EXT
-template <class _Tp, int __num_element>
+template <class _Tp, size_t __num_element>
class __simd_storage<_Tp, __simd_abi<_StorageKind::_VecExt, __num_element>> {
using _StorageType =
typename __vec_ext_traits<_Tp, __ceil_pow_of_2(sizeof(_Tp) *
@@ -841,27 +841,32 @@
using scalar = __simd_abi<_StorageKind::_Scalar, 1>;
-template <int _Np>
+template <size_t _Np>
using fixed_size = __simd_abi<_StorageKind::_Array, _Np>;
#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) && \
!defined(_LIBCPP_HAS_NO_INLINE_VARIABLES)
template <class _Tp>
-inline constexpr int max_fixed_size = 32;
+inline 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
@@ -889,7 +894,7 @@
template <class _Tp>
struct is_abi_tag : std::integral_constant<bool, false> {};
-template <_StorageKind __kind, int _Np>
+template <_StorageKind __kind, size_t _Np>
struct is_abi_tag<__simd_abi<__kind, _Np>>
: std::integral_constant<bool, true> {};
@@ -940,7 +945,7 @@
using type = simd_abi::fixed_size<_Np>;
};
-template <class _Tp, size_t _Np, _StorageKind __kind, int... __old_size>
+template <class _Tp, size_t _Np, _StorageKind __kind, size_t... __old_size>
struct abi_for_size<_Tp, _Np, __simd_abi<__kind, __old_size>...> {
using type = __simd_abi<__kind, _Np>;
};
@@ -954,7 +959,7 @@
template <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
struct simd_size;
-template <class _Tp, _StorageKind __kind, int _Np>
+template <class _Tp, _StorageKind __kind, size_t _Np>
struct simd_size<_Tp, __simd_abi<__kind, _Np>>
: std::integral_constant<size_t, _Np> {
static_assert(
@@ -979,39 +984,49 @@
// class template simd [simd.class]
template <class _Tp>
using native_simd = simd<_Tp, simd_abi::native<_Tp>>;
-template <class _Tp, int _Np>
+template <class _Tp, size_t _Np>
using fixed_size_simd = simd<_Tp, simd_abi::fixed_size<_Np>>;
// class template simd_mask [simd.mask.class]
template <class _Tp>
using native_simd_mask = simd_mask<_Tp, simd_abi::native<_Tp>>;
-template <class _Tp, int _Np>
+template <class _Tp, size_t _Np>
using fixed_size_simd_mask = simd_mask<_Tp, simd_abi::fixed_size<_Np>>;
// casts [simd.casts]
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>
@@ -1021,7 +1036,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>
@@ -1038,20 +1055,32 @@
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;
+// NOTE: As an extension, allow transforming to a native type with a size
+// that's not native_simd<T>::size().
template <class _Tp, size_t _Np>
-native_simd<_Tp> to_native(const fixed_size_simd<_Tp, _Np>&) noexcept;
+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>
native_simd_mask<_Tp> to_native(const fixed_size_simd_mask<_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, size_t _Np>
-simd<_Tp> to_compatible(const fixed_size_simd<_Tp, _Np>&) noexcept;
+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>
simd_mask<_Tp> to_compatible(const fixed_size_simd_mask<_Tp, _Np>&) noexcept;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits