timshen updated this revision to Diff 128687. timshen added a comment. Remove unintended binary file.
https://reviews.llvm.org/D41747 Files: libcxx/include/experimental/simd libcxx/test/std/experimental/simd/simd.elementwise/operators.pass.cpp libcxx/test/std/experimental/simd/simd.mask.access/default.pass.cpp libcxx/test/std/experimental/simd/simd.mask.cons/broadcast.pass.cpp libcxx/test/std/experimental/simd/simd.mask.cons/default.pass.cpp libcxx/test/std/experimental/simd/simd.mask.cons/fixed_size_conversion.pass.cpp libcxx/test/std/experimental/simd/simd.mask.cons/load.pass.cpp libcxx/test/std/experimental/simd/simd.mask.elementwise/operators.pass.cpp libcxx/test/std/experimental/simd/simd.mask.mem/load.pass.cpp libcxx/test/std/experimental/simd/simd.mask.mem/store.pass.cpp
Index: libcxx/test/std/experimental/simd/simd.mask.mem/store.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/experimental/simd/simd.mask.mem/store.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// 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> +// +// loads [simd.mask.copy] +// template <class Flags> void copy_to(value_type* mem, Flags) const; + +#include <experimental/simd> + +#include "test_macros.h" + +using namespace std::experimental::parallelism_v2; + +void test_store() { + fixed_size_simd_mask<int, 4> a; + a[0] = false; + a[1] = true; + a[2] = true; + a[3] = false; + { + alignas(32) bool buffer[4] = {0}; + a.copy_to(buffer, element_aligned_tag()); + assert(!buffer[0]); + assert(buffer[1]); + assert(buffer[2]); + assert(!buffer[3]); + } + { + alignas(32) bool buffer[4] = {0}; + a.copy_to(buffer, vector_aligned_tag()); + assert(!buffer[0]); + assert(buffer[1]); + assert(buffer[2]); + assert(!buffer[3]); + } + { + alignas(32) bool buffer[4] = {0}; + a.copy_to(buffer, overaligned_tag<32>()); + assert(!buffer[0]); + assert(buffer[1]); + assert(buffer[2]); + assert(!buffer[3]); + } + +#if TEST_STD_VER > 14 + { + alignas(32) bool buffer[4] = {0}; + a.copy_to(buffer, element_aligned); + assert(!buffer[0]); + assert(buffer[1]); + assert(buffer[2]); + assert(!buffer[3]); + } + { + alignas(32) bool buffer[4] = {0}; + a.copy_to(buffer, vector_aligned); + assert(!buffer[0]); + assert(buffer[1]); + assert(buffer[2]); + assert(!buffer[3]); + } + { + alignas(32) bool buffer[4] = {0}; + a.copy_to(buffer, overaligned<32>); + assert(!buffer[0]); + assert(buffer[1]); + assert(buffer[2]); + assert(!buffer[3]); + } +#endif +} + +int main() { test_store(); } Index: libcxx/test/std/experimental/simd/simd.mask.mem/load.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/experimental/simd/simd.mask.mem/load.pass.cpp @@ -0,0 +1,105 @@ +//===----------------------------------------------------------------------===// +// +// 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> +// +// loads [simd.mask.copy] +// template <class Flags> void copy_from(const value_type* mem, Flags); + +#include <experimental/simd> +#include <cstdint> + +#include "test_macros.h" + +using namespace std::experimental::parallelism_v2; + +template <class T, class... Args> +auto not_supported_load(Args&&... args) -> decltype( + std::declval<native_simd_mask<T>>().copy_from(std::forward<Args>(args)...), + void()) = delete; + +template <class T> +void not_supported_load(...) {} + +template <class T, class... Args> +auto supported_load(Args&&... args) -> decltype( + std::declval<native_simd_mask<T>>().copy_from(std::forward<Args>(args)...), + void()) {} + +template <class T> +void supported_load(...) = delete; + +void compile_load() { + supported_load<int>((bool*)nullptr, element_aligned_tag()); + supported_load<uint32_t>((bool*)nullptr, element_aligned_tag()); + supported_load<double>((bool*)nullptr, element_aligned_tag()); + supported_load<uint16_t>((bool*)nullptr, element_aligned_tag()); + supported_load<uint32_t>((bool*)nullptr, element_aligned_tag()); + + not_supported_load<int>((bool*)nullptr, int()); +} + +void test_load() { + alignas(32) bool buffer[] = {false, true, true, false}; + { + fixed_size_simd_mask<int32_t, 4> a; + a.copy_from(buffer, element_aligned_tag()); + assert(!a[0]); + assert(a[1]); + assert(a[2]); + assert(!a[3]); + } + { + fixed_size_simd_mask<int32_t, 4> a; + a.copy_from(buffer, vector_aligned_tag()); + assert(!a[0]); + assert(a[1]); + assert(a[2]); + assert(!a[3]); + } + { + fixed_size_simd_mask<int32_t, 4> a; + a.copy_from(buffer, overaligned_tag<32>()); + assert(!a[0]); + assert(a[1]); + assert(a[2]); + assert(!a[3]); + } + +#if TEST_STD_VER > 14 + { + fixed_size_simd_mask<int32_t, 4> a; + a.copy_from(buffer, element_aligned); + assert(!a[0]); + assert(a[1]); + assert(a[2]); + assert(!a[3]); + } + { + fixed_size_simd_mask<int32_t, 4> a; + a.copy_from(buffer, vector_aligned); + assert(!a[0]); + assert(a[1]); + assert(a[2]); + assert(!a[3]); + } + { + fixed_size_simd_mask<int32_t, 4> a; + a.copy_from(buffer, overaligned<32>); + assert(!a[0]); + assert(a[1]); + assert(a[2]); + assert(!a[3]); + } +#endif +} + +int main() { test_load(); } Index: libcxx/test/std/experimental/simd/simd.mask.elementwise/operators.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/experimental/simd/simd.mask.elementwise/operators.pass.cpp @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// +// 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.mask.class] +// // unary operators [simd.mask.unary] +// simd_mask operator!() const noexcept; +// +// // simd_mask binary operators [simd.mask.binary] +// friend simd_mask operator&&(const simd_mask&, const simd_mask&) noexcept; +// friend simd_mask operator||(const simd_mask&, const simd_mask&) noexcept; +// friend simd_mask operator& (const simd_mask&, const simd_mask&) noexcept; +// friend simd_mask operator| (const simd_mask&, const simd_mask&) noexcept; +// friend simd_mask operator^ (const simd_mask&, const simd_mask&) noexcept; +// +// // simd_mask compound assignment [simd.mask.cassign] +// friend simd_mask& operator&=(simd_mask&, const simd_mask&) noexcept; +// friend simd_mask& operator|=(simd_mask&, const simd_mask&) noexcept; +// friend simd_mask& operator^=(simd_mask&, const simd_mask&) noexcept; +// +// // simd_mask compares [simd.mask.comparison] +// friend simd_mask operator==(const simd_mask&, const simd_mask&) noexcept; +// friend simd_mask operator!=(const simd_mask&, const simd_mask&) noexcept; + +#include <cstdint> +#include <experimental/simd> + +using namespace std::experimental::parallelism_v2; + +void test_pure_operators() { + assert(all_of(!simd_mask<int>(false))); + assert(all_of(simd_mask<int>(false) == + (simd_mask<int>(false) && simd_mask<int>(true)))); + assert(all_of(simd_mask<int>(true) == + (simd_mask<int>(false) || simd_mask<int>(true)))); + assert(all_of(simd_mask<int>(false) == + (simd_mask<int>(false) & simd_mask<int>(true)))); + assert(all_of(simd_mask<int>(true) == + (simd_mask<int>(false) | simd_mask<int>(true)))); + assert(all_of(simd_mask<int>(true) == + (simd_mask<int>(false) ^ simd_mask<int>(true)))); + assert(all_of(simd_mask<int>(false) == + (simd_mask<int>(true) ^ simd_mask<int>(true)))); +} + +void test_mutating_opreators() { + { + simd_mask<int> a(true); + a &= simd_mask<int>(false); + assert(all_of(simd_mask<int>(false) == a)); + } + { + simd_mask<int> a(true); + a |= simd_mask<int>(false); + assert(all_of(simd_mask<int>(true) == a)); + } + { + simd_mask<int> a(true); + a ^= simd_mask<int>(false); + assert(all_of(simd_mask<int>(true) == a)); + } + { + simd_mask<int> a(true); + a ^= simd_mask<int>(true); + assert(all_of(simd_mask<int>(false) == a)); + } +} + +void test_relational_operators() { + assert(all_of(!(simd_mask<int>(false) == simd_mask<int>(true)))); + assert(all_of(simd_mask<int>(false) != simd_mask<int>(true))); + assert(all_of(simd_mask<int>(false) == simd_mask<int>(false))); + assert(all_of(!(simd_mask<int>(false) != simd_mask<int>(false)))); + assert(all_of(simd_mask<int>(true) == simd_mask<int>(true))); + assert(all_of(!(simd_mask<int>(true) != simd_mask<int>(true)))); +} + +int main() { + test_pure_operators(); + test_mutating_opreators(); + test_relational_operators(); +} Index: libcxx/test/std/experimental/simd/simd.mask.cons/load.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/experimental/simd/simd.mask.cons/load.pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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.mask.class] +// load constructor +// template <class Flags> simd_mask(const value_type* mem, Flags); + +#include <experimental/simd> + +#include "test_macros.h" + +using namespace std::experimental::parallelism_v2; + +void test_load_ctor() { + { + bool buf[] = {false, true, true, false}; + fixed_size_simd_mask<int, 4> m(buf, element_aligned_tag()); + assert(buf[0] == m[0]); + assert(buf[1] == m[1]); + assert(buf[2] == m[2]); + assert(buf[3] == m[3]); + } + { + bool buf[] = {false, true, true, false}; + fixed_size_simd_mask<int, 4> m(buf, vector_aligned_tag()); + assert(buf[0] == m[0]); + assert(buf[1] == m[1]); + assert(buf[2] == m[2]); + assert(buf[3] == m[3]); + } + { + bool buf[] = {false, true, true, false}; + fixed_size_simd_mask<int, 4> m(buf, overaligned_tag<32>()); + assert(buf[0] == m[0]); + assert(buf[1] == m[1]); + assert(buf[2] == m[2]); + assert(buf[3] == m[3]); + } +#if TEST_STD_VER > 14 + { + bool buf[] = {false, true, true, false}; + fixed_size_simd_mask<int, 4> m(buf, element_aligned); + assert(buf[0] == m[0]); + assert(buf[1] == m[1]); + assert(buf[2] == m[2]); + assert(buf[3] == m[3]); + } + { + bool buf[] = {false, true, true, false}; + fixed_size_simd_mask<int, 4> m(buf, vector_aligned); + assert(buf[0] == m[0]); + assert(buf[1] == m[1]); + assert(buf[2] == m[2]); + assert(buf[3] == m[3]); + } + { + bool buf[] = {false, true, true, false}; + fixed_size_simd_mask<int, 4> m(buf, overaligned<32>); + assert(buf[0] == m[0]); + assert(buf[1] == m[1]); + assert(buf[2] == m[2]); + assert(buf[3] == m[3]); + } +#endif +} + +int main() { test_load_ctor(); } Index: libcxx/test/std/experimental/simd/simd.mask.cons/fixed_size_conversion.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/experimental/simd/simd.mask.cons/fixed_size_conversion.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// 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.mask.class] +// implicit type conversion constructor +// template <class U> simd(const simd<U, simd_abi::fixed_size<size()>>&); + +#include <cstdint> +#include <experimental/simd> + +using namespace std::experimental::parallelism_v2; + +void test_fixed_size_conversion() { + { + fixed_size_simd_mask<float, 4> m = fixed_size_simd_mask<int, 4>(false); + for (size_t i = 0; i < m.size(); i++) { + assert(!m[i]); + } + } + { + fixed_size_simd_mask<float, 4> m = fixed_size_simd_mask<int, 4>(true); + for (size_t i = 0; i < m.size(); i++) { + assert(m[i]); + } + } +} + +int main() { test_fixed_size_conversion(); } Index: libcxx/test/std/experimental/simd/simd.mask.cons/default.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/experimental/simd/simd.mask.cons/default.pass.cpp @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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.mask.class] +// simd() = default; + +#include <cstdint> +#include <experimental/simd> + +using namespace std::experimental::parallelism_v2; + +int main() { (void)native_simd_mask<int32_t>(); } Index: libcxx/test/std/experimental/simd/simd.mask.cons/broadcast.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/experimental/simd/simd.mask.cons/broadcast.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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.mask.class] +// broadcast constructor +// explicit simd_mask(value_type) noexcept; + +#include <experimental/simd> + +using namespace std::experimental::parallelism_v2; + +void test_broadcast() { + { + native_simd_mask<int> m(false); + for (size_t i = 0; i < m.size(); i++) { + assert(!m[i]); + } + } + { + native_simd_mask<int> m(true); + for (size_t i = 0; i < m.size(); i++) { + assert(m[i]); + } + } +} + +int main() { test_broadcast(); } Index: libcxx/test/std/experimental/simd/simd.mask.access/default.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/experimental/simd/simd.mask.access/default.pass.cpp @@ -0,0 +1,210 @@ +//===----------------------------------------------------------------------===// +// +// 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> +// +// scalar access [simd.mask.subscr] +// reference operator[](size_t); +// value_type operator[](size_t) const; + +#include <experimental/simd> +#include <cassert> +#include <cstdint> + +using namespace std::experimental::parallelism_v2; + +void test_access() { + { + fixed_size_simd_mask<int, 2> a(false), b(true); + + assert(bool(a[0]) == false); + assert(bool(!a[0]) == true); + assert(bool(~a[0]) == true); + assert(bool(+a[0]) == false); + assert(bool(-a[0]) == false); + assert(bool(a[0] + b[0]) == true); + assert(bool(a[0] - b[0]) == true); + assert(bool(a[0] * b[0]) == false); + assert(bool(a[0] / b[0]) == false); + assert(bool(a[0] % b[0]) == false); + assert(bool(a[0] << b[0]) == false); + assert(bool(a[0] >> b[0]) == false); + assert(bool(a[0] < b[0]) == true); + assert(bool(a[0] <= b[0]) == true); + assert(bool(a[0] > b[0]) == false); + assert(bool(a[0] >= b[0]) == false); + assert(bool(a[0] == b[0]) == false); + assert(bool(a[0] != b[0]) == true); + assert(bool((a[0] & b[0])) == false); + assert(bool((a[0] | b[0])) == true); + assert(bool((a[0] ^ b[0])) == true); + assert(bool((a[0] && b[0])) == false); + assert(bool((a[0] || b[0])) == true); + + { + auto c = a; + ++c[0]; + assert(bool(c[0]) == true); + assert(bool(c[1]) == false); + } + { + auto c = a; + auto ret = c[0]++; + assert(ret == false); + assert(bool(c[0]) == true); + assert(bool(c[1]) == false); + } + { + auto c = a; + --c[0]; + assert(bool(c[0]) == true); + assert(bool(c[1]) == false); + } + { + auto c = a; + auto ret = c[0]--; + assert(ret == false); + assert(bool(c[0]) == true); + assert(bool(c[1]) == false); + } + + { + auto c = a; + c[0] += b[0]; + assert(bool(c[0]) == true); + assert(bool(c[1]) == false); + } + { + auto c = a; + c[0] -= b[0]; + assert(bool(c[0]) == true); + assert(bool(c[1]) == false); + } + { + auto c = b; + c[0] *= a[0]; + assert(bool(c[0]) == false); + assert(bool(c[1]) == true); + } + { + auto c = a; + c[0] /= b[0]; + assert(bool(c[0]) == false); + assert(bool(c[1]) == false); + } + { + auto c = a; + c[0] %= b[0]; + assert(bool(c[0]) == false); + assert(bool(c[1]) == false); + } + { + auto c = a; + c[0] >>= b[0]; + assert(bool(c[0]) == false); + assert(bool(c[1]) == false); + } + { + auto c = a; + c[0] <<= b[0]; + assert(bool(c[0]) == false); + assert(bool(c[1]) == false); + } + { + auto c = a; + c[0] &= b[0]; + assert(bool(c[0]) == false); + assert(bool(c[1]) == false); + } + { + auto c = a; + c[0] |= b[0]; + assert(bool(c[0]) == true); + assert(bool(c[1]) == false); + } + { + auto c = a; + c[0] ^= b[0]; + assert(bool(c[0]) == true); + assert(bool(c[1]) == false); + } + + { + auto c = a; + (void)(a[0] + (c[0] += a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] -= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] *= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] /= b[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] %= b[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] >>= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] <<= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] &= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] |= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] ^= a[0])); + } + } + { + const fixed_size_simd_mask<int, 2> a(false), b(true); + + assert(bool(a[0]) == false); + assert(bool(!a[0]) == true); + assert(bool(~a[0]) == true); + assert(bool(+a[0]) == false); + assert(bool(-a[0]) == false); + assert(bool(a[0] + b[0]) == true); + assert(bool(a[0] - b[0]) == true); + assert(bool(a[0] * b[0]) == false); + assert(bool(a[0] / b[0]) == false); + assert(bool(a[0] % b[0]) == false); + assert(bool(a[0] << b[0]) == false); + assert(bool(a[0] >> b[0]) == false); + assert(bool(a[0] < b[0]) == true); + assert(bool(a[0] <= b[0]) == true); + assert(bool(a[0] > b[0]) == false); + assert(bool(a[0] >= b[0]) == false); + assert(bool(a[0] == b[0]) == false); + assert(bool(a[0] != b[0]) == true); + assert(bool((a[0] & b[0])) == false); + assert(bool((a[0] | b[0])) == true); + assert(bool((a[0] ^ b[0])) == true); + assert(bool((a[0] && b[0])) == false); + assert(bool((a[0] || b[0])) == true); + } +} + +int main() { test_access(); } 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 @@ -49,6 +49,14 @@ // friend simd& operator>>=(simd&, const simd&); // friend simd& operator<<=(simd&, int); // friend simd& operator>>=(simd&, int); +// +// // compares [simd.comparison] +// friend mask_type operator==(const simd&, const simd&); +// friend mask_type operator!=(const simd&, const simd&); +// friend mask_type operator>=(const simd&, const simd&); +// friend mask_type operator<=(const simd&, const simd&); +// friend mask_type operator> (const simd&, const simd&); +// friend mask_type operator< (const simd&, const simd&); #include <cassert> #include <cstdint> @@ -194,7 +202,74 @@ } } +void test_relational_operators() { + fixed_size_simd<int, 9> a, b; + { + int buf[] = {1, 1, 1, 2, 2, 2, 3, 3, 3}; + a.copy_from(buf, element_aligned_tag()); + } + { + int buf[] = {1, 2, 3, 1, 2, 3, 1, 2, 3}; + b.copy_from(buf, element_aligned_tag()); + } + { + bool expected[] = { + true, false, false, + false, true, false, + false, false, true, + }; + assert(all_of((a == b) == fixed_size_simd_mask<int, 9>( + expected, element_aligned_tag()))); + } + { + bool expected[] = { + false, true, true, + true, false, true, + true, true, false, + }; + assert(all_of((a != b) == fixed_size_simd_mask<int, 9>( + expected, element_aligned_tag()))); + } + { + bool expected[] = { + false, true, true, + false, false, true, + false, false, false, + }; + assert(all_of((a < b) == fixed_size_simd_mask<int, 9>( + expected, element_aligned_tag()))); + } + { + bool expected[] = { + true, true, true, + false, true, true, + false, false, true, + }; + assert(all_of((a <= b) == fixed_size_simd_mask<int, 9>( + expected, element_aligned_tag()))); + } + { + bool expected[] = { + false, false, false, + true, false, false, + true, true, false, + }; + assert(all_of((a > b) == fixed_size_simd_mask<int, 9>( + expected, element_aligned_tag()))); + } + { + bool expected[] = { + true, false, false, + true, true, false, + true, true, true, + }; + assert(all_of((a >= b) == fixed_size_simd_mask<int, 9>( + expected, element_aligned_tag()))); + } +} + int main() { test_pure_operators(); test_mutating_opreators(); + test_relational_operators(); } Index: libcxx/include/experimental/simd =================================================================== --- libcxx/include/experimental/simd +++ libcxx/include/experimental/simd @@ -706,14 +706,20 @@ template <class _Vp, class _Tp, class _Abi> class __simd_reference { - static_assert(std::is_same<_Vp, _Tp>::value, ""); + static_assert(std::is_same<_Vp, _Tp>::value || + (std::is_same<_Vp, bool>::value && + std::is_unsigned<_Tp>::value), + ""); template <class, class, class> friend struct __simd_ref_traits; template <class, class> friend class simd; + template <class, class> + friend class simd_mask; + __simd_storage<_Tp, _Abi>* __ptr_; size_t __index_; @@ -875,6 +881,36 @@ !std::is_volatile<_Tp>::value && !std::is_same<_Tp, bool>::value; } +template <size_t __num_bytes> +struct __unsigned_traits {}; + +template <> +struct __unsigned_traits<1> { + using type = uint8_t; +}; + +template <> +struct __unsigned_traits<2> { + using type = uint16_t; +}; + +template <> +struct __unsigned_traits<4> { + using type = uint32_t; +}; + +template <> +struct __unsigned_traits<8> { + using type = uint64_t; +}; + +#if !defined(_LIBCPP_HAS_NO_INT128) +template <> +struct __unsigned_traits<16> { + using type = __uint128_t; +}; +#endif // !defined(_LIBCPP_HAS_NO_INT128) + _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD_ABI @@ -1254,7 +1290,13 @@ // reductions [simd.mask.reductions] template <class _Tp, class _Abi> -bool all_of(const simd_mask<_Tp, _Abi>&) noexcept; +bool all_of(const simd_mask<_Tp, _Abi>& __m) noexcept { + bool __ret = true; + for (size_t __i = 0; __i < __m.size(); __i++) { + __ret &= __m[__i]; + } + return __ret; +} template <class _Tp, class _Abi> bool any_of(const simd_mask<_Tp, _Abi>&) noexcept; template <class _Tp, class _Abi> @@ -1470,6 +1512,9 @@ return simd_size<_Tp, _Abi>::value; } + template <class, class> + friend class simd_mask; + private: __simd_storage<_Tp, _Abi> __s_; @@ -1757,66 +1802,179 @@ } // compares [simd.comparison] - friend mask_type operator==(const simd&, const simd&); - friend mask_type operator!=(const simd&, const simd&); - friend mask_type operator>=(const simd&, const simd&); - friend mask_type operator<=(const simd&, const simd&); - friend mask_type operator>(const simd&, const simd&); - friend mask_type operator<(const simd&, const simd&); + friend mask_type operator==(const simd& __a, const simd& __b) { + mask_type __mask; + for (size_t __i = 0; __i < __a.size(); __i++) { + __mask[__i] = __a[__i] == __b[__i]; + } + return __mask; + } + + friend mask_type operator!=(const simd& __a, const simd& __b) { + mask_type __mask; + for (size_t __i = 0; __i < __a.size(); __i++) { + __mask[__i] = __a[__i] != __b[__i]; + } + return __mask; + } + + friend mask_type operator>=(const simd& __a, const simd& __b) { + mask_type __mask; + for (size_t __i = 0; __i < __a.size(); __i++) { + __mask[__i] = __a[__i] >= __b[__i]; + } + return __mask; + } + + friend mask_type operator<=(const simd& __a, const simd& __b) { + mask_type __mask; + for (size_t __i = 0; __i < __a.size(); __i++) { + __mask[__i] = __a[__i] <= __b[__i]; + } + return __mask; + } + + friend mask_type operator>(const simd& __a, const simd& __b) { + mask_type __mask; + for (size_t __i = 0; __i < __a.size(); __i++) { + __mask[__i] = __a[__i] > __b[__i]; + } + return __mask; + } + + friend mask_type operator<(const simd& __a, const simd& __b) { + mask_type __mask; + for (size_t __i = 0; __i < __a.size(); __i++) { + __mask[__i] = __a[__i] < __b[__i]; + } + return __mask; + } }; // [simd.mask.class] template <class _Tp, class _Abi> -// TODO: implement simd_mask class simd_mask { + using __element_type = typename __unsigned_traits<sizeof(_Tp)>::type; + using __ref_traits = __simd_ref_traits<bool, __element_type, _Abi>; + + simd<__element_type, _Abi> __s_; + + explicit simd_mask(const simd<__element_type, _Abi>& __mask) : __s_(__mask) {} + public: using value_type = bool; - // TODO: this is strawman implementation. Turn it into a proxy type. - using reference = bool&; + using reference = typename __ref_traits::type; using simd_type = simd<_Tp, _Abi>; using abi_type = _Abi; - static constexpr size_t size() noexcept; + + static constexpr size_t size() noexcept { + return simd<__element_type, _Abi>::size(); + } + simd_mask() = default; // broadcast constructor - explicit simd_mask(value_type) noexcept; + explicit simd_mask(value_type __value) noexcept { + for (size_t __i = 0; __i < size(); __i++) { + (*this)[__i] = __value; + } + } // implicit type conversion constructor - template <class _Up> - simd_mask(const simd_mask<_Up, simd_abi::fixed_size<size()>>&) noexcept; + template < + class _Up, + class = typename std::enable_if< + !std::is_void<_Up>::value && + std::is_same<abi_type, simd_abi::fixed_size<size()>>::value>::type> + simd_mask(const simd_mask<_Up, simd_abi::fixed_size<size()>>& __v) noexcept { + for (size_t __i = 0; __i < size(); __i++) { + (*this)[__i] = __v[__i]; + } + } // load constructor - template <class _Flags> - simd_mask(const value_type*, _Flags); + template <class _Flags, class = typename std::enable_if< + is_simd_flag_type<_Flags>::value>::type> + simd_mask(const value_type* __buffer, _Flags) { + for (size_t __i = 0; __i < size(); __i++) { + (*this)[__i] = __buffer[__i]; + } + } // loads [simd.mask.copy] template <class _Flags> - void copy_from(const value_type*, _Flags); + typename std::enable_if<is_simd_flag_type<_Flags>::value>::type + copy_from(const value_type* __buffer, _Flags) { + *this = simd_mask(__buffer, _Flags()); + } + template <class _Flags> - void copy_to(value_type*, _Flags) const; + typename std::enable_if<is_simd_flag_type<_Flags>::value>::type + copy_to(value_type* __buffer, _Flags) const { + for (size_t __i = 0; __i < size(); __i++) { + __buffer[__i] = (*this)[__i]; + } + } // scalar access [simd.mask.subscr] - reference operator[](size_t); - value_type operator[](size_t) const; + reference operator[](size_t __i) { + return __ref_traits::__ref(&__s_.__s_, __i); + } + + value_type operator[](size_t __i) const { return __s_[__i]; } // unary operators [simd.mask.unary] - simd_mask operator!() const noexcept; + simd_mask operator!() const noexcept { return simd_mask(~__s_); } // simd_mask binary operators [simd.mask.binary] - friend simd_mask operator&&(const simd_mask&, const simd_mask&) noexcept; - friend simd_mask operator||(const simd_mask&, const simd_mask&) noexcept; - friend simd_mask operator&(const simd_mask&, const simd_mask&)noexcept; - friend simd_mask operator|(const simd_mask&, const simd_mask&) noexcept; - friend simd_mask operator^(const simd_mask&, const simd_mask&) noexcept; + friend simd_mask operator&&(const simd_mask& __a, + const simd_mask& __b) noexcept { + return __a & __b; + } + + friend simd_mask operator||(const simd_mask& __a, + const simd_mask& __b) noexcept { + return __a | __b; + } + + friend simd_mask operator&(const simd_mask& __a, + const simd_mask& __b) noexcept { + return simd_mask(__a.__s_ & __b.__s_); + } + + friend simd_mask operator|(const simd_mask& __a, + const simd_mask& __b) noexcept { + return simd_mask(__a.__s_ | __b.__s_); + } + + friend simd_mask operator^(const simd_mask& __a, + const simd_mask& __b) noexcept { + return simd_mask(__a.__s_ ^ __b.__s_); + } // simd_mask compound assignment [simd.mask.cassign] - friend simd_mask& operator&=(simd_mask&, const simd_mask&) noexcept; - friend simd_mask& operator|=(simd_mask&, const simd_mask&) noexcept; - friend simd_mask& operator^=(simd_mask&, const simd_mask&) noexcept; + friend simd_mask& operator&=(simd_mask& __a, const simd_mask& __b) noexcept { + return __a = __a & __b; + } + + friend simd_mask& operator|=(simd_mask& __a, const simd_mask& __b) noexcept { + return __a = __a | __b; + } + + friend simd_mask& operator^=(simd_mask& __a, const simd_mask& __b) noexcept { + return __a = __a ^ __b; + } // simd_mask compares [simd.mask.comparison] - friend simd_mask operator==(const simd_mask&, const simd_mask&) noexcept; - friend simd_mask operator!=(const simd_mask&, const simd_mask&) noexcept; + friend simd_mask operator==(const simd_mask& __a, + const simd_mask& __b) noexcept { + return simd_mask(__a.__s_ == __b.__s_); + } + + friend simd_mask operator!=(const simd_mask& __a, + const simd_mask& __b) noexcept { + return simd_mask(__a.__s_ != __b.__s_); + } }; _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits