63bce3c895f676d31b270d7ff96d2de699911ee7
[alexxy/gromacs.git] / src / gromacs / simd / impl_ibm_qpx / impl_ibm_qpx.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2014, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35
36 #ifndef GMX_SIMD_IMPLEMENTATION_IBM_QPX_H
37 #define GMX_SIMD_IMPLEMENTATION_IBM_QPX_H
38
39 #include <math.h>
40 #ifdef __clang__
41 #include <qpxmath.h>
42 #endif
43
44 /* IBM QPX SIMD instruction wrappers
45  *
46  * Please see documentation in gromacs/simd/simd.h for the available
47  * defines.
48  */
49 /* Capability definitions for IBM QPX */
50 #define GMX_SIMD_HAVE_FLOAT
51 #define GMX_SIMD_HAVE_DOUBLE
52 #define GMX_SIMD_HAVE_HARDWARE
53 #undef  GMX_SIMD_HAVE_STOREU
54 #undef  GMX_SIMD_HAVE_STOREU
55 #undef  GMX_SIMD_HAVE_LOGICAL
56 #define GMX_SIMD_HAVE_FMA
57 #undef  GMX_SIMD_HAVE_FRACTION
58 #define GMX_SIMD_HAVE_FINT32
59 #undef  GMX_SIMD_HAVE_FINT32_EXTRACT
60 #undef  GMX_SIMD_HAVE_FINT32_LOGICAL
61 #undef  GMX_SIMD_HAVE_FINT32_ARITHMETICS
62 #define GMX_SIMD_HAVE_DINT32
63 #undef  GMX_SIMD_HAVE_DINT32_EXTRACT
64 #undef  GMX_SIMD_HAVE_DINT32_LOGICAL
65 #undef  GMX_SIMD_HAVE_DINT32_ARITHMETICS
66 #define GMX_SIMD4_HAVE_FLOAT
67 #define GMX_SIMD4_HAVE_DOUBLE
68
69 /* Implementation details */
70 #define GMX_SIMD_FLOAT_WIDTH         4
71 #define GMX_SIMD_DOUBLE_WIDTH        4
72 #define GMX_SIMD_FINT32_WIDTH        4
73 #define GMX_SIMD_DINT32_WIDTH        4
74 #define GMX_SIMD_RSQRT_BITS         14
75 #define GMX_SIMD_RCP_BITS           14
76
77 /****************************************************
78  *      SINGLE PRECISION SIMD IMPLEMENTATION        *
79  ****************************************************/
80 #define gmx_simd_float_t          vector4double
81 #ifdef NDEBUG
82 #    define gmx_simd_load_f(m)    vec_ld(0, (float *)(m))
83 #    define gmx_simd_store_f(m, a) vec_st(a, 0, (float *)(m))
84 #else
85 #    define gmx_simd_load_f(m)    vec_lda(0, (float *)(m))
86 #    define gmx_simd_store_f(m, a) vec_sta(a, 0, (float *)(m))
87 #endif
88 #    define gmx_simd_load1_f(m)   vec_lds(0, (float *)(m))
89 #define gmx_simd_set1_f(x)        vec_splats(x)
90 /* No support for unaligned load/store */
91 #define gmx_simd_setzero_f        gmx_simd_setzero_ibm_qpx
92 #define gmx_simd_add_f(a, b)       vec_add(a, b)
93 #define gmx_simd_sub_f(a, b)       vec_sub(a, b)
94 #define gmx_simd_mul_f(a, b)       vec_mul(a, b)
95 #define gmx_simd_fmadd_f(a, b, c)   vec_madd(a, b, c)
96 #define gmx_simd_fmsub_f(a, b, c)   vec_msub(a, b, c)
97 /* IBM uses an alternative FMA definition, so -a*b+c=-(a*b-c) is "nmsub" */
98 #define gmx_simd_fnmadd_f(a, b, c)  vec_nmsub(a, b, c)
99 /* IBM uses an alternative FMA definition, so -a*b-c=-(a*b+c) is "nmadd" */
100 #define gmx_simd_fnmsub_f(a, b, c)  vec_nmadd(a, b, c)
101 /* gmx_simd_and_f not supported - no bitwise logical ops */
102 /* gmx_simd_andnot_f not supported - no bitwise logical ops */
103 /* gmx_simd_or_f not supported - no bitwise logical ops */
104 /* gmx_simd_xor_f not supported - no bitwise logical ops */
105 #define gmx_simd_rsqrt_f(a)       vec_rsqrte(a)
106 #define gmx_simd_rcp_f(a)         vec_re(a)
107 #define gmx_simd_fabs_f(a)        vec_abs(a)
108 #define gmx_simd_fneg_f           gmx_simd_fneg_ibm_qpx
109 #define gmx_simd_max_f(a, b)       vec_sel(b, a, vec_sub(a, b))
110 #define gmx_simd_min_f(a, b)       vec_sel(b, a, vec_sub(b, a))
111 /* Note: It is critical to use vec_cfid(vec_ctid(a)) for the implementation
112  * of gmx_simd_round_f(), since vec_round() does not adhere to the FP control
113  * word rounding scheme. We rely on float-to-float and float-to-integer
114  * rounding being the same for half-way values in a few algorithms.
115  */
116 #define gmx_simd_round_f(a)       vec_cfid(vec_ctid(a))
117 #define gmx_simd_trunc_f(a)       vec_trunc(a)
118 #define gmx_simd_fraction_f(x)    vec_sub(x, vec_trunc(x))
119 #define gmx_simd_get_exponent_f(a) gmx_simd_get_exponent_ibm_qpx(a)
120 #define gmx_simd_get_mantissa_f(a) gmx_simd_get_mantissa_ibm_qpx(a)
121 #define gmx_simd_set_exponent_f(a) gmx_simd_set_exponent_ibm_qpx(a)
122 /* integer datatype corresponding to float: gmx_simd_fint32_t */
123 #define gmx_simd_fint32_t         vector4double
124 #ifdef NDEBUG
125 #    define gmx_simd_load_fi(m)   vec_ldia(0, (int *)(m))
126 #else
127 #    define gmx_simd_load_fi(m)   vec_ldiaa(0, (int *)(m))
128 #endif
129 #define gmx_simd_set1_fi(i)       gmx_simd_set1_int_ibm_qpx(i)
130 #define gmx_simd_store_fi(m, x)    vec_st(x, 0, (int *)(m))
131 #define gmx_simd_setzero_fi       gmx_simd_setzero_ibm_qpx
132 #define gmx_simd_cvt_f2i(a)       vec_ctiw(a)
133 #define gmx_simd_cvtt_f2i(a)      vec_ctiwz(a)
134 #define gmx_simd_cvt_i2f(a)       vec_cfid(a)
135 /* Integer simd extract not available */
136 /* Integer logical ops on gmx_simd_fint32_t not supported */
137 /* Integer arithmetic ops on gmx_simd_fint32_t not supported */
138 /* Boolean & comparison operations on gmx_simd_float_t */
139 #define gmx_simd_fbool_t          vector4double
140 #define gmx_simd_cmpeq_f(a, b)     vec_cmpeq(a, b)
141 #define gmx_simd_cmplt_f(a, b)     vec_cmplt((a), (b))
142 #define gmx_simd_cmple_f(a, b)     gmx_simd_or_fb(vec_cmpeq(a, b), vec_cmplt(a, b))
143 #define gmx_simd_and_fb(a, b)      vec_and(a, b)
144 #define gmx_simd_or_fb(a, b)       vec_or(a, b)
145 #define gmx_simd_anytrue_fb(a)    gmx_simd_anytrue_bool_ibm_qpx(a)
146 #define gmx_simd_blendzero_f(a, sel) vec_sel(vec_splats(0.0), a, sel)
147 #define gmx_simd_blendnotzero_f(a, sel) vec_sel(a, vec_splats(0.0), sel)
148 #define gmx_simd_blendv_f(a, b, sel)  vec_sel(a, b, sel)
149 #define gmx_simd_reduce_f(a)       gmx_simd_reduce_ibm_qpx(a)
150
151
152 /* Boolean & comparison operations on gmx_simd_fint32_t not supported */
153 /* Conversions between different booleans not supported */
154
155 static __attribute__((always_inline)) vector4double
156 gmx_simd_fneg_ibm_qpx(vector4double a)
157 {
158     return vec_neg(a);
159 }
160 /****************************************************
161  *      DOUBLE PRECISION SIMD IMPLEMENTATION        *
162  ****************************************************/
163 #define gmx_simd_double_t         vector4double
164 #ifdef NDEBUG
165 #    define gmx_simd_load_d(m)    vec_ld(0, (double *)(m))
166 #    define gmx_simd_store_d(m, a) vec_st(a, 0, (double *)(m))
167 #else
168 #    define gmx_simd_load_d(m)    vec_lda(0, (double *)(m))
169 #    define gmx_simd_store_d(m, a) vec_sta(a, 0, (double *)(m))
170 #endif
171 #    define gmx_simd_load1_d(m)   vec_lds(0, (double *)(m))
172 #define gmx_simd_set1_d(x)        vec_splats(x)
173 /* No support for unaligned load/store */
174 #define gmx_simd_setzero_d        gmx_simd_setzero_ibm_qpx
175 #define gmx_simd_add_d(a, b)       vec_add(a, b)
176 #define gmx_simd_sub_d(a, b)       vec_sub(a, b)
177 #define gmx_simd_mul_d(a, b)       vec_mul(a, b)
178 #define gmx_simd_fmadd_d(a, b, c)   vec_madd(a, b, c)
179 #define gmx_simd_fmsub_d(a, b, c)   vec_msub(a, b, c)
180 /* IBM uses an alternative FMA definition, so -a*b+c=-(a*b-c) is "nmsub" */
181 #define gmx_simd_fnmadd_d(a, b, c)  vec_nmsub(a, b, c)
182 /* IBM uses an alternative FMA definition, so -a*b-c=-(a*b+c) is "nmadd" */
183 #define gmx_simd_fnmsub_d(a, b, c)  vec_nmadd(a, b, c)
184 /* gmx_simd_and_d not supported - no bitwise logical ops */
185 /* gmx_simd_andnot_d not supported - no bitwise logical ops */
186 /* gmx_simd_or_d not supported - no bitwise logical ops */
187 /* gmx_simd_xor_d not supported - no bitwise logical ops */
188 #define gmx_simd_rsqrt_d(a)       vec_rsqrte(a)
189 #define gmx_simd_rcp_d(a)         vec_re(a)
190 #define gmx_simd_fabs_d(a)        vec_abs(a)
191 #define gmx_simd_fneg_d           gmx_simd_fneg_ibm_qpx
192 #define gmx_simd_max_d(a, b)       vec_sel(b, a, vec_sub(a, b))
193 #define gmx_simd_min_d(a, b)       vec_sel(b, a, vec_sub(b, a))
194 /* Note: It is critical to use vec_cfid(vec_ctid(a)) for the implementation
195  * of gmx_simd_round_f(), since vec_round() does not adhere to the FP control
196  * word rounding scheme. We rely on float-to-float and float-to-integer
197  * rounding being the same for half-way values in a few algorithms.
198  */
199 #define gmx_simd_round_d(a)       vec_cfid(vec_ctid(a))
200 #define gmx_simd_trunc_d(a)       vec_trunc(a)
201 #define gmx_simd_fraction_d(x)    vec_sub(x, vec_trunc(x))
202 #define gmx_simd_get_exponent_d(a) gmx_simd_get_exponent_ibm_qpx(a)
203 #define gmx_simd_get_mantissa_d(a) gmx_simd_get_mantissa_ibm_qpx(a)
204 #define gmx_simd_set_exponent_d(a) gmx_simd_set_exponent_ibm_qpx(a)
205 /* integer datatype corresponding to double: gmx_simd_dint32_t */
206 #define gmx_simd_dint32_t         vector4double
207 #ifdef NDEBUG
208 #    define gmx_simd_load_di(m)   vec_ldia(0, (int *)(m))
209 #else
210 #    define gmx_simd_load_di(m)   vec_ldiaa(0, (int *)(m))
211 #endif
212 #define gmx_simd_set1_di(i)       gmx_simd_set1_int_ibm_qpx(i)
213 #define gmx_simd_store_di(m, x)   vec_st(x, 0, (int *)(m))
214 #define gmx_simd_setzero_di       gmx_simd_setzero_ibm_qpx
215 #define gmx_simd_cvt_d2i(a)       vec_ctiw(a)
216 #define gmx_simd_cvtt_d2i(a)      vec_ctiwz(a)
217 #define gmx_simd_cvt_i2d(a)       vec_cfid(a)
218 /* Integer simd extract not available */
219 /* Integer logical ops on gmx_simd_dint32_t not supported */
220 /* Integer arithmetic ops on gmx_simd_dint32_t not supported */
221 /* Boolean & comparison operations on gmx_simd_double_t */
222 #define gmx_simd_dbool_t          vector4double
223 #define gmx_simd_cmpeq_d(a, b)     vec_cmpeq(a, b)
224 #define gmx_simd_cmplt_d(a, b)     vec_cmplt((a), (b))
225 #define gmx_simd_cmple_d(a, b)     gmx_simd_or_fb(vec_cmpeq(a, b), vec_cmplt(a, b))
226 #define gmx_simd_and_db(a, b)      vec_and(a, b)
227 #define gmx_simd_or_db(a, b)       vec_or(a, b)
228 #define gmx_simd_anytrue_db(a)    gmx_simd_anytrue_bool_ibm_qpx(a)
229 #define gmx_simd_blendzero_d(a, sel) vec_sel(vec_splats(0.0), a, sel)
230 #define gmx_simd_blendnotzero_d(a, sel) vec_sel(a, vec_splats(0.0), sel)
231 #define gmx_simd_blendv_d(a, b, sel)  vec_sel(a, b, sel)
232 #define gmx_simd_reduce_d(a)      gmx_simd_reduce_ibm_qpx(a)
233
234 /* Boolean & comparison operations on gmx_simd_dint32_t not supported */
235 /* Conversions between different booleans not supported */
236
237
238 /****************************************************
239  * IMPLEMENTATION HELPER FUNCTIONS                  *
240  ****************************************************/
241 static __attribute__((always_inline)) vector4double gmx_simdcall
242 gmx_simd_setzero_ibm_qpx(void)
243 {
244     return vec_splats(0.0);
245 }
246
247 static __attribute__((always_inline)) vector4double gmx_simdcall
248 gmx_simd_get_exponent_ibm_qpx(vector4double x)
249 {
250     const gmx_int64_t    expmask   = 0x7ff0000000000000LL;
251     const gmx_int64_t    expbase   = 1023;
252     gmx_int64_t          idata[4] __attribute__((aligned(32)));
253
254     /* Store to memory */
255     vec_st(x, 0, idata);
256     /* Perform integer arithmetics in general registers. */
257     idata[0] = ((idata[0] & expmask) >> 52) - expbase;
258     idata[1] = ((idata[1] & expmask) >> 52) - expbase;
259     idata[2] = ((idata[2] & expmask) >> 52) - expbase;
260     idata[3] = ((idata[3] & expmask) >> 52) - expbase;
261     /* Reload from memory */
262     return vec_cfid(vec_ld(0, idata));
263 }
264
265 static __attribute__((always_inline)) vector4double gmx_simdcall
266 gmx_simd_get_mantissa_ibm_qpx(vector4double x)
267 {
268     const gmx_int64_t    exp_and_sign_mask = 0xfff0000000000000LL;
269     const gmx_int64_t    ione              = 0x3ff0000000000000LL;
270     gmx_int64_t          idata[4] __attribute__((aligned(32)));
271
272     /* Store to memory */
273     vec_st(x, 0, idata);
274     /* Perform integer arithmetics in general registers. */
275     idata[0] = (idata[0] & (~exp_and_sign_mask)) | ione;
276     idata[1] = (idata[1] & (~exp_and_sign_mask)) | ione;
277     idata[2] = (idata[2] & (~exp_and_sign_mask)) | ione;
278     idata[3] = (idata[3] & (~exp_and_sign_mask)) | ione;
279     /* Reload from memory */
280     return vec_ld(0, idata);
281 }
282
283 static __attribute__((always_inline)) vector4double gmx_simdcall
284 gmx_simd_set_exponent_ibm_qpx(vector4double x)
285 {
286     const gmx_int64_t    expbase = 1023;
287     gmx_int64_t          idata[4] __attribute__((aligned(32)));
288
289     /* Store to memory for shifts. It is REALLY critical that we use the same
290      * rounding mode as for gmx_simd_round_r() here. In particular, for QPX
291      * this means we implement gmx_simd_round_r(a) as vec_cfid(vec_ctid(a)),
292      * since vec_round() uses a different rounding scheme.
293      */
294     vec_st(vec_ctid(x), 0, idata);
295     /* Perform integer arithmetics in general registers. */
296     idata[0] = (idata[0] + expbase) << 52;
297     idata[1] = (idata[1] + expbase) << 52;
298     idata[2] = (idata[2] + expbase) << 52;
299     idata[3] = (idata[3] + expbase) << 52;
300     /* Reload from memory */
301     return vec_ld(0, idata);
302 }
303
304 static __attribute__((always_inline)) double gmx_simdcall
305 gmx_simd_reduce_ibm_qpx(vector4double x)
306 {
307     vector4double y = vec_sldw(x, x, 2);
308     vector4double z;
309
310     y = vec_add(y, x);
311     z = vec_sldw(y, y, 1);
312     y = vec_add(y, z);
313     return vec_extract(y, 0);
314 }
315
316 static __attribute__((always_inline)) vector4double gmx_simdcall
317 gmx_simd_set1_int_ibm_qpx(int i)
318 {
319     int idata[4] __attribute__((aligned(32)));
320
321     idata[0] = i;
322
323     /* Reload from memory */
324     return vec_splat(vec_ldia(0, idata), 0);
325 }
326
327 /* This works in both single and double */
328 static __attribute__((always_inline)) int gmx_simdcall
329 gmx_simd_anytrue_bool_ibm_qpx(vector4double a)
330 {
331     vector4double b = vec_sldw(a, a, 2);
332
333     a = vec_or(a, b);
334     b = vec_sldw(a, a, 1);
335     a = vec_or(a, b);
336     return (vec_extract(a, 0) > 0);
337 }
338
339 /* QPX is already 4-wide both in single and double, so just reuse for SIMD4 */
340
341 /* SINGLE */
342 #define gmx_simd4_float_t                gmx_simd_float_t
343 #define gmx_simd4_load_f                 gmx_simd_load_f
344 #define gmx_simd4_load1_f                gmx_simd_load1_f
345 #define gmx_simd4_set1_f                 gmx_simd_set1_f
346 #define gmx_simd4_store_f                gmx_simd_store_f
347 #define gmx_simd4_loadu_f                gmx_simd_loadu_f
348 #define gmx_simd4_storeu_f               gmx_simd_storeu_f
349 #define gmx_simd4_setzero_f              gmx_simd_setzero_f
350 #define gmx_simd4_add_f                  gmx_simd_add_f
351 #define gmx_simd4_sub_f                  gmx_simd_sub_f
352 #define gmx_simd4_mul_f                  gmx_simd_mul_f
353 #define gmx_simd4_fmadd_f                gmx_simd_fmadd_f
354 #define gmx_simd4_fmsub_f                gmx_simd_fmsub_f
355 #define gmx_simd4_fnmadd_f               gmx_simd_fnmadd_f
356 #define gmx_simd4_fnmsub_f               gmx_simd_fnmsub_f
357 #define gmx_simd4_and_f                  gmx_simd_and_f
358 #define gmx_simd4_andnot_f               gmx_simd_andnot_f
359 #define gmx_simd4_or_f                   gmx_simd_or_f
360 #define gmx_simd4_xor_f                  gmx_simd_xor_f
361 #define gmx_simd4_rsqrt_f                gmx_simd_rsqrt_f
362 #define gmx_simd4_rcp_f                  gmx_simd_rcp_f
363 #define gmx_simd4_fabs_f                 gmx_simd_fabs_f
364 #define gmx_simd4_fneg_f                 gmx_simd_fneg_f
365 #define gmx_simd4_max_f                  gmx_simd_max_f
366 #define gmx_simd4_min_f                  gmx_simd_min_f
367 #define gmx_simd4_round_f                gmx_simd_round_f
368 #define gmx_simd4_trunc_f                gmx_simd_trunc_f
369 #define gmx_simd4_fraction_f             gmx_simd_fraction_f
370 #define gmx_simd4_get_exponent_f         gmx_simd_get_exponent_f
371 #define gmx_simd4_get_mantissa_f         gmx_simd_get_mantissa_f
372 #define gmx_simd4_set_exponent_f         gmx_simd_set_exponent_f
373 #define gmx_simd4_dotproduct3_f          gmx_simd4_dotproduct3_f_ibm_qpx
374 #define gmx_simd4_fint32_t               gmx_simd_fint32_t
375 #define gmx_simd4_load_fi                gmx_simd_load_fi
376 #define gmx_simd4_load1_fi               gmx_simd_load1_fi
377 #define gmx_simd4_set1_fi                gmx_simd_set1_fi
378 #define gmx_simd4_store_fi               gmx_simd_store_fi
379 #define gmx_simd4_loadu_fi               gmx_simd_loadu_fi
380 #define gmx_simd4_storeu_fi              gmx_simd_storeu_fi
381 #define gmx_simd4_setzero_fi             gmx_simd_setzero_fi
382 #define gmx_simd4_cvt_f2i                gmx_simd_cvt_f2i
383 #define gmx_simd4_cvtt_f2i               gmx_simd_cvtt_f2i
384 #define gmx_simd4_cvt_i2f                gmx_simd_cvt_i2f
385 #define gmx_simd4_fbool_t                gmx_simd_fbool_t
386 #define gmx_simd4_cmpeq_f                gmx_simd_cmpeq_f
387 #define gmx_simd4_cmplt_f                gmx_simd_cmplt_f
388 #define gmx_simd4_cmple_f                gmx_simd_cmple_f
389 #define gmx_simd4_and_fb                 gmx_simd_and_fb
390 #define gmx_simd4_or_fb                  gmx_simd_or_fb
391 #define gmx_simd4_anytrue_fb             gmx_simd_anytrue_fb
392 #define gmx_simd4_blendzero_f            gmx_simd_blendzero_f
393 #define gmx_simd4_blendnotzero_f         gmx_simd_blendnotzero_f
394 #define gmx_simd4_blendv_f               gmx_simd_blendv_f
395 #define gmx_simd4_reduce_f               gmx_simd_reduce_f
396 /* DOUBLE */
397 #define gmx_simd4_double_t               gmx_simd_double_t
398 #define gmx_simd4_load_d                 gmx_simd_load_d
399 #define gmx_simd4_load1_d                gmx_simd_load1_d
400 #define gmx_simd4_set1_d                 gmx_simd_set1_d
401 #define gmx_simd4_store_d                gmx_simd_store_d
402 #define gmx_simd4_loadu_d                gmx_simd_loadu_d
403 #define gmx_simd4_storeu_d               gmx_simd_storeu_d
404 #define gmx_simd4_setzero_d              gmx_simd_setzero_d
405 #define gmx_simd4_add_d                  gmx_simd_add_d
406 #define gmx_simd4_sub_d                  gmx_simd_sub_d
407 #define gmx_simd4_mul_d                  gmx_simd_mul_d
408 #define gmx_simd4_fmadd_d                gmx_simd_fmadd_d
409 #define gmx_simd4_fmsub_d                gmx_simd_fmsub_d
410 #define gmx_simd4_fnmadd_d               gmx_simd_fnmadd_d
411 #define gmx_simd4_fnmsub_d               gmx_simd_fnmsub_d
412 #define gmx_simd4_and_d                  gmx_simd_and_d
413 #define gmx_simd4_andnot_d               gmx_simd_andnot_d
414 #define gmx_simd4_or_d                   gmx_simd_or_d
415 #define gmx_simd4_xor_d                  gmx_simd_xor_d
416 #define gmx_simd4_rsqrt_d                gmx_simd_rsqrt_d
417 #define gmx_simd4_rcp_d                  gmx_simd_rcp_d
418 #define gmx_simd4_fabs_d                 gmx_simd_fabs_d
419 #define gmx_simd4_fneg_d                 gmx_simd_fneg_d
420 #define gmx_simd4_max_d                  gmx_simd_max_d
421 #define gmx_simd4_min_d                  gmx_simd_min_d
422 #define gmx_simd4_round_d                gmx_simd_round_d
423 #define gmx_simd4_trunc_d                gmx_simd_trunc_d
424 #define gmx_simd4_fraction_d             gmx_simd_fraction_d
425 #define gmx_simd4_get_exponent_d         gmx_simd_get_exponent_d
426 #define gmx_simd4_get_mantissa_d         gmx_simd_get_mantissa_d
427 #define gmx_simd4_set_exponent_d         gmx_simd_set_exponent_d
428 #define gmx_simd4_dotproduct3_d          gmx_simd4_dotproduct3_d_ibm_qpx
429 #define gmx_simd4_dint32_t               gmx_simd_dint32_t
430 #define gmx_simd4_load_di                gmx_simd_load_di
431 #define gmx_simd4_load1_di               gmx_simd_load1_di
432 #define gmx_simd4_set1_di                gmx_simd_set1_di
433 #define gmx_simd4_store_di               gmx_simd_store_di
434 #define gmx_simd4_loadu_di               gmx_simd_loadu_di
435 #define gmx_simd4_storeu_di              gmx_simd_storeu_di
436 #define gmx_simd4_setzero_di             gmx_simd_setzero_di
437 #define gmx_simd4_cvt_d2i                gmx_simd_cvt_d2i
438 #define gmx_simd4_cvtt_d2i               gmx_simd_cvtt_d2i
439 #define gmx_simd4_cvt_i2f                gmx_simd_cvt_i2f
440 #define gmx_simd4_dbool_t                gmx_simd_dbool_t
441 #define gmx_simd4_cmpeq_d                gmx_simd_cmpeq_d
442 #define gmx_simd4_cmplt_d                gmx_simd_cmplt_d
443 #define gmx_simd4_cmple_d                gmx_simd_cmple_d
444 #define gmx_simd4_and_db                 gmx_simd_and_db
445 #define gmx_simd4_or_db                  gmx_simd_or_db
446 #define gmx_simd4_anytrue_db             gmx_simd_anytrue_db
447 #define gmx_simd4_blendzero_d            gmx_simd_blendzero_d
448 #define gmx_simd4_blendnotzero_d         gmx_simd_blendnotzero_d
449 #define gmx_simd4_blendv_d               gmx_simd_blendv_d
450 #define gmx_simd4_reduce_d               gmx_simd_reduce_d
451
452 static __attribute__((always_inline)) double gmx_simdcall
453 gmx_simd4_dotproduct3_d_ibm_qpx(vector4double a, vector4double b)
454 {
455     vector4double dp_sh0 = vec_mul(a, b);
456     vector4double dp_sh1 = vec_sldw(dp_sh0, dp_sh0, 1);
457     vector4double dp_sh2 = vec_sldw(dp_sh0, dp_sh0, 2);
458     vector4double dp     = vec_add(dp_sh2, vec_add(dp_sh0, dp_sh1));
459
460     return vec_extract(dp, 0);
461 }
462
463 static __attribute__((always_inline)) float gmx_simdcall
464 gmx_simd4_dotproduct3_f_ibm_qpx(vector4double a, vector4double b)
465 {
466     return (float)gmx_simd4_dotproduct3_d_ibm_qpx(a, b);
467 }
468
469 /* Function to check whether SIMD operations have resulted in overflow.
470  * For now, this is unfortunately a dummy for this architecture.
471  */
472 static int
473 gmx_simd_check_and_reset_overflow(void)
474 {
475     return 0;
476 }
477
478 #endif /* GMX_SIMD_IMPLEMENTATION_IBM_QPX_H */