timshen updated this revision to Diff 139042. timshen added a comment. Herald added a subscriber: christof.
Rebase. https://reviews.llvm.org/D41756 Files: libcxx/include/experimental/simd 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 libcxx/test/std/experimental/simd/simd.elementwise/clamp.pass.cpp libcxx/test/std/experimental/simd/simd.elementwise/max.pass.cpp libcxx/test/std/experimental/simd/simd.elementwise/min.pass.cpp libcxx/test/std/experimental/simd/simd.elementwise/minmax.pass.cpp libcxx/test/std/experimental/simd/simd.elementwise/operators.pass.cpp libcxx/test/std/experimental/simd/simd.horizontal/concat.pass.cpp libcxx/test/std/experimental/simd/simd.horizontal/mask.pass.cpp libcxx/test/std/experimental/simd/simd.horizontal/split.pass.cpp libcxx/test/std/experimental/simd/simd.mask.elementwise/operators.pass.cpp
Index: libcxx/test/std/experimental/simd/simd.mask.elementwise/operators.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.mask.elementwise/operators.pass.cpp +++ libcxx/test/std/experimental/simd/simd.mask.elementwise/operators.pass.cpp @@ -50,6 +50,10 @@ (simd_mask<int>(false) ^ simd_mask<int>(true)))); assert(all_of(simd_mask<int>(false) == (simd_mask<int>(true) ^ simd_mask<int>(true)))); + assert(all_of(!simd<int>(0))); + assert(all_of(!simd<int>(0) == simd_mask<int>(true))); + assert(none_of(!simd<int>(42))); + assert(all_of(!simd<int>(42) == simd_mask<int>(false))); } void test_mutating_opreators() { 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 @@ -39,7 +39,7 @@ using namespace std::experimental::parallelism_v2; -void test_split() { +void test_split_simd() { auto t = split<1, 2, 3>(fixed_size_simd<int, 6>([](int i) { return i; })); static_assert(std::tuple_size<decltype(t)>::value == 3, ""); @@ -56,7 +56,24 @@ assert(std::get<2>(t)[2] == 5); } -void test_split_array() { +void test_split_mask() { + auto t = split<1, 2, 3>(fixed_size_simd_mask<int, 6>(true)); + static_assert(std::tuple_size<decltype(t)>::value == 3, ""); + + assert(std::get<0>(t).size() == 1); + assert(std::get<0>(t)[0]); + + assert(std::get<1>(t).size() == 2); + assert(std::get<1>(t)[0]); + assert(std::get<1>(t)[1]); + + assert(std::get<2>(t).size() == 3); + assert(std::get<2>(t)[0]); + assert(std::get<2>(t)[1]); + assert(std::get<2>(t)[2]); +} + +void test_split_array_simd() { { auto arr = split_by<2>(fixed_size_simd<int, 6>([](int i) { return i; })); static_assert(arr.size() == 2, ""); @@ -88,7 +105,38 @@ } } -void compile_split_propagate_abi() { +void test_split_array_mask() { + { + auto arr = split_by<2>(fixed_size_simd_mask<int, 6>(true)); + static_assert(arr.size() == 2, ""); + + assert(arr[0].size() == 3); + assert(arr[0][0]); + assert(arr[0][1]); + assert(arr[0][2]); + + assert(arr[1].size() == 3); + assert(arr[1][0]); + assert(arr[1][1]); + assert(arr[1][2]); + } + { + auto arr = split<fixed_size_simd<int, 3>>(fixed_size_simd<int, 6>(true)); + static_assert(arr.size() == 2, ""); + + assert(arr[0].size() == 3); + assert(arr[0][0]); + assert(arr[0][1]); + assert(arr[0][2]); + + assert(arr[1].size() == 3); + assert(arr[1][0]); + assert(arr[1][1]); + assert(arr[1][2]); + } +} + +void compile_split_simd_propagate_abi() { using compatible_simd_half = simd<int, rebind_abi_t<int, simd<int>::size() / 2, simd_abi::compatible<int>>>; @@ -119,7 +167,41 @@ ""); } +void compile_split_simd_mask_propagate_abi() { + using compatible_simd_mask_half = + simd_mask<int, rebind_abi_t<int, simd_mask<int>::size() / 2, + simd_abi::compatible<int>>>; + using native_simd_mask_half = + simd_mask<int, rebind_abi_t<int, native_simd_mask<int>::size() / 2, + simd_abi::native<int>>>; + + static_assert(std::is_same<decltype(split<simd_mask<int>::size() / 2, + simd_mask<int>::size() / 2>( + simd_mask<int>())), + std::tuple<compatible_simd_mask_half, + compatible_simd_mask_half>>::value, + ""); + + static_assert( + std::is_same< + decltype(split<native_simd_mask<int>::size() / 2, + native_simd_mask<int>::size() / 2>( + native_simd_mask<int>())), + std::tuple<native_simd_mask_half, native_simd_mask_half>>::value, + ""); + + static_assert(std::is_same<decltype(split_by<2>(simd_mask<int>())), + std::array<compatible_simd_mask_half, 2>>::value, + ""); + + static_assert(std::is_same<decltype(split_by<2>(native_simd_mask<int>())), + std::array<native_simd_mask_half, 2>>::value, + ""); +} + int main() { - test_split(); - test_split_array(); + test_split_simd(); + test_split_mask(); + test_split_array_simd(); + test_split_array_mask(); } Index: libcxx/test/std/experimental/simd/simd.horizontal/mask.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/experimental/simd/simd.horizontal/mask.pass.cpp @@ -0,0 +1,189 @@ +//===----------------------------------------------------------------------===// +// +// 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> +// +// // reductions [simd.mask.reductions] +// template <class T, class Abi> bool all_of(const simd_mask<T, Abi>&) noexcept; +// template <class T, class Abi> bool any_of(const simd_mask<T, Abi>&) noexcept; +// template <class T, class Abi> bool none_of(const simd_mask<T, Abi>&) noexcept; +// template <class T, class Abi> bool some_of(const simd_mask<T, Abi>&) noexcept; +// template <class T, class Abi> int popcount(const simd_mask<T, Abi>&) noexcept; +// template <class T, class Abi> int find_first_set(const simd_mask<T, Abi>&); +// template <class T, class Abi> int find_last_set(const simd_mask<T, Abi>&); +// +// bool all_of(see below ) noexcept; +// bool any_of(see below ) noexcept; +// bool none_of(see below ) noexcept; +// bool some_of(see below ) noexcept; +// int popcount(see below ) noexcept; +// int find_first_set(see below ) noexcept; +// int find_last_set(see below ) noexcept; + +#include <cassert> +#include <cstdint> +#include <experimental/simd> + +using namespace std::experimental::parallelism_v2; + +void test_all_of() { + { + bool expected[] = {false, false}; + assert( + !all_of(fixed_size_simd_mask<int, 2>(expected, element_aligned_tag()))); + } + { + bool expected[] = {true, false}; + assert( + !all_of(fixed_size_simd_mask<int, 2>(expected, element_aligned_tag()))); + } + { + bool expected[] = {true, true}; + assert( + all_of(fixed_size_simd_mask<int, 2>(expected, element_aligned_tag()))); + } +} + +void test_any_of() { + { + bool expected[] = {false, false}; + assert( + !any_of(fixed_size_simd_mask<int, 2>(expected, element_aligned_tag()))); + } + { + bool expected[] = {true, false}; + assert( + any_of(fixed_size_simd_mask<int, 2>(expected, element_aligned_tag()))); + } + { + bool expected[] = {true, true}; + assert( + any_of(fixed_size_simd_mask<int, 2>(expected, element_aligned_tag()))); + } +} + +void test_none_of() { + { + bool expected[] = {false, false}; + assert( + none_of(fixed_size_simd_mask<int, 2>(expected, element_aligned_tag()))); + } + { + bool expected[] = {true, false}; + assert(!none_of( + fixed_size_simd_mask<int, 2>(expected, element_aligned_tag()))); + } + { + bool expected[] = {true, true}; + assert(!none_of( + fixed_size_simd_mask<int, 2>(expected, element_aligned_tag()))); + } +} + +void test_some_of() { + { + bool expected[] = {false, false}; + assert(!some_of( + fixed_size_simd_mask<int, 2>(expected, element_aligned_tag()))); + } + { + bool expected[] = {true, false}; + assert( + some_of(fixed_size_simd_mask<int, 2>(expected, element_aligned_tag()))); + } + { + bool expected[] = {true, true}; + assert(!some_of( + fixed_size_simd_mask<int, 2>(expected, element_aligned_tag()))); + } +} + +void test_popcount() { + { + bool expected[] = {false, false}; + assert(popcount(fixed_size_simd_mask<int, 2>(expected, + element_aligned_tag())) == 0); + } + { + bool expected[] = {true, false}; + assert(popcount(fixed_size_simd_mask<int, 2>(expected, + element_aligned_tag())) == 1); + } + { + bool expected[] = {true, true}; + assert(popcount(fixed_size_simd_mask<int, 2>(expected, + element_aligned_tag())) == 2); + } +} + +void test_find_first_set() { + { + bool expected[] = {false, true, true}; + assert(find_first_set(fixed_size_simd_mask<int, 3>( + expected, element_aligned_tag())) == 1); + } + { + bool expected[] = {true, false, true}; + assert(find_first_set(fixed_size_simd_mask<int, 3>( + expected, element_aligned_tag())) == 0); + } + { + bool expected[] = {true, true, false}; + assert(find_first_set(fixed_size_simd_mask<int, 3>( + expected, element_aligned_tag())) == 0); + } +} + +void test_find_last_set() { + { + bool expected[] = {false, true, true}; + assert(find_last_set(fixed_size_simd_mask<int, 3>( + expected, element_aligned_tag())) == 2); + } + { + bool expected[] = {true, false, true}; + assert(find_last_set(fixed_size_simd_mask<int, 3>( + expected, element_aligned_tag())) == 2); + } + { + bool expected[] = {true, true, false}; + assert(find_last_set(fixed_size_simd_mask<int, 3>( + expected, element_aligned_tag())) == 1); + } +} + +void test_bool_functions() { + assert(all_of(true)); + assert(!all_of(false)); + assert(any_of(true)); + assert(!any_of(false)); + assert(!none_of(true)); + assert(none_of(false)); + assert(!some_of(true)); + assert(!some_of(false)); + assert(popcount(true) == 1); + assert(popcount(false) == 0); + assert(find_first_set(true) == 0); + assert(find_first_set(false) == 0); + assert(find_last_set(true) == 0); + assert(find_last_set(false) == 0); +} + +int main() { + test_all_of(); + test_any_of(); + test_none_of(); + test_some_of(); + test_popcount(); + test_find_first_set(); + test_find_last_set(); + test_bool_functions(); +} 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 @@ -33,7 +33,7 @@ using namespace std::experimental::parallelism_v2; -void test_concat() { +void test_concat_simd() { auto v = concat(fixed_size_simd<int, 1>([](int i) { return i; }), fixed_size_simd<int, 2>([](int i) { return i + 1; }), fixed_size_simd<int, 3>([](int i) { return i + 3; })); @@ -46,7 +46,20 @@ assert(v[5] == 5); } -void test_concat_array() { +void test_concat_mask() { + auto v = concat(fixed_size_simd_mask<int, 1>(true), + fixed_size_simd_mask<int, 2>(true), + fixed_size_simd_mask<int, 3>(true)); + static_assert(v.size() == 6, ""); + assert(v[0]); + assert(v[1]); + assert(v[2]); + assert(v[3]); + assert(v[4]); + assert(v[5]); +} + +void test_concat_array_simd() { std::array<fixed_size_simd<int, 2>, 2> arr; arr[0] = fixed_size_simd<int, 2>([](int) { return 0; }); arr[1] = fixed_size_simd<int, 2>([](int) { return 1; }); @@ -75,6 +88,19 @@ } } +void test_concat_array_mask() { + std::array<fixed_size_simd_mask<int, 2>, 2> arr; + arr[0] = fixed_size_simd_mask<int, 2>(true); + arr[1] = fixed_size_simd_mask<int, 2>(true); + + auto v = concat(arr); + static_assert(v.size() == 4, ""); + assert(v[0]); + assert(v[1]); + assert(v[2]); + assert(v[3]); +} + void compile_split_propagate_abi() { static_assert(std::is_same<typename decltype( concat(simd<int>(), simd<int>()))::abi_type, @@ -91,7 +117,9 @@ } int main() { - test_concat(); - test_concat_array(); test_concat_native(); + test_concat_simd(); + test_concat_mask(); + test_concat_array_simd(); + test_concat_array_mask(); } 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 @@ -64,141 +64,131 @@ using namespace std::experimental::parallelism_v2; -template <typename T, typename Abi> -bool equal(simd<T, Abi> a, simd<T, Abi> b) { - for (size_t i = 0; i < a.size(); i++) { - if (a[i] != b[i]) { - return false; - } - } - return true; -} - void test_pure_operators() { { native_simd<int> a(42), b(4); - assert(equal(~a, native_simd<int>(~42))); - assert(equal(+a, a)); - assert(equal(-a, native_simd<int>(-42))); - assert(equal(a + b, native_simd<int>(42 + 4))); - assert(equal(a - b, native_simd<int>(42 - 4))); - assert(equal(a * b, native_simd<int>(42 * 4))); - assert(equal(a / b, native_simd<int>(42 / 4))); - assert(equal(a % b, native_simd<int>(42 % 4))); - assert(equal(a & b, native_simd<int>(42 & 4))); - assert(equal(a | b, native_simd<int>(42 | 4))); - assert(equal(a ^ b, native_simd<int>(42 ^ 4))); - assert(equal(a << b, native_simd<int>(42 << 4))); - assert(equal(a >> b, native_simd<int>(42 >> 4))); - assert(equal(a << 4, native_simd<int>(42 << 4))); - assert(equal(a >> 4, native_simd<int>(42 >> 4))); + assert(all_of(~a == native_simd<int>(~42))); + assert(all_of(+a == a)); + assert(all_of(-a == native_simd<int>(-42))); + assert(all_of(a + b == native_simd<int>(42 + 4))); + assert(all_of(a - b == native_simd<int>(42 - 4))); + assert(all_of(a * b == native_simd<int>(42 * 4))); + assert(all_of(a / b == native_simd<int>(42 / 4))); + assert(all_of(a % b == native_simd<int>(42 % 4))); + assert(all_of((a & b) == native_simd<int>(42 & 4))); + assert(all_of((a | b) == native_simd<int>(42 | 4))); + assert(all_of((a ^ b) == native_simd<int>(42 ^ 4))); + assert(all_of((a << b) == native_simd<int>(42 << 4))); + assert(all_of((a >> b) == native_simd<int>(42 >> 4))); + assert(all_of((a << 4) == native_simd<int>(42 << 4))); + assert(all_of((a >> 4) == native_simd<int>(42 >> 4))); } { native_simd<int> a([](int i) { return 2 * i + 1; }), b([](int i) { return i + 1; }); - assert(equal(~a, native_simd<int>([](int i) { return ~(2 * i + 1); }))); - assert(equal(+a, a)); - assert(equal(-a, native_simd<int>([](int i) { return -(2 * i + 1); }))); - assert(equal(a + b, native_simd<int>([](int i) { return 3 * i + 2; }))); - assert(equal(a - b, native_simd<int>([](int i) { return i; }))); - assert(equal( - a * b, native_simd<int>([](int i) { return (2 * i + 1) * (i + 1); }))); - assert(equal( - a / b, native_simd<int>([](int i) { return (2 * i + 1) / (i + 1); }))); - assert(equal( - a % b, native_simd<int>([](int i) { return (2 * i + 1) % (i + 1); }))); - assert(equal( - a & b, native_simd<int>([](int i) { return (2 * i + 1) & (i + 1); }))); - assert(equal( - a | b, native_simd<int>([](int i) { return (2 * i + 1) | (i + 1); }))); - assert(equal( - a ^ b, native_simd<int>([](int i) { return (2 * i + 1) ^ (i + 1); }))); + assert(all_of(~a == native_simd<int>([](int i) { return ~(2 * i + 1); }))); + assert(all_of(+a == a)); + assert(all_of(-a == native_simd<int>([](int i) { return -(2 * i + 1); }))); + assert(all_of(a + b == native_simd<int>([](int i) { return 3 * i + 2; }))); + assert(all_of(a - b == native_simd<int>([](int i) { return i; }))); + assert(all_of(a * b == native_simd<int>( + [](int i) { return (2 * i + 1) * (i + 1); }))); + assert(all_of(a / b == native_simd<int>( + [](int i) { return (2 * i + 1) / (i + 1); }))); + assert(all_of(a % b == native_simd<int>( + [](int i) { return (2 * i + 1) % (i + 1); }))); + assert(all_of((a & b) == native_simd<int>( + [](int i) { return (2 * i + 1) & (i + 1); }))); + assert(all_of((a | b) == native_simd<int>( + [](int i) { return (2 * i + 1) | (i + 1); }))); + assert(all_of((a ^ b) == native_simd<int>( + [](int i) { return (2 * i + 1) ^ (i + 1); }))); } } void test_mutating_opreators() { native_simd<int> b(4); { native_simd<int> a(42); - assert(equal(++a, native_simd<int>(43))); - assert(equal(a, native_simd<int>(43))); + assert(all_of(++a == native_simd<int>(43))); + assert(all_of(a == native_simd<int>(43))); } { native_simd<int> a(42); - assert(equal(a++, native_simd<int>(42))); - assert(equal(a, native_simd<int>(43))); + assert(all_of(a++ == native_simd<int>(42))); + assert(all_of(a == native_simd<int>(43))); } { native_simd<int> a(42); - assert(equal(--a, native_simd<int>(41))); - assert(equal(a, native_simd<int>(41))); + assert(all_of(--a == native_simd<int>(41))); + assert(all_of(a == native_simd<int>(41))); } { native_simd<int> a(42); - assert(equal(a--, native_simd<int>(42))); - assert(equal(a, native_simd<int>(41))); + assert(all_of(a-- == native_simd<int>(42))); + assert(all_of(a == native_simd<int>(41))); } { native_simd<int> a(42); - assert(equal(a += b, native_simd<int>(42 + 4))); - assert(equal(a, native_simd<int>(42 + 4))); + assert(all_of((a += b) == native_simd<int>(42 + 4))); + assert(all_of(a == native_simd<int>(42 + 4))); } { native_simd<int> a(42); - assert(equal(a -= b, native_simd<int>(42 - 4))); - assert(equal(a, native_simd<int>(42 - 4))); + assert(all_of((a -= b) == native_simd<int>(42 - 4))); + assert(all_of(a == native_simd<int>(42 - 4))); } { native_simd<int> a(42); - assert(equal(a *= b, native_simd<int>(42 * 4))); - assert(equal(a, native_simd<int>(42 * 4))); + assert(all_of((a *= b) == native_simd<int>(42 * 4))); + assert(all_of(a == native_simd<int>(42 * 4))); } { native_simd<int> a(42); - assert(equal(a /= b, native_simd<int>(42 / 4))); - assert(equal(a, native_simd<int>(42 / 4))); + assert(all_of((a /= b) == native_simd<int>(42 / 4))); + assert(all_of(a == native_simd<int>(42 / 4))); } { native_simd<int> a(42); - assert(equal(a %= b, native_simd<int>(42 % 4))); - assert(equal(a, native_simd<int>(42 % 4))); + assert(all_of((a %= b) == native_simd<int>(42 % 4))); + assert(all_of(a == native_simd<int>(42 % 4))); } { native_simd<int> a(42); - assert(equal(a &= b, native_simd<int>(42 & 4))); - assert(equal(a, native_simd<int>(42 & 4))); + assert(all_of((a &= b) == native_simd<int>(42 & 4))); + assert(all_of(a == native_simd<int>(42 & 4))); } { native_simd<int> a(42); - assert(equal(a |= b, native_simd<int>(42 | 4))); - assert(equal(a, native_simd<int>(42 | 4))); + assert(all_of((a |= b) == native_simd<int>(42 | 4))); + assert(all_of(a == native_simd<int>(42 | 4))); } { native_simd<int> a(42); - assert(equal(a ^= b, native_simd<int>(42 ^ 4))); - assert(equal(a, native_simd<int>(42 ^ 4))); + assert(all_of((a ^= b) == native_simd<int>(42 ^ 4))); + assert(all_of(a == native_simd<int>(42 ^ 4))); } { native_simd<int> a(42); - assert(equal(a <<= b, native_simd<int>(42 << 4))); - assert(equal(a, native_simd<int>(42 << 4))); + assert(all_of((a <<= b) == native_simd<int>(42 << 4))); + assert(all_of(a == native_simd<int>(42 << 4))); } { native_simd<int> a(42); - assert(equal(a >>= b, native_simd<int>(42 >> 4))); - assert(equal(a, native_simd<int>(42 >> 4))); + assert(all_of((a >>= b) == native_simd<int>(42 >> 4))); + assert(all_of(a == native_simd<int>(42 >> 4))); } { native_simd<int> a(42); - assert(equal(a <<= 4, native_simd<int>(42 << 4))); - assert(equal(a, native_simd<int>(42 << 4))); + assert(all_of((a <<= 4) == native_simd<int>(42 << 4))); + assert(all_of(a == native_simd<int>(42 << 4))); } { native_simd<int> a(42); - assert(equal(a >>= 4, native_simd<int>(42 >> 4))); - assert(equal(a, native_simd<int>(42 >> 4))); + assert(all_of((a >>= 4) == native_simd<int>(42 >> 4))); + assert(all_of(a == native_simd<int>(42 >> 4))); } } Index: libcxx/test/std/experimental/simd/simd.elementwise/minmax.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.elementwise/minmax.pass.cpp +++ libcxx/test/std/experimental/simd/simd.elementwise/minmax.pass.cpp @@ -22,26 +22,16 @@ using namespace std::experimental::parallelism_v2; -template <typename T, typename Abi> -bool equal(simd<T, Abi> a, simd<T, Abi> b) { - for (size_t i = 0; i < a.size(); i++) { - if (a[i] != b[i]) { - return false; - } - } - return true; -} - void test_minmax() { int n = (int)native_simd<int>::size(); native_simd<int> mi, mx; std::tie(mi, mx) = minmax(native_simd<int>([](int i) { return i; }), native_simd<int>([n](int i) { return n - 1 - i; })), - assert(equal(mi, native_simd<int>([n](int i) { - return std::min(i, n - 1 - i); - }))); - assert(equal( - mx, native_simd<int>([n](int i) { return std::max(i, n - 1 - i); }))); + assert(all_of(mi == native_simd<int>([n](int i) { + return std::min(i, n - 1 - i); + }))); + assert(all_of( + mx == native_simd<int>([n](int i) { return std::max(i, n - 1 - i); }))); } int main() { test_minmax(); } Index: libcxx/test/std/experimental/simd/simd.elementwise/min.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.elementwise/min.pass.cpp +++ libcxx/test/std/experimental/simd/simd.elementwise/min.pass.cpp @@ -22,22 +22,12 @@ using namespace std::experimental::parallelism_v2; -template <typename T, typename Abi> -bool equal(simd<T, Abi> a, simd<T, Abi> b) { - for (size_t i = 0; i < a.size(); i++) { - if (a[i] != b[i]) { - return false; - } - } - return true; -} - void test_min() { int n = (int)native_simd<int>::size(); assert( - equal(min(native_simd<int>([](int i) { return i; }), - native_simd<int>([n](int i) { return n - 1 - i; })), - native_simd<int>([n](int i) { return std::min(i, n - 1 - i); }))); + all_of(min(native_simd<int>([](int i) { return i; }), + native_simd<int>([n](int i) { return n - 1 - i; })) == + native_simd<int>([n](int i) { return std::min(i, n - 1 - i); }))); } int main() { test_min(); } Index: libcxx/test/std/experimental/simd/simd.elementwise/max.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.elementwise/max.pass.cpp +++ libcxx/test/std/experimental/simd/simd.elementwise/max.pass.cpp @@ -22,22 +22,12 @@ using namespace std::experimental::parallelism_v2; -template <typename T, typename Abi> -bool equal(simd<T, Abi> a, simd<T, Abi> b) { - for (size_t i = 0; i < a.size(); i++) { - if (a[i] != b[i]) { - return false; - } - } - return true; -} - void test_max() { int n = (int)native_simd<int>::size(); assert( - equal(max(native_simd<int>([](int i) { return i; }), - native_simd<int>([n](int i) { return n - 1 - i; })), - native_simd<int>([n](int i) { return std::max(i, n - 1 - i); }))); + all_of(max(native_simd<int>([](int i) { return i; }), + native_simd<int>([n](int i) { return n - 1 - i; })) == + native_simd<int>([n](int i) { return std::max(i, n - 1 - i); }))); } int main() { test_max(); } Index: libcxx/test/std/experimental/simd/simd.elementwise/clamp.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.elementwise/clamp.pass.cpp +++ libcxx/test/std/experimental/simd/simd.elementwise/clamp.pass.cpp @@ -22,25 +22,15 @@ using namespace std::experimental::parallelism_v2; -template <typename T, typename Abi> -bool equal(simd<T, Abi> a, simd<T, Abi> b) { - for (size_t i = 0; i < a.size(); i++) { - if (a[i] != b[i]) { - return false; - } - } - return true; -} - void test_clamp() { auto actual = clamp(fixed_size_simd<int, 16>([](int i) { return i - 8; }), fixed_size_simd<int, 16>([](int) { return 0; }), fixed_size_simd<int, 16>([](int) { return 5; })); int expected[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 5}; - assert( - equal(fixed_size_simd<int, 16>(expected, element_aligned_tag()), actual)); + assert(all_of(fixed_size_simd<int, 16>(expected, element_aligned_tag()) == + actual)); } int main() { test_clamp(); } Index: libcxx/test/std/experimental/simd/simd.casts/to_native.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.casts/to_native.pass.cpp +++ libcxx/test/std/experimental/simd/simd.casts/to_native.pass.cpp @@ -25,27 +25,47 @@ 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; }); + { + 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, ""); + static_assert(std::is_same<decltype(v), decltype(w)>::value, ""); - for (size_t i = 0; i < v.size(); i++) { - assert(v[i] == w[i]); + for (size_t i = 0; i < v.size(); i++) { + assert(v[i] == w[i]); + } + } + { + auto v = to_native( + fixed_size_simd_mask<int, native_simd_mask<int>::size()>(true)); + static_assert(std::is_same<native_simd_mask<int>, decltype(v)>::value, ""); + assert(all_of(v)); } } 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++; + { + std::array<native_simd<int>, 2> arr = split_by<2>( + to_native(fixed_size_simd<int, native_simd<int>::size() * 2>( + [](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++; + } + } + } + { + std::array<native_simd_mask<int>, 2> arr = split_by<2>(to_native( + fixed_size_simd_mask<int, native_simd_mask<int>::size() * 2>(true))); + for (size_t i = 0; i < arr.size(); i++) { + for (size_t j = 0; j < arr[0].size(); j++) { + assert(arr[i][j]); + } } } } Index: libcxx/test/std/experimental/simd/simd.casts/to_fixed_size.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.casts/to_fixed_size.pass.cpp +++ libcxx/test/std/experimental/simd/simd.casts/to_fixed_size.pass.cpp @@ -27,13 +27,23 @@ 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, - ""); + { + 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); + for (size_t i = 0; i < v.size(); i++) { + assert(v[i] == (int)i); + } + } + { + auto v = to_fixed_size(native_simd_mask<int>(true)); + static_assert( + std::is_same<fixed_size_simd_mask<int, native_simd_mask<int>::size()>, + decltype(v)>::value, + ""); + assert(all_of(v)); } } Index: libcxx/test/std/experimental/simd/simd.casts/to_compatible.pass.cpp =================================================================== --- libcxx/test/std/experimental/simd/simd.casts/to_compatible.pass.cpp +++ libcxx/test/std/experimental/simd/simd.casts/to_compatible.pass.cpp @@ -25,26 +25,47 @@ 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; }); + { + 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, ""); + static_assert(std::is_same<decltype(v), decltype(w)>::value, ""); - for (size_t i = 0; i < v.size(); i++) { - assert(v[i] == w[i]); + for (size_t i = 0; i < v.size(); i++) { + assert(v[i] == w[i]); + } + } + + { + auto v = + to_compatible(fixed_size_simd_mask<int, simd_mask<int>::size()>(true)); + static_assert(std::is_same<simd_mask<int>, decltype(v)>::value, ""); + assert(all_of(v)); } } 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++; + { + std::array<simd<int>, 2> arr = split_by<2>(to_compatible( + fixed_size_simd<int, simd<int>::size() * 2>([](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++; + } + } + } + { + std::array<simd_mask<int>, 2> arr = split_by<2>(to_compatible( + fixed_size_simd_mask<int, simd_mask<int>::size() * 2>(true))); + for (size_t i = 0; i < arr.size(); i++) { + for (size_t j = 0; j < arr[0].size(); j++) { + assert(arr[i][j]); + } } } } Index: libcxx/include/experimental/simd =================================================================== --- libcxx/include/experimental/simd +++ libcxx/include/experimental/simd @@ -1172,32 +1172,22 @@ 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, 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, int _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, 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, int _Np> -simd_mask<_Tp> to_compatible(const fixed_size_simd_mask<_Tp, _Np>&) noexcept; - template <class _TupleType, class _Tp, size_t... __indices> _TupleType __split_tuple_impl(_Tp** __buffers, std::index_sequence<__indices...>) { @@ -1273,10 +1263,6 @@ return __split_impl(__v, std::integral_constant<size_t, __sizes>()...); } -template <size_t... __sizes, class _Tp, class _Abi> -tuple<simd_mask<_Tp, rebind_abi_t<_Tp, __sizes, _Abi>>...> -split(const simd_mask<_Tp, _Abi>&); - template <class _Tp, class _Abi, class _Abi2, size_t __array_size, size_t... __indices> void __split_by_impl(const simd<_Tp, _Abi>& __v, @@ -1316,18 +1302,6 @@ _SimdType::size()>(__v); } -template <size_t __array_size, class _Tp, class _Abi> -array< - simd_mask<_Tp, rebind_abi_t<_Tp, simd_size<_Tp, _Abi>::value / __array_size, - _Abi>>, - __array_size> -split_by(const simd_mask<_Tp, _Abi>& x); - -template <class _SimdType, class _Abi> -array<_SimdType, simd_size<typename _SimdType::value_type, _Abi>::value / - _SimdType::size()> -split(const simd_mask<typename _SimdType::value_type, _Abi>&); - template <class _Tp, class _Abi> simd<_Tp, _Abi> __concat_variadic(const simd<_Tp, _Abi>& __v) { return __v; @@ -1367,15 +1341,157 @@ return __concat_array(__arr, std::make_index_sequence<_Np>()); } +struct __simd_mask_friend { + template <class _Tp, class _Abi> + static fixed_size_simd_mask<_Tp, simd_size<_Tp, _Abi>::value> + __to_fixed_size(const simd_mask<_Tp, _Abi>& __m) noexcept { + return to_fixed_size(__m.__s_); + } + + template <class _Tp, int _Np> + static simd_mask<_Tp, simd_abi::__native<_Tp, _Np>> + __to_native(const fixed_size_simd_mask<_Tp, _Np>& __m) noexcept { + return to_native(__m.__s_); + } + + template <class _Tp, int _Np> + static simd_mask<_Tp, simd_abi::__compatible<_Tp, _Np>> + __to_compatible(const fixed_size_simd_mask<_Tp, _Np>& __m) noexcept { + return to_compatible(__m.__s_); + } + + template <class _ResType, class _TupleType, size_t... __indices> + static _ResType __split_impl(const _TupleType& __t, + std::index_sequence<__indices...>) { + return _ResType(std::get<__indices>(__t)...); + } + + template <size_t... __sizes, class _Tp, class _Abi> + static typename std::enable_if< + __variadic_sum<size_t>(__sizes...) == simd<_Tp, _Abi>::size(), + tuple<simd_mask<_Tp, rebind_abi_t<_Tp, __sizes, _Abi>>...>>::type + __split(const simd_mask<_Tp, _Abi>& __m) { + return __split_impl< + tuple<simd_mask<_Tp, rebind_abi_t<_Tp, __sizes, _Abi>>...>>( + split<__sizes...>(__m.__s_), + std::make_index_sequence<sizeof...(__sizes)>()); + } + + template <size_t __array_size, class _Tp, class _Abi> + static typename std::enable_if< + simd_size<_Tp, _Abi>::value % __array_size == 0, + array<simd_mask<_Tp, rebind_abi_t< + _Tp, simd_size<_Tp, _Abi>::value / __array_size, + _Abi>>, + __array_size>>::type + __split_by(const simd_mask<_Tp, _Abi>& __m) { + auto __arr = split_by<__array_size>(__m.__s_); + array<simd_mask< + _Tp, rebind_abi_t<_Tp, simd_size<_Tp, _Abi>::value / __array_size, + _Abi>>, + __array_size> + __ret; + for (size_t __i = 0; __i < __ret.size(); __i++) { + __ret[__i] = __arr[__i]; + } + return __ret; + } + + template <class _MaskType, class _Abi> + static typename std::enable_if< + is_simd_mask<_MaskType>::value && + simd_size<typename _MaskType::value_type, _Abi>::value % + _MaskType::size() == + 0, + array<_MaskType, simd_size<typename _MaskType::value_type, _Abi>::value / + _MaskType::size()>>::type + __split(const simd_mask<typename _MaskType::value_type, _Abi>& __m) { + return split<typename _MaskType::simd_type>(__m.__s_); + } + + template <class _Tp, class... _Abis> + static simd_mask< + _Tp, + rebind_abi_t<_Tp, __variadic_sum<size_t>(simd_size<_Tp, _Abis>::value...), + _Abis...>> + __concat(const simd_mask<_Tp, _Abis>&... __ms) { + return concat(__ms.__s_...); + } + + template <class _Tp, class _Abi, size_t _Np> + static simd_mask<_Tp, + rebind_abi_t<_Tp, _Np * simd_size<_Tp, _Abi>::value, _Abi>> + __concat(const std::array<simd_mask<_Tp, _Abi>, _Np>& __ms) { + std::array<decltype(__ms[0].__s_), _Np> __arr; + for (size_t __i = 0; __i < __ms.size(); __i++) { + __arr[__i] = __ms[__i].__s_; + } + return concat(__arr); + } +}; + +template <class _Tp, class _Abi> +fixed_size_simd_mask<_Tp, simd_size<_Tp, _Abi>::value> +to_fixed_size(const simd_mask<_Tp, _Abi>& __m) noexcept { + return __simd_mask_friend::__to_fixed_size(__m); +} + +template <class _Tp, int _Np> +simd_mask<_Tp, simd_abi::__native<_Tp, _Np>> +to_native(const fixed_size_simd_mask<_Tp, _Np>& __m) noexcept { + return __simd_mask_friend::__to_native(__m); +} + +template <class _Tp, int _Np> +simd_mask<_Tp, simd_abi::__compatible<_Tp, _Np>> +to_compatible(const fixed_size_simd_mask<_Tp, _Np>& __m) noexcept { + return __simd_mask_friend::__to_compatible(__m); +} + +template <size_t... __sizes, class _Tp, class _Abi> +typename std::enable_if< + __variadic_sum<size_t>(__sizes...) == simd<_Tp, _Abi>::size(), + tuple<simd_mask<_Tp, rebind_abi_t<_Tp, __sizes, _Abi>>...>>::type +split(const simd_mask<_Tp, _Abi>& __m) { + return __simd_mask_friend::__split<__sizes...>(__m); +} + +template <size_t __array_size, class _Tp, class _Abi> +static typename std::enable_if< + simd_size<_Tp, _Abi>::value % __array_size == 0, + array<simd_mask< + _Tp, rebind_abi_t<_Tp, simd_size<_Tp, _Abi>::value / __array_size, + _Abi>>, + __array_size>>::type +split_by(const simd_mask<_Tp, _Abi>& __m) { + return __simd_mask_friend::__split_by<__array_size>(__m); +} + +template <class _MaskType, class _Abi> +static typename std::enable_if< + is_simd_mask<_MaskType>::value && + simd_size<typename _MaskType::value_type, _Abi>::value % + _MaskType::size() == + 0, + array<_MaskType, simd_size<typename _MaskType::value_type, _Abi>::value / + _MaskType::size()>>::type +split(const simd_mask<typename _MaskType::value_type, _Abi>& __m) { + return __simd_mask_friend::__split<_MaskType>(__m); +} + template <class _Tp, class... _Abis> simd_mask<_Tp, rebind_abi_t< _Tp, __variadic_sum<size_t>(simd_size<_Tp, _Abis>::value...), _Abis...>> -concat(const simd_mask<_Tp, _Abis>&...); +concat(const simd_mask<_Tp, _Abis>&... __ms) { + return __simd_mask_friend::__concat(__ms...); +} template <class _Tp, class _Abi, size_t _Np> -simd_mask<_Tp, rebind_abi_t<_Tp, _Np, _Abi>> -concat(const std::array<simd_mask<_Tp, _Abi>, _Np>&); +simd_mask<_Tp, rebind_abi_t<_Tp, _Np * simd_size<_Tp, _Abi>::value, _Abi>> +concat(const std::array<simd_mask<_Tp, _Abi>, _Np>& __ms) { + return __simd_mask_friend::__concat(__ms); +} // reductions [simd.mask.reductions] template <class _Tp, class _Abi> @@ -1386,25 +1502,96 @@ } return __ret; } + template <class _Tp, class _Abi> -bool any_of(const simd_mask<_Tp, _Abi>&) noexcept; +bool any_of(const simd_mask<_Tp, _Abi>& __m) noexcept { + bool __ret = false; + for (size_t __i = 0; __i < __m.size(); __i++) { + __ret |= __m[__i]; + } + return __ret; +} + template <class _Tp, class _Abi> -bool none_of(const simd_mask<_Tp, _Abi>&) noexcept; +bool none_of(const simd_mask<_Tp, _Abi>& __m) noexcept { + return !any_of(__m); +} + template <class _Tp, class _Abi> -bool some_of(const simd_mask<_Tp, _Abi>&) noexcept; +bool some_of(const simd_mask<_Tp, _Abi>& __m) noexcept { + return !all_of(__m) && !none_of(__m); +} + template <class _Tp, class _Abi> -int popcount(const simd_mask<_Tp, _Abi>&) noexcept; +int popcount(const simd_mask<_Tp, _Abi>& __m) noexcept { + int __ret = 0; + for (size_t __i = 0; __i < __m.size(); __i++) { + __ret += __m[__i]; + } + return __ret; +} + template <class _Tp, class _Abi> -int find_first_set(const simd_mask<_Tp, _Abi>&); +int find_first_set(const simd_mask<_Tp, _Abi>& __m) { + for (size_t __i = 0; __i < __m.size(); __i++) { + if (__m[__i]) { + return __i; + } + } + return __m.size(); +} + template <class _Tp, class _Abi> -int find_last_set(const simd_mask<_Tp, _Abi>&); -bool all_of(bool) noexcept; -bool any_of(bool) noexcept; -bool none_of(bool) noexcept; -bool some_of(bool) noexcept; -int popcount(bool) noexcept; -int find_first_set(bool) noexcept; -int find_last_set(bool) noexcept; +int find_last_set(const simd_mask<_Tp, _Abi>& __m) { + for (int __i = __m.size() - 1; __i >= 0; __i--) { + if (__m[__i]) { + return __i; + } + } + return __m.size(); +} + +template <class _Tp> +typename std::enable_if<std::is_same<_Tp, bool>::value, bool>::type +all_of(_Tp __v) noexcept { + return __v; +} + +template <class _Tp> +typename std::enable_if<std::is_same<_Tp, bool>::value, bool>::type +any_of(_Tp __v) noexcept { + return __v; +} + +template <class _Tp> +typename std::enable_if<std::is_same<_Tp, bool>::value, bool>::type +none_of(_Tp __v) noexcept { + return !__v; +} + +template <class _Tp> +typename std::enable_if<std::is_same<_Tp, bool>::value, bool>::type +some_of(_Tp) noexcept { + return false; +} + +template <class _Tp> +typename std::enable_if<std::is_same<_Tp, bool>::value, int>::type +popcount(_Tp __v) noexcept { + return __v; +} + +template <class _Tp> +typename std::enable_if<std::is_same<_Tp, bool>::value, int>::type +find_first_set(_Tp) noexcept { + return 0; +} + +template <class _Tp> +typename std::enable_if<std::is_same<_Tp, bool>::value, int>::type +find_last_set(_Tp) noexcept { + return 0; +} // masked assignment [simd.whereexpr] template <class _MaskType, class _Tp> @@ -1734,7 +1921,7 @@ return __tmp; } - mask_type operator!() const; + mask_type operator!() const { return *this == simd(0); } simd operator~() const { simd __v; @@ -1953,7 +2140,9 @@ simd<__element_type, _Abi> __s_; - explicit simd_mask(const simd<__element_type, _Abi>& __mask) : __s_(__mask) {} + simd_mask(const simd<__element_type, _Abi>& __mask) : __s_(__mask) {} + + friend struct __simd_mask_friend; public: using value_type = bool;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits