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

Reply via email to