]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/experimental/simd/tests/mask_loadstore.cc
libstdc++: Add simd testsuite
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / experimental / simd / tests / mask_loadstore.cc
1 // Copyright (C) 2020 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library. This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
7 // any later version.
8 //
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3. If not see
16 // <http://www.gnu.org/licenses/>.
17
18 #include "bits/verify.h"
19
20 // simd_mask generator functions
21 template <class M>
22 M
23 make_mask(const std::initializer_list<bool>& init)
24 {
25 std::size_t i = 0;
26 M r = {};
27 for (;;)
28 {
29 for (bool x : init)
30 {
31 r[i] = x;
32 if (++i == M::size())
33 {
34 return r;
35 }
36 }
37 }
38 }
39
40 template <class M>
41 M
42 make_alternating_mask()
43 {
44 return make_mask<M>({false, true});
45 }
46
47 template <typename V>
48 void
49 test()
50 {
51 using M = typename V::mask_type;
52 // loads
53 constexpr size_t alignment = 2 * std::experimental::memory_alignment_v<M>;
54 alignas(alignment) bool mem[3 * M::size()];
55 std::memset(mem, 0, sizeof(mem));
56 for (std::size_t i = 1; i < sizeof(mem) / sizeof(*mem); i += 2)
57 {
58 COMPARE(mem[i - 1], false);
59 mem[i] = true;
60 }
61 using std::experimental::element_aligned;
62 using std::experimental::vector_aligned;
63 constexpr size_t stride_alignment
64 = M::size() & 1
65 ? 1
66 : M::size() & 2
67 ? 2
68 : M::size() & 4
69 ? 4
70 : M::size() & 8
71 ? 8
72 : M::size() & 16
73 ? 16
74 : M::size() & 32
75 ? 32
76 : M::size() & 64
77 ? 64
78 : M::size() & 128 ? 128
79 : M::size() & 256 ? 256 : 512;
80 using stride_aligned_t = std::conditional_t<
81 M::size() == stride_alignment, decltype(vector_aligned),
82 std::experimental::overaligned_tag<stride_alignment * sizeof(bool)>>;
83 constexpr stride_aligned_t stride_aligned = {};
84 constexpr auto overaligned = std::experimental::overaligned<alignment>;
85
86 const M alternating_mask = make_alternating_mask<M>();
87
88 M x(&mem[M::size()], stride_aligned);
89 COMPARE(x, M::size() % 2 == 1 ? !alternating_mask : alternating_mask)
90 << x.__to_bitset()
91 << ", alternating_mask: " << alternating_mask.__to_bitset();
92 x = {&mem[1], element_aligned};
93 COMPARE(x, !alternating_mask);
94 x = M{mem, overaligned};
95 COMPARE(x, alternating_mask);
96
97 x.copy_from(&mem[M::size()], stride_aligned);
98 COMPARE(x, M::size() % 2 == 1 ? !alternating_mask : alternating_mask);
99 x.copy_from(&mem[1], element_aligned);
100 COMPARE(x, !alternating_mask);
101 x.copy_from(mem, vector_aligned);
102 COMPARE(x, alternating_mask);
103
104 x = !alternating_mask;
105 where(alternating_mask, x).copy_from(&mem[M::size()], stride_aligned);
106 COMPARE(x, M::size() % 2 == 1 ? !alternating_mask : M{true});
107 x = M(true); // 1111
108 where(alternating_mask, x).copy_from(&mem[1], element_aligned); // load .0.0
109 COMPARE(x, !alternating_mask); // 1010
110 where(alternating_mask, x).copy_from(mem, overaligned); // load .1.1
111 COMPARE(x, M{true}); // 1111
112
113 // stores
114 memset(mem, 0, sizeof(mem));
115 x = M(true);
116 x.copy_to(&mem[M::size()], stride_aligned);
117 std::size_t i = 0;
118 for (; i < M::size(); ++i)
119 {
120 COMPARE(mem[i], false);
121 }
122 for (; i < 2 * M::size(); ++i)
123 {
124 COMPARE(mem[i], true) << "i: " << i << ", x: " << x;
125 }
126 for (; i < 3 * M::size(); ++i)
127 {
128 COMPARE(mem[i], false);
129 }
130 memset(mem, 0, sizeof(mem));
131 x.copy_to(&mem[1], element_aligned);
132 COMPARE(mem[0], false);
133 for (i = 1; i <= M::size(); ++i)
134 {
135 COMPARE(mem[i], true);
136 }
137 for (; i < 3 * M::size(); ++i)
138 {
139 COMPARE(mem[i], false);
140 }
141 memset(mem, 0, sizeof(mem));
142 alternating_mask.copy_to(mem, overaligned);
143 for (i = 0; i < M::size(); ++i)
144 {
145 COMPARE(mem[i], (i & 1) == 1);
146 }
147 for (; i < 3 * M::size(); ++i)
148 {
149 COMPARE(mem[i], false);
150 }
151 x.copy_to(mem, vector_aligned);
152 where(alternating_mask, !x).copy_to(mem, overaligned);
153 for (i = 0; i < M::size(); ++i)
154 {
155 COMPARE(mem[i], i % 2 == 0);
156 }
157 for (; i < 3 * M::size(); ++i)
158 {
159 COMPARE(mem[i], false);
160 }
161 }