Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / native_client / tests / simd / vector_shuffle.cc
1 /*
2  * Copyright (c) 2014 The Native Client Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6
7 /*
8  * Test that the LLVM vector shuffle can be used from C code.
9  * http://clang.llvm.org/docs/LanguageExtensions.html#builtin-shufflevector
10  *
11  * We support the LLVM syntax only, the GCC equivalent isn't supported
12  * by LLVM:
13  * http://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
14  *
15  * This test ensures that the compiler can generate code for vector
16  * shuffles without rejecting it (e.g. with some internal failure or
17  * validation error), and that the output it generates is as specified
18  * by the shuffle builtin's specification. It is fairly exhaustive and
19  * covers many shuffle patterns in an attempt to utilize shuffle
20  * patterns that compilers may choose to lower to better instructions on
21  * certain architectures:
22  *
23  *  - Only the left-hand-side source is used to form the destination.
24  *  - Only the right-hand-side source is used to form the destination.
25  *  - Each index in a source is shuffled to each index in the destination.
26  *  - The destination is identical to one of the inputs.
27  *  - The destination is a broadcast from a single element in a source.
28  *  - The destination interleaves elements from each source.
29  *
30  * The test is performed for all vector sizes and element sizes
31  * currently supported by PNaCl.
32  */
33
34 #include "native_client/src/include/nacl_macros.h"
35
36 #include <cstdint>
37 #include <iostream>
38 #include <sstream>
39 #include <string>
40
41 //  Functions are non-inlined to make sure that nothing gets
42 //  pre-computed at compile time.
43 #define NO_INLINE __attribute__((noinline))
44
45 /*
46  * Basic types that are supported inside vectors.
47  *
48  * TODO(jfb) Handle 64-bit int and double.
49  */
50 typedef int8_t I8;
51 typedef uint8_t U8;
52 typedef int16_t I16;
53 typedef uint16_t U16;
54 typedef int32_t I32;
55 typedef uint32_t U32;
56 typedef float F32;
57
58 // All supported vector types are currently 128-bit wide.
59 #define VEC_BYTES 16
60
61 // Vector types corresponding to each supported basic type.
62 typedef I8 VI8 __attribute__((vector_size(VEC_BYTES)));
63 typedef U8 VU8 __attribute__((vector_size(VEC_BYTES)));
64 typedef I16 VI16 __attribute__((vector_size(VEC_BYTES)));
65 typedef U16 VU16 __attribute__((vector_size(VEC_BYTES)));
66 typedef I32 VI32 __attribute__((vector_size(VEC_BYTES)));
67 typedef U32 VU32 __attribute__((vector_size(VEC_BYTES)));
68 typedef F32 VF32 __attribute__((vector_size(VEC_BYTES)));
69
70 // Reformat some types so they print nicely. Leave others as-is.
71 int32_t format(int8_t v) { return v; }
72 uint32_t format(uint8_t v) { return v; }
73 int32_t format(int16_t v) { return v; }
74 uint32_t format(uint16_t v) { return v; }
75 template <typename T> T format(T v) { return v; }
76
77 template <typename T>
78 NO_INLINE std::string print(const T v) {
79   std::stringstream ss;
80   ss << '{';
81   for (size_t i = 0, e = sizeof(v) / sizeof(v[0]); i != e; ++i)
82     ss << format(v[i]) << (i != e - 1 ? ',' : '}');
83   return ss.str();
84 }
85
86 #define TEST_SHUFFLE(TYPE, LHS, RHS, ...)                                  \
87   do {                                                                     \
88     NACL_COMPILE_TIME_ASSERT(sizeof(TYPE) ==                               \
89                              sizeof(LHS[0])); /* Types must match. */      \
90     NACL_COMPILE_TIME_ASSERT(sizeof(TYPE) ==                               \
91                              sizeof(RHS[0])); /* Types must match. */      \
92     const V##TYPE result = __builtin_shufflevector(LHS, RHS, __VA_ARGS__); \
93     std::cout << #TYPE " __builtin_shufflevector(" << print(LHS) << ", "   \
94               << print(RHS) << ", " #__VA_ARGS__ ") = " << print(result)   \
95               << std::endl;                                                \
96   } while (0)
97
98 // Shuffle BASE into different locations, filling with FILL otherwise.
99 #define TEST_8BIT_SHUFFLE_STEP(T, L, R, BASE, FILL)                         \
100   do {                                                                      \
101     if (FILL != BASE) {                                                     \
102       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL, \
103                    FILL, FILL, FILL, FILL, FILL, FILL, FILL, BASE);         \
104       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL, \
105                    FILL, FILL, FILL, FILL, FILL, FILL, BASE, FILL);         \
106       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL, \
107                    FILL, FILL, FILL, FILL, FILL, BASE, FILL, FILL);         \
108       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL, \
109                    FILL, FILL, FILL, FILL, BASE, FILL, FILL, FILL);         \
110       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL, \
111                    FILL, FILL, FILL, BASE, FILL, FILL, FILL, FILL);         \
112       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL, \
113                    FILL, FILL, BASE, FILL, FILL, FILL, FILL, FILL);         \
114       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL, \
115                    FILL, BASE, FILL, FILL, FILL, FILL, FILL, FILL);         \
116       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL, \
117                    BASE, FILL, FILL, FILL, FILL, FILL, FILL, FILL);         \
118       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, FILL, FILL, FILL, BASE, \
119                    FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL);         \
120       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, FILL, FILL, BASE, FILL, \
121                    FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL);         \
122       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, FILL, BASE, FILL, FILL, \
123                    FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL);         \
124       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, BASE, FILL, FILL, FILL, \
125                    FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL);         \
126       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, BASE, FILL, FILL, FILL, FILL, \
127                    FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL);         \
128       TEST_SHUFFLE(T, L, R, FILL, FILL, BASE, FILL, FILL, FILL, FILL, FILL, \
129                    FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL);         \
130       TEST_SHUFFLE(T, L, R, FILL, BASE, FILL, FILL, FILL, FILL, FILL, FILL, \
131                    FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL);         \
132       TEST_SHUFFLE(T, L, R, BASE, FILL, FILL, FILL, FILL, FILL, FILL, FILL, \
133                    FILL, FILL, FILL, FILL, FILL, FILL, FILL, FILL);         \
134     }                                                                       \
135     /* Broadcast: */                                                        \
136     TEST_SHUFFLE(T, L, R, BASE, BASE, BASE, BASE, BASE, BASE, BASE, BASE,   \
137                  BASE, BASE, BASE, BASE, BASE, BASE, BASE, BASE);           \
138   } while (0)
139
140 #define TEST_8BIT_SHUFFLE(T, L, R)                                            \
141   do {                                                                        \
142     std::cout << "Shuffle L only, ignore R:" << std::endl;                    \
143     TEST_8BIT_SHUFFLE_STEP(T, L, R, 0, 0);                                    \
144     TEST_8BIT_SHUFFLE_STEP(T, L, R, 1, 0);                                    \
145     TEST_8BIT_SHUFFLE_STEP(T, L, R, 2, 0);                                    \
146     TEST_8BIT_SHUFFLE_STEP(T, L, R, 3, 0);                                    \
147     TEST_8BIT_SHUFFLE_STEP(T, L, R, 4, 0);                                    \
148     TEST_8BIT_SHUFFLE_STEP(T, L, R, 5, 0);                                    \
149     TEST_8BIT_SHUFFLE_STEP(T, L, R, 6, 0);                                    \
150     TEST_8BIT_SHUFFLE_STEP(T, L, R, 7, 0);                                    \
151     TEST_8BIT_SHUFFLE_STEP(T, L, R, 8, 0);                                    \
152     TEST_8BIT_SHUFFLE_STEP(T, L, R, 9, 0);                                    \
153     TEST_8BIT_SHUFFLE_STEP(T, L, R, 10, 0);                                   \
154     TEST_8BIT_SHUFFLE_STEP(T, L, R, 11, 0);                                   \
155     TEST_8BIT_SHUFFLE_STEP(T, L, R, 12, 0);                                   \
156     TEST_8BIT_SHUFFLE_STEP(T, L, R, 13, 0);                                   \
157     TEST_8BIT_SHUFFLE_STEP(T, L, R, 14, 0);                                   \
158     TEST_8BIT_SHUFFLE_STEP(T, L, R, 15, 0);                                   \
159     std::cout << "Shuffle R only, ignore L:" << std::endl;                    \
160     TEST_8BIT_SHUFFLE_STEP(T, L, R, 16, 16);                                  \
161     TEST_8BIT_SHUFFLE_STEP(T, L, R, 17, 16);                                  \
162     TEST_8BIT_SHUFFLE_STEP(T, L, R, 18, 16);                                  \
163     TEST_8BIT_SHUFFLE_STEP(T, L, R, 19, 16);                                  \
164     TEST_8BIT_SHUFFLE_STEP(T, L, R, 20, 16);                                  \
165     TEST_8BIT_SHUFFLE_STEP(T, L, R, 21, 16);                                  \
166     TEST_8BIT_SHUFFLE_STEP(T, L, R, 22, 16);                                  \
167     TEST_8BIT_SHUFFLE_STEP(T, L, R, 23, 16);                                  \
168     TEST_8BIT_SHUFFLE_STEP(T, L, R, 24, 16);                                  \
169     TEST_8BIT_SHUFFLE_STEP(T, L, R, 25, 16);                                  \
170     TEST_8BIT_SHUFFLE_STEP(T, L, R, 26, 16);                                  \
171     TEST_8BIT_SHUFFLE_STEP(T, L, R, 27, 16);                                  \
172     TEST_8BIT_SHUFFLE_STEP(T, L, R, 28, 16);                                  \
173     TEST_8BIT_SHUFFLE_STEP(T, L, R, 29, 16);                                  \
174     TEST_8BIT_SHUFFLE_STEP(T, L, R, 30, 16);                                  \
175     TEST_8BIT_SHUFFLE_STEP(T, L, R, 31, 16);                                  \
176     std::cout << "Identity:" << std::endl;                                    \
177     TEST_SHUFFLE(T, L, R, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,   \
178                  15);                                                         \
179     TEST_SHUFFLE(T, L, R, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, \
180                  29, 30, 31);                                                 \
181     std::cout << "Interleave:" << std::endl;                                  \
182     TEST_SHUFFLE(T, L, R, 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, \
183                  23);                                                         \
184     TEST_SHUFFLE(T, L, R, 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14,   \
185                  30, 15, 31);                                                 \
186   } while (0)
187
188 // Shuffle BASE into different locations, filling with FILL otherwise.
189 #define TEST_16BIT_SHUFFLE_STEP(T, L, R, BASE, FILL)                         \
190   do {                                                                       \
191     if (FILL != BASE) {                                                      \
192       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, FILL, FILL, FILL, BASE); \
193       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, FILL, FILL, BASE, FILL); \
194       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, FILL, BASE, FILL, FILL); \
195       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, FILL, BASE, FILL, FILL, FILL); \
196       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, BASE, FILL, FILL, FILL, FILL); \
197       TEST_SHUFFLE(T, L, R, FILL, FILL, BASE, FILL, FILL, FILL, FILL, FILL); \
198       TEST_SHUFFLE(T, L, R, FILL, BASE, FILL, FILL, FILL, FILL, FILL, FILL); \
199       TEST_SHUFFLE(T, L, R, BASE, FILL, FILL, FILL, FILL, FILL, FILL, FILL); \
200     }                                                                        \
201     /* Broadcast: */                                                         \
202     TEST_SHUFFLE(T, L, R, BASE, BASE, BASE, BASE, BASE, BASE, BASE, BASE);   \
203   } while (0)
204
205 #define TEST_16BIT_SHUFFLE(T, L, R)                        \
206   do {                                                     \
207     std::cout << "Shuffle L only, ignore R:" << std::endl; \
208     TEST_16BIT_SHUFFLE_STEP(T, L, R, 0, 0);                \
209     TEST_16BIT_SHUFFLE_STEP(T, L, R, 1, 0);                \
210     TEST_16BIT_SHUFFLE_STEP(T, L, R, 2, 0);                \
211     TEST_16BIT_SHUFFLE_STEP(T, L, R, 3, 0);                \
212     TEST_16BIT_SHUFFLE_STEP(T, L, R, 4, 0);                \
213     TEST_16BIT_SHUFFLE_STEP(T, L, R, 5, 0);                \
214     TEST_16BIT_SHUFFLE_STEP(T, L, R, 6, 0);                \
215     TEST_16BIT_SHUFFLE_STEP(T, L, R, 7, 0);                \
216     std::cout << "Shuffle R only, ignore L:" << std::endl; \
217     TEST_16BIT_SHUFFLE_STEP(T, L, R, 8, 8);                \
218     TEST_16BIT_SHUFFLE_STEP(T, L, R, 9, 8);                \
219     TEST_16BIT_SHUFFLE_STEP(T, L, R, 10, 8);               \
220     TEST_16BIT_SHUFFLE_STEP(T, L, R, 11, 8);               \
221     TEST_16BIT_SHUFFLE_STEP(T, L, R, 12, 8);               \
222     TEST_16BIT_SHUFFLE_STEP(T, L, R, 13, 8);               \
223     TEST_16BIT_SHUFFLE_STEP(T, L, R, 14, 8);               \
224     TEST_16BIT_SHUFFLE_STEP(T, L, R, 15, 8);               \
225     std::cout << "Identity:" << std::endl;                 \
226     TEST_SHUFFLE(T, L, R, 0, 1, 2, 3, 4, 5, 6, 7);         \
227     TEST_SHUFFLE(T, L, R, 8, 9, 10, 11, 12, 13, 14, 15);   \
228     std::cout << "Interleave:" << std::endl;               \
229     TEST_SHUFFLE(T, L, R, 0, 8, 1, 9, 2, 10, 3, 11);       \
230     TEST_SHUFFLE(T, L, R, 4, 12, 5, 13, 6, 14, 7, 15);     \
231   } while (0)
232
233 // Shuffle BASE into different locations, filling with FILL otherwise.
234 #define TEST_32BIT_SHUFFLE_STEP(T, L, R, BASE, FILL) \
235   do {                                               \
236     if (FILL != BASE) {                              \
237       TEST_SHUFFLE(T, L, R, FILL, FILL, FILL, BASE); \
238       TEST_SHUFFLE(T, L, R, FILL, FILL, BASE, FILL); \
239       TEST_SHUFFLE(T, L, R, FILL, BASE, FILL, FILL); \
240       TEST_SHUFFLE(T, L, R, BASE, FILL, FILL, FILL); \
241     }                                                \
242     /* Broadcast: */                                 \
243     TEST_SHUFFLE(T, L, R, BASE, BASE, BASE, BASE);   \
244   } while (0)
245
246 #define TEST_32BIT_SHUFFLE(T, L, R)                        \
247   do {                                                     \
248     std::cout << "Shuffle L only, ignore R:" << std::endl; \
249     TEST_32BIT_SHUFFLE_STEP(T, L, R, 0, 0);                \
250     TEST_32BIT_SHUFFLE_STEP(T, L, R, 1, 0);                \
251     TEST_32BIT_SHUFFLE_STEP(T, L, R, 2, 0);                \
252     TEST_32BIT_SHUFFLE_STEP(T, L, R, 3, 0);                \
253     std::cout << "Shuffle R only, ignore L:" << std::endl; \
254     TEST_32BIT_SHUFFLE_STEP(T, L, R, 4, 4);                \
255     TEST_32BIT_SHUFFLE_STEP(T, L, R, 5, 4);                \
256     TEST_32BIT_SHUFFLE_STEP(T, L, R, 6, 4);                \
257     TEST_32BIT_SHUFFLE_STEP(T, L, R, 7, 4);                \
258     std::cout << "Identity:" << std::endl;                 \
259     TEST_SHUFFLE(T, L, R, 0, 1, 2, 3);                     \
260     TEST_SHUFFLE(T, L, R, 4, 5, 6, 7);                     \
261     std::cout << "Interleave:" << std::endl;               \
262     TEST_SHUFFLE(T, L, R, 0, 4, 1, 5);                     \
263     TEST_SHUFFLE(T, L, R, 2, 6, 3, 7);                     \
264   } while (0)
265
266 // Vector values used in tests.
267 VI8 vi8[2];
268 VU8 vu8[2];
269 VI16 vi16[2];
270 VU16 vu16[2];
271 VI32 vi32[2];
272 VU32 vu32[2];
273 VF32 vf32[2];
274 NO_INLINE void init(void) {
275   vi8[0] = (VI8) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
276   vi8[1] =
277       (VI8) {17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32};
278
279   vu8[0] = (VU8) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
280   vu8[1] =
281       (VU8) {17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32};
282
283   vi16[0] = (VI16) {1, 2, 3, 4, 5, 6, 7, 8};
284   vi16[1] = (VI16) {9, 10, 11, 12, 13, 14, 15, 16};
285
286   vu16[0] = (VU16) {1, 2, 3, 4, 5, 6, 7, 8};
287   vu16[1] = (VU16) {9, 10, 11, 12, 13, 14, 15, 16};
288
289   vi32[0] = (VI32) {1, 2, 3, 4};
290   vi32[1] = (VI32) {5, 6, 7, 8};
291
292   vu32[0] = (VU32) {1, 2, 3, 4};
293   vu32[1] = (VU32) {5, 6, 7, 8};
294
295   vf32[0] = (VF32) {1, 2, 3, 4};
296   vf32[1] = (VF32) {5, 6, 7, 8};
297 }
298
299 NO_INLINE void test(void) {
300   std::cout << "8 bit shuffles:" << std::endl;
301   TEST_8BIT_SHUFFLE(I8, vi8[0], vi8[1]);
302   TEST_8BIT_SHUFFLE(U8, vu8[0], vu8[1]);
303   std::cout << "16 bit shuffles:" << std::endl;
304   TEST_16BIT_SHUFFLE(I16, vi16[0], vi16[1]);
305   TEST_16BIT_SHUFFLE(U16, vu16[0], vu16[1]);
306   std::cout << "32 bit shuffles:" << std::endl;
307   TEST_32BIT_SHUFFLE(I32, vi32[0], vi32[1]);
308   TEST_32BIT_SHUFFLE(U32, vu32[0], vu32[1]);
309   TEST_32BIT_SHUFFLE(F32, vf32[0], vf32[1]);
310 }
311
312 int main(void) {
313   init();
314   test();
315
316   return 0;
317 }