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