1This directory contains executable tests for ARM/AArch64 Advanced SIMD
2(Neon) intrinsics.
3
4It is meant to cover execution cases of all the Advanced SIMD
5intrinsics, but does not scan the generated assembler code.
6
7The general framework is composed as follows:
8- advsimd-intrinsics.exp: main dejagnu driver
9- *.c: actual tests, generally one per intrinsinc family
10- arm-neon-ref.h: contains macro definitions to save typing in actual
11 test files
12- compute-ref-data.h: contains input vectors definitions
13- *.inc: generic tests, shared by several families of intrinsics. For
14 instance, unary or binary operators
15
16A typical .c test file starts with the following contents (look at
17vld1.c and vaba.c for sample cases):
18#include <arm_neon.h>
19#include "arm-neon-ref.h"
20#include "compute-ref-data.h"
21
22Then, definitions of expected results, based on common input values,
23as defined in compute-ref-data.h.
24For example:
25VECT_VAR_DECL(expected,int,16,4) [] = { 0x16, 0x17, 0x18, 0x19 };
26defines the expected results of an operator generating int16x4 values.
27
28The common input values defined in compute-ref-data.h have been chosen
29to avoid corner-case values for most operators, yet exposing negative
30values for signed operators. For this reason, their range is also
31limited. For instance, the initialization of buffer_int16x4 will be
32{ -16, -15, -14, -13 }.
33
34The initialization of floating-point values is done via hex notation,
35to avoid potential rounding problems.
36
37To test special values and corner cases, specific initialization
38values should be used in dedicated tests, to ensure proper coverage.
39An example of this is vshl.
40
41When a variant of an intrinsic is not available, its expected result
42should be defined to the value of CLEAN_PATTERN_8 as defined in
43arm-neon-ref.h. For example:
44VECT_VAR_DECL(expected,int,64,1) [] = { 0x3333333333333333 };
45if the given intrinsic has no variant producing an int64x1 result,
46like the vcmp family (eg. vclt).
47
48This is because the helper function (check_results(), defined in
49arm-neon-ref.h), iterates over all the possible variants, to save
50typing in each individual test file. Alternatively, one can directly
51call the CHECK/CHECK_FP macros to check only a few expected results
52(see vabs.c for an example).
53
54Then, define the TEST_MSG string, which will be used when reporting errors.
55
56Next, define the function performing the actual tests, in general
57relying on the helpers provided by arm-neon-ref.h, which means:
58
59* declare necessary vectors of suitable types: using
60 DECL_VARIABLE_ALL_VARIANTS when all variants are supported, or the
61 relevant of subset calls to DECL_VARIABLE.
62
63* call clean_results() to initialize the 'results' buffers.
64
65* initialize the input vectors, using VLOAD, VDUP or VSET_LANE (vld*
66 tests do not need this step, since their actual purpose is to
67 initialize vectors).
68
69* execute the intrinsic on relevant variants, for instance using
70 TEST_MACRO_ALL_VARIANTS_2_5.
71
72* call check_results() to check that the results match the expected
73 values.
74
75A template test file could be:
76=================================================================
77#include <arm_neon.h>
78#include "arm-neon-ref.h"
79#include "compute-ref-data.h"
80
81/* Expected results. */
82VECT_VAR_DECL(expected,int,8,8) [] = { 0xf6, 0xf7, 0xf8, 0xf9,
83 0xfa, 0xfb, 0xfc, 0xfd };
84/* and as many others as necessary. */
85
86#define TEST_MSG "VMYINTRINSIC"
87void exec_myintrinsic (void)
88{
89 /* my test: v4=vmyintrinsic(v1,v2,v3), then store the result. */
90#define TEST_VMYINTR(Q, T1, T2, W, N) \
91 VECT_VAR(vector_res, T1, W, N) = \
92 vmyintr##Q##_##T2##W(VECT_VAR(vector1, T1, W, N), \
93 VECT_VAR(vector2, T1, W, N), \
94 VECT_VAR(vector3, T1, W, N)); \
95 vst1##Q##_##T2##W(VECT_VAR(result, T1, W, N), VECT_VAR(vector_res, T1, W, N))
96
97#define DECL_VMYINTR_VAR(VAR) \
98 DECL_VARIABLE(VAR, int, 8, 8);
99/* And as many others as necessary. */
100
101 DECL_VMYINTR_VAR(vector1);
102 DECL_VMYINTR_VAR(vector2);
103 DECL_VMYINTR_VAR(vector3);
104 DECL_VMYINTR_VAR(vector_res);
105
106 clean_results ();
107
108 /* Initialize input "vector1" from "buffer". */
109 VLOAD(vector1, buffer, , int, s, 8, 8);
110/* And as many others as necessary. */
111
112 /* Choose init value arbitrarily. */
113 VDUP(vector2, , int, s, 8, 8, 1);
114/* And as many others as necessary. */
115
116 /* Choose init value arbitrarily. */
117 VDUP(vector3, , int, s, 8, 8, -5);
118/* And as many others as necessary. */
119
120 /* Execute the tests. */
121 TEST_VMYINTR(, int, s, 8, 8);
122/* And as many others as necessary. */
123
124 check_results (TEST_MSG, "");
125}
126
127int main (void)
128{
129 exec_vmyintrinsic ();
130 return 0;
131}
132=================================================================
133