Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / simd / impl_x86_avx2_256 / impl_x86_avx2_256.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_IMPL_X86_AVX2_256_H
37 #define GMX_SIMD_IMPL_X86_AVX2_256_H
38
39 #include "config.h"
40
41 #include <math.h>
42
43 #include <immintrin.h>
44
45 /* x86 256-bit AVX2 SIMD instruction wrappers
46  *
47  * Please see documentation in gromacs/simd/simd.h for details
48  */
49
50 /* Inherit parts of AVX2_256 from AVX_256 */
51 #include "gromacs/simd/impl_x86_avx_256/impl_x86_avx_256.h"
52 /* Increment over AVX_256 capabilities */
53 #define GMX_SIMD_X86_AVX2_256_OR_HIGHER
54
55 /* Override some capability definitions for things added in AVX2 */
56 #define GMX_SIMD_HAVE_FMA
57 #define GMX_SIMD_HAVE_FINT32_LOGICAL     /* AVX2 adds 256-bit integer shifts */
58 #define GMX_SIMD_HAVE_FINT32_ARITHMETICS /* AVX2 adds 256-bit integer +,-,*  */
59
60 /****************************************************
61  *      SINGLE PRECISION SIMD IMPLEMENTATION        *
62  ****************************************************/
63 #undef  gmx_simd_fmadd_f
64 #define gmx_simd_fmadd_f           _mm256_fmadd_ps
65 #undef  gmx_simd_fmsub_f
66 #define gmx_simd_fmsub_f           _mm256_fmsub_ps
67 #undef  gmx_simd_fnmadd_f
68 #define gmx_simd_fnmadd_f          _mm256_fnmadd_ps
69 #undef  gmx_simd_fnmsub_f
70 #define gmx_simd_fnmsub_f          _mm256_fnmsub_ps
71 #undef  gmx_simd_get_exponent_f
72 #define gmx_simd_get_exponent_f    gmx_simd_get_exponent_f_avx2_256
73 #undef  gmx_simd_set_exponent_f
74 #define gmx_simd_set_exponent_f    gmx_simd_set_exponent_f_avx2_256
75 /* Previously undefined logical ops on gmx_simd_fint32_t */
76 #define gmx_simd_slli_fi           _mm256_slli_epi32
77 #define gmx_simd_srli_fi           _mm256_srli_epi32
78 #define gmx_simd_and_fi            _mm256_and_si256
79 #define gmx_simd_andnot_fi         _mm256_andnot_si256
80 #define gmx_simd_or_fi             _mm256_or_si256
81 #define gmx_simd_xor_fi            _mm256_xor_si256
82 /* Previously undefined arithmetic ops on gmx_simd_fint32_t */
83 #define gmx_simd_add_fi            _mm256_add_epi32
84 #define gmx_simd_sub_fi            _mm256_sub_epi32
85 #define gmx_simd_mul_fi            _mm256_mullo_epi32
86 /* Previously undefined boolean ops on gmx_simd_fint32_t */
87 #define gmx_simd_cmpeq_fi          _mm256_cmpeq_epi32
88 #define gmx_simd_cmplt_fi(a, b)     _mm256_cmpgt_epi32(b, a)
89 #define gmx_simd_and_fib           _mm256_and_si256
90 #define gmx_simd_or_fib            _mm256_or_si256
91 #define gmx_simd_anytrue_fib       _mm256_movemask_epi8
92 #define gmx_simd_blendzero_fi      _mm256_and_si256
93 #define gmx_simd_blendnotzero_fi(a, sel) _mm256_andnot_si256(sel, a)
94 #define gmx_simd_blendv_fi         _mm256_blendv_epi8
95
96
97 /****************************************************
98  *      DOUBLE PRECISION SIMD IMPLEMENTATION        *
99  ****************************************************/
100 #undef  gmx_simd_fmadd_d
101 #define gmx_simd_fmadd_d           _mm256_fmadd_pd
102 #undef  gmx_simd_fmsub_d
103 #define gmx_simd_fmsub_d           _mm256_fmsub_pd
104 #undef  gmx_simd_fnmadd_d
105 #define gmx_simd_fnmadd_d          _mm256_fnmadd_pd
106 #undef  gmx_simd_fnmsub_d
107 #define gmx_simd_fnmsub_d          _mm256_fnmsub_pd
108 #undef  gmx_simd_get_exponent_d
109 #define gmx_simd_get_exponent_d    gmx_simd_get_exponent_d_avx2_256
110 #undef  gmx_simd_set_exponent_d
111 #define gmx_simd_set_exponent_d    gmx_simd_set_exponent_d_avx2_256
112 #undef  gmx_simd_cvt_db2dib
113 #define gmx_simd_cvt_db2dib        gmx_simd_cvt_db2dib_avx2_256
114 #undef  gmx_simd_cvt_dib2db
115 #define gmx_simd_cvt_dib2db        gmx_simd_cvt_dib2db_avx2_256
116
117 /****************************************************
118  *      SIMD4 SINGLE PRECISION IMPLEMENTATION       *
119  ****************************************************/
120 #undef  gmx_simd4_fmadd_f
121 #define gmx_simd4_fmadd_f          _mm_fmadd_ps
122 #undef  gmx_simd4_fmsub_f
123 #define gmx_simd4_fmsub_f          _mm_fmsub_ps
124 #undef  gmx_simd4_fnmadd_f
125 #define gmx_simd4_fnmadd_f         _mm_fnmadd_ps
126 #undef  gmx_simd4_fnmsub_f
127 #define gmx_simd4_fnmsub_f         _mm_fnmsub_ps
128
129 /* No need to update SIMD4 double, since those instructions
130  * are aliased to the general SIMD double instructions above.
131  */
132
133 /*********************************************************
134  * SIMD SINGLE PRECISION IMPLEMENTATION HELPER FUNCTIONS *
135  *********************************************************/
136 static gmx_inline gmx_simd_float_t gmx_simdcall
137 gmx_simd_get_exponent_f_avx2_256(gmx_simd_float_t x)
138 {
139     const __m256  expmask      = _mm256_castsi256_ps(_mm256_set1_epi32(0x7F800000));
140     const __m256i expbias      = _mm256_set1_epi32(127);
141     __m256i       iexp;
142
143     iexp = _mm256_castps_si256(_mm256_and_ps(x, expmask));
144     iexp = _mm256_sub_epi32(_mm256_srli_epi32(iexp, 23), expbias);
145     return _mm256_cvtepi32_ps(iexp);
146 }
147
148 static gmx_inline gmx_simd_float_t gmx_simdcall
149 gmx_simd_set_exponent_f_avx2_256(gmx_simd_float_t x)
150 {
151     const __m256i  expbias      = _mm256_set1_epi32(127);
152     __m256i        iexp         = _mm256_cvtps_epi32(x);
153
154     iexp = _mm256_slli_epi32(_mm256_add_epi32(iexp, expbias), 23);
155     return _mm256_castsi256_ps(iexp);
156 }
157
158 /*********************************************************
159  * SIMD DOUBLE PRECISION IMPLEMENTATION HELPER FUNCTIONS *
160  *********************************************************/
161 static gmx_inline gmx_simd_double_t gmx_simdcall
162 gmx_simd_get_exponent_d_avx2_256(gmx_simd_double_t x)
163 {
164     const __m256d  expmask      = _mm256_castsi256_pd(_mm256_set1_epi64x(0x7FF0000000000000LL));
165     const __m256i  expbias      = _mm256_set1_epi64x(1023LL);
166     __m256i        iexp;
167     __m128i        iexp128;
168
169     iexp = _mm256_castpd_si256(_mm256_and_pd(x, expmask));
170     iexp = _mm256_sub_epi64(_mm256_srli_epi64(iexp, 52), expbias);
171     iexp = _mm256_shuffle_epi32(iexp, _MM_SHUFFLE(3, 1, 2, 0));
172
173     iexp128 = _mm256_extractf128_si256(iexp, 1);
174     iexp128 = _mm_unpacklo_epi64(_mm256_castsi256_si128(iexp), iexp128);
175     return _mm256_cvtepi32_pd(iexp128);
176 }
177
178 static gmx_inline gmx_simd_double_t gmx_simdcall
179 gmx_simd_set_exponent_d_avx2_256(gmx_simd_double_t x)
180 {
181     const __m256i  expbias      = _mm256_set1_epi64x(1023LL);
182     __m256i        iexp         = _mm256_cvtepi32_epi64(_mm256_cvtpd_epi32(x));
183
184     iexp = _mm256_slli_epi64(_mm256_add_epi64(iexp, expbias), 52);
185     return _mm256_castsi256_pd(iexp);
186 }
187
188 static gmx_inline gmx_simd_dibool_t gmx_simdcall
189 gmx_simd_cvt_db2dib_avx2_256(gmx_simd_dbool_t a)
190 {
191     __m128i ia = _mm256_castsi256_si128(_mm256_castpd_si256(a));
192     __m128i ib = _mm256_extractf128_si256(_mm256_castpd_si256(a), 0x1);
193
194     ia = _mm_packs_epi32(ia, ib);
195
196     return ia;
197 }
198
199 static gmx_inline gmx_simd_dbool_t gmx_simdcall
200 gmx_simd_cvt_dib2db_avx2_256(gmx_simd_dibool_t ia)
201 {
202     __m128d lo = _mm_castsi128_pd(_mm_unpacklo_epi32(ia, ia));
203     __m128d hi = _mm_castsi128_pd(_mm_unpackhi_epi32(ia, ia));
204
205     return _mm256_insertf128_pd(_mm256_castpd128_pd256(lo), hi, 0x1);
206 }
207
208 #endif /* GMX_SIMD_IMPL_X86_AVX2_256_H */