1 #if !defined(__XOP__) && !defined(__AVX512F__)
2 #include "simd.h"
3 ENTRY(fma_test);
4 #endif
5 
6 #if VEC_SIZE < 16 && !defined(to_bool)
7 # define to_bool(cmp) (!~(cmp)[0])
8 #elif VEC_SIZE == 16 && !defined(__AVX512VL__)
9 # if FLOAT_SIZE == 4
10 #  define to_bool(cmp) __builtin_ia32_vtestcps(cmp, (vec_t){} == 0)
11 # elif FLOAT_SIZE == 8
12 #  define to_bool(cmp) __builtin_ia32_vtestcpd(cmp, (vec_t){} == 0)
13 # endif
14 #elif VEC_SIZE == 32 && !defined(__AVX512VL__)
15 # if FLOAT_SIZE == 4
16 #  define to_bool(cmp) __builtin_ia32_vtestcps256(cmp, (vec_t){} == 0)
17 # elif FLOAT_SIZE == 8
18 #  define to_bool(cmp) __builtin_ia32_vtestcpd256(cmp, (vec_t){} == 0)
19 # endif
20 #endif
21 
22 #ifndef eq
23 # define eq(x, y) to_bool((x) == (y))
24 #endif
25 
26 #if defined(__AVX512F__) && VEC_SIZE > FLOAT_SIZE
27 # if FLOAT_SIZE == 4
28 #  define fmaddsub(x, y, z) BR(vfmaddsubps, _mask, x, y, z, ~0)
29 # elif FLOAT_SIZE == 8
30 #  define fmaddsub(x, y, z) BR(vfmaddsubpd, _mask, x, y, z, ~0)
31 # endif
32 #elif VEC_SIZE == 16
33 # if FLOAT_SIZE == 4
34 #  define addsub(x, y) __builtin_ia32_addsubps(x, y)
35 #  if defined(__FMA4__) || defined(__FMA__)
36 #   define fmaddsub(x, y, z) __builtin_ia32_vfmaddsubps(x, y, z)
37 #  endif
38 # elif FLOAT_SIZE == 8
39 #  define addsub(x, y) __builtin_ia32_addsubpd(x, y)
40 #  if defined(__FMA4__) || defined(__FMA__)
41 #   define fmaddsub(x, y, z) __builtin_ia32_vfmaddsubpd(x, y, z)
42 #  endif
43 # endif
44 #elif VEC_SIZE == 32
45 # if FLOAT_SIZE == 4
46 #  define addsub(x, y) __builtin_ia32_addsubps256(x, y)
47 #  if defined(__FMA4__) || defined(__FMA__)
48 #   define fmaddsub(x, y, z) __builtin_ia32_vfmaddsubps256(x, y, z)
49 #  endif
50 # elif FLOAT_SIZE == 8
51 #  define addsub(x, y) __builtin_ia32_addsubpd256(x, y)
52 #  if defined(__FMA4__) || defined(__FMA__)
53 #   define fmaddsub(x, y, z) __builtin_ia32_vfmaddsubpd256(x, y, z)
54 #  endif
55 # endif
56 #endif
57 
58 #if defined(fmaddsub) && !defined(addsub)
59 # define addsub(x, y) fmaddsub(x, broadcast(1), y)
60 #endif
61 
fma_test(void)62 int fma_test(void)
63 {
64     unsigned int i;
65     vec_t x, y, z, src, inv, one;
66 
67     for ( i = 0; i < ELEM_COUNT; ++i )
68     {
69         src[i] = i + 1;
70         inv[i] = ELEM_COUNT - i;
71         one[i] = 1;
72     }
73 
74     x = (src + one) * inv;
75     y = (src - one) * inv;
76     touch(src);
77     z = inv * src + inv;
78     if ( !eq(x, z) ) return __LINE__;
79 
80     touch(src);
81     z = -inv * src - inv;
82     if ( !eq(-x, z) ) return __LINE__;
83 
84     touch(src);
85     z = inv * src - inv;
86     if ( !eq(y, z) ) return __LINE__;
87 
88     touch(src);
89     z = -inv * src + inv;
90     if ( !eq(-y, z) ) return __LINE__;
91     touch(src);
92 
93     x = src + inv;
94     y = src - inv;
95     touch(inv);
96     z = src * one + inv;
97     if ( !eq(x, z) ) return __LINE__;
98 
99     touch(inv);
100     z = -src * one - inv;
101     if ( !eq(-x, z) ) return __LINE__;
102 
103     touch(inv);
104     z = src * one - inv;
105     if ( !eq(y, z) ) return __LINE__;
106 
107     touch(inv);
108     z = -src * one + inv;
109     if ( !eq(-y, z) ) return __LINE__;
110     touch(inv);
111 
112 #if defined(addsub) && defined(fmaddsub)
113     x = addsub(src * inv, one);
114     y = addsub(src * inv, -one);
115     touch(one);
116     z = fmaddsub(src, inv, one);
117     if ( !eq(x, z) ) return __LINE__;
118 
119     touch(one);
120     z = fmaddsub(src, inv, -one);
121     if ( !eq(y, z) ) return __LINE__;
122     touch(one);
123 
124     x = addsub(src * inv, one);
125     touch(inv);
126     z = fmaddsub(src, inv, one);
127     if ( !eq(x, z) ) return __LINE__;
128 
129     touch(inv);
130     z = fmaddsub(src, inv, -one);
131     if ( !eq(y, z) ) return __LINE__;
132     touch(inv);
133 #endif
134 
135     return 0;
136 }
137