Index: libcxx/include/experimental/simd =================================================================== --- libcxx/include/experimental/simd +++ libcxx/include/experimental/simd @@ -1417,6 +1417,21 @@ #endif / sizeof(_Tp)>; +// NOTE: _Abis... is the extension proposed by P0820, allowing the APIs to +// propagate _StorageKind during transforming input type(s) to the output type. +template +struct deduce { + using type = simd_abi::fixed_size<_Np>; +}; + +template +struct deduce<_Tp, _Np, __simd_abi<__kind, __old_size>...> { + using type = __simd_abi<__kind, _Np>; +}; + +template +using deduce_t = typename deduce<_Tp, _Np, _Abis...>::type; + _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD_ABI _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD @@ -1484,24 +1499,6 @@ is_simd_flag_type<_Tp>::value; #endif -// NOTE: _Abis... is the extension proposed by P0820, allowing the APIs to -// propagate _StorageKind during transforming input type(s) to the output type. -template -struct abi_for_size { - using type = simd_abi::fixed_size<_Np>; -}; - -template -struct abi_for_size<_Tp, _Np, __simd_abi<__kind, __old_size>...> { - using type = __simd_abi<__kind, _Np>; -}; - -template -using abi_for_size_t = typename abi_for_size<_Tp, _Np, _Abis...>::type; - -template -using rebind_abi_t = abi_for_size_t<_Tp, _Np, _Abis...>; - template > struct simd_size; @@ -1662,10 +1659,10 @@ #endif template -simd<_Tp, rebind_abi_t<_Tp, sizeof...(__indices), _Abi1, _Abi2>> +simd<_Tp, simd_abi::deduce_t<_Tp, sizeof...(__indices), _Abi1, _Abi2>> __simd_shuffle(const simd<_Tp, _Abi1>& __v, const simd<_Tp, _Abi2>& __u, std::index_sequence<__indices...> = {}) { - simd<_Tp, rebind_abi_t<_Tp, sizeof...(__indices), _Abi1, _Abi2>> __ret; + simd<_Tp, simd_abi::deduce_t<_Tp, sizeof...(__indices), _Abi1, _Abi2>> __ret; size_t __i = 0; for (size_t __index : {__indices...}) { __ret[__i++] = @@ -1675,9 +1672,9 @@ } template -tuple< - simd<_Tp, rebind_abi_t<_Tp, __first_size, _Abi>>, - simd<_Tp, rebind_abi_t<_Tp, simd<_Tp, _Abi>::size() - __first_size, _Abi>>> +tuple>, + simd<_Tp, simd_abi::deduce_t<_Tp, simd<_Tp, _Abi>::size() - __first_size, + _Abi>>> __split_to_two(const simd<_Tp, _Abi>& __v, std::index_sequence<__indices...>) { static_assert(__first_size + sizeof...(__indices) == simd<_Tp, _Abi>::size(), ""); @@ -1694,8 +1691,8 @@ } template -tuple>, - simd<_Tp, rebind_abi_t<_Tp, __rest, _Abi>>...> +tuple>, + simd<_Tp, simd_abi::deduce_t<_Tp, __rest, _Abi>>...> __split_impl(const simd<_Tp, _Abi>& __v, std::integral_constant, std::integral_constant...) { @@ -1710,7 +1707,7 @@ template typename std::enable_if< __variadic_sum(__sizes...) == simd<_Tp, _Abi>::size(), - tuple>...>>::type + tuple>...>>::type split(const simd<_Tp, _Abi>& __v) { return __split_impl(__v, std::integral_constant()...); } @@ -1729,12 +1726,12 @@ template typename std::enable_if< simd_size<_Tp, _Abi>::value % __array_size == 0, - array::value / __array_size, _Abi>>, __array_size>>::type split_by(const simd<_Tp, _Abi>& __v) { - array::value / __array_size, - _Abi>>, + array::value / __array_size, _Abi>>, __array_size> __ret; __split_by_impl(__v, &__ret, std::make_index_sequence<__array_size>()); @@ -1760,10 +1757,11 @@ } template -simd<_Tp, rebind_abi_t<_Tp, - __variadic_sum(simd_size<_Tp, _Abi>::value, - simd_size<_Tp, _Abis>::value...), - _Abi, _Abis...>> +simd<_Tp, + simd_abi::deduce_t<_Tp, + __variadic_sum(simd_size<_Tp, _Abi>::value, + simd_size<_Tp, _Abis>::value...), + _Abi, _Abis...>> __concat_variadic(const simd<_Tp, _Abi>& __first, const simd<_Tp, _Abis>&... __rest) { return __simd_shuffle( @@ -1773,22 +1771,22 @@ } template -simd<_Tp, - rebind_abi_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...), - _Abis...>> +simd<_Tp, simd_abi::deduce_t< + _Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...), + _Abis...>> concat(const simd<_Tp, _Abis>&... __vs) { return __concat_variadic(__vs...); } template -simd<_Tp, rebind_abi_t<_Tp, _Np * simd<_Tp, _Abi>::size(), _Abi>> +simd<_Tp, simd_abi::deduce_t<_Tp, _Np * simd<_Tp, _Abi>::size(), _Abi>> __concat_array(const std::array, _Np>& __arr, std::index_sequence<__indices...>) { return concat(__arr[__indices]...); } template -simd<_Tp, rebind_abi_t<_Tp, _Np * simd<_Tp, _Abi>::size(), _Abi>> +simd<_Tp, simd_abi::deduce_t<_Tp, _Np * simd<_Tp, _Abi>::size(), _Abi>> concat(const std::array, _Np>& __arr) { return __concat_array(__arr, std::make_index_sequence<_Np>()); } @@ -1835,10 +1833,10 @@ template static typename std::enable_if< __variadic_sum(__sizes...) == simd<_Tp, _Abi>::size(), - tuple>...>>::type + tuple>...>>::type __split(const simd_mask<_Tp, _Abi>& __m) { return __split_impl< - tuple>...>>( + tuple>...>>( split<__sizes...>(__m.__s_), std::make_index_sequence()); } @@ -1846,15 +1844,15 @@ template static typename std::enable_if< simd_size<_Tp, _Abi>::value % __array_size == 0, - array::value / __array_size, _Abi>>, __array_size>>::type __split_by(const simd_mask<_Tp, _Abi>& __m) { auto __arr = split_by<__array_size>(__m.__s_); - array::value / __array_size, - _Abi>>, + array::value / __array_size, _Abi>>, __array_size> __ret; for (size_t __i = 0; __i < __ret.size(); __i++) { @@ -1877,16 +1875,16 @@ template static simd_mask< - _Tp, - rebind_abi_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...), - _Abis...>> + _Tp, simd_abi::deduce_t< + _Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...), + _Abis...>> __concat(const simd_mask<_Tp, _Abis>&... __ms) { return concat(__ms.__s_...); } template - static simd_mask<_Tp, - rebind_abi_t<_Tp, _Np * simd_size<_Tp, _Abi>::value, _Abi>> + static simd_mask< + _Tp, simd_abi::deduce_t<_Tp, _Np * simd_size<_Tp, _Abi>::value, _Abi>> __concat(const std::array, _Np>& __ms) { std::array __arr; for (size_t __i = 0; __i < __ms.size(); __i++) { @@ -1942,7 +1940,7 @@ template typename std::enable_if< __variadic_sum(__sizes...) == simd<_Tp, _Abi>::size(), - tuple>...>>::type + tuple>...>>::type split(const simd_mask<_Tp, _Abi>& __m) { return __simd_mask_friend::__split<__sizes...>(__m); } @@ -1950,9 +1948,9 @@ template static typename std::enable_if< simd_size<_Tp, _Abi>::value % __array_size == 0, - array::value / __array_size, - _Abi>>, + array::value / __array_size, _Abi>>, __array_size>>::type split_by(const simd_mask<_Tp, _Abi>& __m) { return __simd_mask_friend::__split_by<__array_size>(__m); @@ -1971,7 +1969,7 @@ } template -simd_mask<_Tp, rebind_abi_t< +simd_mask<_Tp, simd_abi::deduce_t< _Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...), _Abis...>> concat(const simd_mask<_Tp, _Abis>&... __ms) { @@ -1979,7 +1977,7 @@ } template -simd_mask<_Tp, rebind_abi_t<_Tp, _Np * simd_size<_Tp, _Abi>::value, _Abi>> +simd_mask<_Tp, simd_abi::deduce_t<_Tp, _Np * simd_size<_Tp, _Abi>::value, _Abi>> concat(const std::array, _Np>& __ms) { return __simd_mask_friend::__concat(__ms); } @@ -2085,7 +2083,8 @@ } template -std::array::size() / 2, _Abi>>, 2> +std::array< + simd<_Tp, simd_abi::deduce_t<_Tp, simd<_Tp, _Abi>::size() / 2, _Abi>>, 2> __deinterleave_impl(const simd<_Tp, _Abi>& __v, std::index_sequence<__indices...>) { return {{__simd_shuffle<(2 * __indices)...>(__v, __v), @@ -2093,7 +2092,8 @@ } template -std::array::size() / 2, _Abi>>, 2> +std::array< + simd<_Tp, simd_abi::deduce_t<_Tp, simd<_Tp, _Abi>::size() / 2, _Abi>>, 2> __deinterleave(const simd<_Tp, _Abi>& __v) { static_assert(simd<_Tp, _Abi>::size() % 2 == 0, ""); return __deinterleave_impl( @@ -2873,20 +2873,17 @@ // [simd.whereexpr] template class const_where_expression { - static_assert( - std::is_arithmetic::type>::value || - is_simd::type>::value || - is_simd_mask::type>::value, - ""); + static_assert(std::is_arithmetic<_ValueType>::value || + is_simd<_ValueType>::value || + is_simd_mask<_ValueType>::value, + ""); - using _Tp = typename __simd_value_type_traits< - typename remove_const<_ValueType>::type>::type; + using _Tp = typename __simd_value_type_traits<_ValueType>::type; - typename std::conditional::value, bool, - const _MaskType>::type __m_; - _ValueType& __v_; + const _MaskType __m_; + const _ValueType& __v_; - const_where_expression(const _MaskType& __m, _ValueType& __v) + const_where_expression(const _MaskType& __m, const _ValueType& __v) : __m_(__m), __v_(__v) {} const_where_expression(const const_where_expression&) = default; @@ -2895,18 +2892,18 @@ friend class where_expression; template - friend const_where_expression, const simd<_Up, _Ap>> + friend const_where_expression, simd<_Up, _Ap>> where(const typename simd<_Up, _Ap>::mask_type& __m, const simd<_Up, _Ap>& __v) noexcept; template - friend const_where_expression, const simd_mask<_Up, _Ap>> + friend const_where_expression, simd_mask<_Up, _Ap>> where(const typename __nodeduce>::type& __m, const simd_mask<_Up, _Ap>& __v) noexcept; template friend typename std::enable_if::value, - const_where_expression>::type + const_where_expression>::type where(_Mp __m, const _Up& __v) noexcept; template @@ -2925,17 +2922,15 @@ public: const_where_expression& operator=(const const_where_expression&) = delete; - typename std::remove_const<_ValueType>::type operator-() const&& { - static_assert(!is_simd_mask::type>::value, - "Library extension: operator-() doesn't really make sense " - "when operating on simd_mask<>."); + _ValueType operator-() const&& { return __simd_mask_friend::__simd_select(__v_, _ValueType(0), __m_) - __simd_mask_friend::__simd_select(_ValueType(0), __v_, __m_); } template - typename std::enable_if::value || - !std::is_same<_Tp, bool>::value>::type + typename std::enable_if<(std::is_same<_Tp, _Up>::value || + !std::is_same<_Tp, bool>::value) && + is_simd_flag_type<_Flags>::value>::type copy_to(_Up* __buffer, _Flags) const&& { __mask_copy_to<__memory_alignment_impl<_ValueType, _Up, _Flags>::value>( __v_, __m_, __buffer); @@ -2944,8 +2939,7 @@ template class where_expression : public const_where_expression<_MaskType, _ValueType> { - using _Tp = typename __simd_value_type_traits< - typename remove_const<_ValueType>::type>::type; + using _Tp = typename __simd_value_type_traits<_ValueType>::type; where_expression(const _MaskType& __m, _ValueType& __v) : const_where_expression<_MaskType, _ValueType>(__m, __v) {} @@ -2967,74 +2961,76 @@ where_expression>::type where(_Mp __m, _Up& __v) noexcept; + _ValueType& __ref() { return const_cast<_ValueType&>(this->__v_); } + public: where_expression& operator=(const where_expression&) = delete; template auto operator=(_Up&& __u) - -> decltype(this->__v_ = std::forward<_Up>(__u), void()) { - this->__v_ = __simd_mask_friend::__simd_select( - this->__v_, _ValueType(std::forward<_Up>(__u)), this->__m_); + -> decltype(this->__ref() = std::forward<_Up>(__u), void()) { + this->__ref() = __simd_mask_friend::__simd_select( + this->__ref(), _ValueType(std::forward<_Up>(__u)), this->__m_); } template auto operator+=(_Up&& __u) - -> decltype(this->__v_ + std::forward<_Up>(__u), void()) { - *this = this->__v_ + std::forward<_Up>(__u); + -> decltype(this->__ref() + std::forward<_Up>(__u), void()) { + *this = this->__ref() + std::forward<_Up>(__u); } template auto operator-=(_Up&& __u) - -> decltype(this->__v_ - std::forward<_Up>(__u), void()) { - *this = this->__v_ - std::forward<_Up>(__u); + -> decltype(this->__ref() - std::forward<_Up>(__u), void()) { + *this = this->__ref() - std::forward<_Up>(__u); } template auto operator*=(_Up&& __u) - -> decltype(this->__v_ * std::forward<_Up>(__u), void()) { - *this = this->__v_ * std::forward<_Up>(__u); + -> decltype(this->__ref() * std::forward<_Up>(__u), void()) { + *this = this->__ref() * std::forward<_Up>(__u); } template auto operator/=(_Up&& __u) - -> decltype(this->__v_ / std::forward<_Up>(__u), void()) { - *this = this->__v_ / std::forward<_Up>(__u); + -> decltype(this->__ref() / std::forward<_Up>(__u), void()) { + *this = this->__ref() / std::forward<_Up>(__u); } template auto operator%=(_Up&& __u) - -> decltype(this->__v_ % std::forward<_Up>(__u), void()) { - *this = this->__v_ % std::forward<_Up>(__u); + -> decltype(this->__ref() % std::forward<_Up>(__u), void()) { + *this = this->__ref() % std::forward<_Up>(__u); } template auto operator&=(_Up&& __u) - -> decltype(this->__v_ & std::forward<_Up>(__u), void()) { - *this = this->__v_ & std::forward<_Up>(__u); + -> decltype(this->__ref() & std::forward<_Up>(__u), void()) { + *this = this->__ref() & std::forward<_Up>(__u); } template auto operator|=(_Up&& __u) - -> decltype(this->__v_ | std::forward<_Up>(__u), void()) { - *this = this->__v_ | std::forward<_Up>(__u); + -> decltype(this->__ref() | std::forward<_Up>(__u), void()) { + *this = this->__ref() | std::forward<_Up>(__u); } template auto operator^=(_Up&& __u) - -> decltype(this->__v_ ^ std::forward<_Up>(__u), void()) { - *this = this->__v_ ^ std::forward<_Up>(__u); + -> decltype(this->__ref() ^ std::forward<_Up>(__u), void()) { + *this = this->__ref() ^ std::forward<_Up>(__u); } template auto operator<<=(_Up&& __u) - -> decltype(this->__v_ << std::forward<_Up>(__u), void()) { - *this = this->__v_ << std::forward<_Up>(__u); + -> decltype(this->__ref() << std::forward<_Up>(__u), void()) { + *this = this->__ref() << std::forward<_Up>(__u); } template auto operator>>=(_Up&& __u) - -> decltype(this->__v_ >> std::forward<_Up>(__u), void()) { - *this = this->__v_ >> std::forward<_Up>(__u); + -> decltype(this->__ref() >> std::forward<_Up>(__u), void()) { + *this = this->__ref() >> std::forward<_Up>(__u); } void operator++() { *this += _ValueType(1); } @@ -3050,7 +3046,7 @@ !std::is_same<_Tp, bool>::value>::type copy_from(const _Up* __buffer, _Flags) { __mask_copy_from<__memory_alignment_impl<_ValueType, _Up, _Flags>::value>( - this->__v_, this->__m_, __buffer); + this->__ref(), this->__m_, __buffer); } }; @@ -3062,11 +3058,11 @@ } template -const_where_expression, const simd<_Tp, _Abi>> +const_where_expression, simd<_Tp, _Abi>> where(const typename simd<_Tp, _Abi>::mask_type& __m, const simd<_Tp, _Abi>& __v) noexcept { - return const_where_expression, const simd<_Tp, _Abi>>( - __m, __v); + return const_where_expression, simd<_Tp, _Abi>>(__m, + __v); } template @@ -3077,11 +3073,11 @@ } template -const_where_expression, const simd_mask<_Tp, _Abi>> +const_where_expression, simd_mask<_Tp, _Abi>> where(const typename __nodeduce>::type& __m, const simd_mask<_Tp, _Abi>& __v) noexcept { - return const_where_expression, - const simd_mask<_Tp, _Abi>>(__m, __v); + return const_where_expression, simd_mask<_Tp, _Abi>>( + __m, __v); } template @@ -3093,9 +3089,9 @@ template typename std::enable_if::value, - const_where_expression>::type + const_where_expression>::type where(_MaskType __m, const _Tp& __v) noexcept { - return const_where_expression(__m, __v); + return const_where_expression(__m, __v); } template Index: libcxx/test/std/experimental/simd/simd.horizontal/concat.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.horizontal/concat.pass.cpp +++ libcxx/test/std/experimental/simd/simd.horizontal/concat.pass.cpp @@ -16,7 +16,7 @@ // concat(const simd&...); // // template -// simd, Abi>> +// simd, Abi>> // concat(const std::array, N>& __v); // // template @@ -24,7 +24,7 @@ // concat(const simd_mask&...); // // template -// simd_mask, Abi>> +// simd_mask, Abi>> // concat(const std::array, N>&); #include @@ -102,17 +102,18 @@ } void compile_split_propagate_abi() { - static_assert(std::is_same(), simd()))::abi_type, - rebind_abi_t::size() * 2, - simd_abi::compatible>>::value, - ""); + static_assert( + std::is_same(), simd()))::abi_type, + simd_abi::deduce_t::size() * 2, + simd_abi::compatible>>::value, + ""); static_assert( std::is_same(), native_simd()))::abi_type, - rebind_abi_t::size() * 2, - simd_abi::native>>::value, + simd_abi::deduce_t::size() * 2, + simd_abi::native>>::value, ""); } Index: libcxx/test/std/experimental/simd/simd.horizontal/hmax.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.horizontal/hmax.pass.cpp +++ libcxx/test/std/experimental/simd/simd.horizontal/hmax.pass.cpp @@ -94,8 +94,9 @@ int main() { test_hmax_simd_power_of_2>(); test_hmax_simd_power_of_2< - simd>>>(); + simd>>>(); test_hmax_simd>(); - test_hmax_simd>>>(); + test_hmax_simd< + simd>>>(); test_hmax_mask(); } Index: libcxx/test/std/experimental/simd/simd.horizontal/hmin.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.horizontal/hmin.pass.cpp +++ libcxx/test/std/experimental/simd/simd.horizontal/hmin.pass.cpp @@ -87,10 +87,12 @@ int main() { test_hmin_simd_power_of_2>(); test_hmin_simd_power_of_2< - simd>>>(); + simd>>>(); test_hmin_simd>(); - test_hmin_simd>>>(); + test_hmin_simd< + simd>>>(); test_hmin_simd>(); - test_hmin_simd>>>(); + test_hmin_simd< + simd>>>(); test_hmin_mask(); } Index: libcxx/test/std/experimental/simd/simd.horizontal/split.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.horizontal/split.pass.cpp +++ libcxx/test/std/experimental/simd/simd.horizontal/split.pass.cpp @@ -26,11 +26,11 @@ // const simd_mask&); // // template -// array / n, A>>, n> split_by( +// array / n, A>>, n> split_by( // const simd& x); // // template -// array / n, A>>, n> split_by( +// array / n, A>>, n> split_by( // const simd_mask& x); #include @@ -138,11 +138,11 @@ void compile_split_simd_propagate_abi() { using compatible_simd_half = - simd::size() / 2, simd_abi::compatible>>; + simd::size() / 2, + simd_abi::compatible>>; using native_simd_half = - simd::size() / 2, - simd_abi::native>>; + simd::size() / 2, + simd_abi::native>>; static_assert( std::is_same< @@ -169,11 +169,11 @@ void compile_split_simd_mask_propagate_abi() { using compatible_simd_mask_half = - simd_mask::size() / 2, - simd_abi::compatible>>; + simd_mask::size() / 2, + simd_abi::compatible>>; using native_simd_mask_half = - simd_mask::size() / 2, - simd_abi::native>>; + simd_mask::size() / 2, + simd_abi::native>>; static_assert(std::is_same::size() / 2, simd_mask::size() / 2>( Index: libcxx/test/std/experimental/simd/simd.elementwise/operators.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.elementwise/operators.pass.cpp +++ libcxx/test/std/experimental/simd/simd.elementwise/operators.pass.cpp @@ -266,6 +266,6 @@ test_mutating_opreators>(); test_mutating_opreators>(); test_relational_operators< - simd>>>(); + simd>>>(); test_relational_operators>(); } Index: libcxx/test/std/experimental/simd/simd.traits/simd_abi_deduce.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.traits/simd_abi_deduce.pass.cpp +++ libcxx/test/std/experimental/simd/simd.traits/simd_abi_deduce.pass.cpp @@ -20,11 +20,12 @@ using namespace std::experimental::parallelism_v2; -static_assert(std::is_same::type, +static_assert(std::is_same::type, simd_abi::fixed_size<4>>::value, ""); static_assert( - std::is_same, simd_abi::fixed_size<4>>::value, ""); + std::is_same, simd_abi::fixed_size<4>>::value, + ""); int main() {} Index: libcxx/test/std/experimental/simd/simd.whereexpr/where.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.whereexpr/where.pass.cpp +++ libcxx/test/std/experimental/simd/simd.whereexpr/where.pass.cpp @@ -43,25 +43,23 @@ void compile_const_where() { { const native_simd a{}; - static_assert( - std::is_same, - const native_simd>>::value, - ""); + static_assert(std::is_same, + native_simd>>::value, + ""); } { const native_simd_mask a{}; static_assert( - std::is_same< - decltype(where(a, a)), - const_where_expression, - const native_simd_mask>>::value, + std::is_same, + native_simd_mask>>::value, ""); } { const bool b = true; static_assert(std::is_same>::value, + const_where_expression>::value, ""); } }