e9dbfb83734ac2d48690c61258effede40db99cd
[alexxy/gromacs.git] / src / mdlib / nbnxn_kernels / nbnxn_kernel_simd_2xnn_inner.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2009, The GROMACS Development Team
6  * Copyright (c) 2012,2013, by the GROMACS development team, led by
7  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
8  * others, as listed in the AUTHORS file in the top-level source
9  * directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37
38 /* This is the innermost loop contents for the 4 x N atom SIMD kernel.
39  * This flavor of the kernel duplicates the data for N j-particles in
40  * 2xN wide SIMD registers to do operate on 2 i-particles at once.
41  * This leads to 4/2=2 sets of most instructions. Therefore we call
42  * this kernel 2x(N+N) = 2xnn
43  *
44  * This 2xnn kernel is basically the 4xn equivalent with half the registers
45  * and instructions removed.
46  *
47  * An alternative would be to load to different cluster of N j-particles
48  * into SIMD registers, giving a 4x(N+N) kernel. This doubles the amount
49  * of instructions, which could lead to better scheduling. But we actually
50  * observed worse scheduling for the AVX-256 4x8 normal analytical PME
51  * kernel, which has a lower pair throughput than 2x(4+4) with gcc 4.7.
52  * It could be worth trying this option, but it takes some more effort.
53  * This 2xnn kernel is basically the 4xn equivalent with
54  */
55
56
57 /* When calculating RF or Ewald interactions we calculate the electrostatic
58  * forces on excluded atom pairs here in the non-bonded loops.
59  * But when energies and/or virial is required we calculate them
60  * separately to as then it is easier to separate the energy and virial
61  * contributions.
62  */
63 #if defined CHECK_EXCLS && defined CALC_COULOMB
64 #define EXCL_FORCES
65 #endif
66
67 /* Without exclusions and energies we only need to mask the cut-off,
68  * this can be faster with blendv (only available with SSE4.1 and later).
69  */
70 #if !(defined CHECK_EXCLS || defined CALC_ENERGIES) && defined GMX_X86_SSE4_1 && !defined COUNT_PAIRS
71 /* With RF and tabulated Coulomb we replace cmp+and with sub+blendv.
72  * With gcc this is slower, except for RF on Sandy Bridge.
73  * Tested with gcc 4.6.2, 4.6.3 and 4.7.1.
74  */
75 #if (defined CALC_COUL_RF || defined CALC_COUL_TAB) && (!defined __GNUC__ || (defined CALC_COUL_RF && defined GMX_X86_AVX_256))
76 #define CUTOFF_BLENDV
77 #endif
78 /* With analytical Ewald we replace cmp+and+and with sub+blendv+blendv.
79  * This is only faster with icc on Sandy Bridge (PS kernel slower than gcc 4.7).
80  * Tested with icc 13.
81  */
82 #if defined CALC_COUL_EWALD && defined __INTEL_COMPILER && defined GMX_X86_AVX_256
83 #define CUTOFF_BLENDV
84 #endif
85 #endif
86
87 {
88     int        cj, aj, ajx, ajy, ajz;
89
90 #ifdef ENERGY_GROUPS
91     /* Energy group indices for two atoms packed into one int */
92     int        egp_jj[UNROLLJ/2];
93 #endif
94
95 #ifdef CHECK_EXCLS
96     /* Interaction (non-exclusion) mask of all 1's or 0's */
97     gmx_mm_pr  int_SSE0;
98     gmx_mm_pr  int_SSE2;
99 #endif
100
101     gmx_mm_pr  jxSSE, jySSE, jzSSE;
102     gmx_mm_pr  dx_SSE0, dy_SSE0, dz_SSE0;
103     gmx_mm_pr  dx_SSE2, dy_SSE2, dz_SSE2;
104     gmx_mm_pr  tx_SSE0, ty_SSE0, tz_SSE0;
105     gmx_mm_pr  tx_SSE2, ty_SSE2, tz_SSE2;
106     gmx_mm_pr  rsq_SSE0, rinv_SSE0, rinvsq_SSE0;
107     gmx_mm_pr  rsq_SSE2, rinv_SSE2, rinvsq_SSE2;
108 #ifndef CUTOFF_BLENDV
109     /* wco: within cut-off, mask of all 1's or 0's */
110     gmx_mm_pr  wco_SSE0;
111     gmx_mm_pr  wco_SSE2;
112 #endif
113 #ifdef VDW_CUTOFF_CHECK
114     gmx_mm_pr  wco_vdw_SSE0;
115 #ifndef HALF_LJ
116     gmx_mm_pr  wco_vdw_SSE2;
117 #endif
118 #endif
119 #ifdef CALC_COULOMB
120 #ifdef CHECK_EXCLS
121     /* 1/r masked with the interaction mask */
122     gmx_mm_pr  rinv_ex_SSE0;
123     gmx_mm_pr  rinv_ex_SSE2;
124 #endif
125     gmx_mm_pr  jq_SSE;
126     gmx_mm_pr  qq_SSE0;
127     gmx_mm_pr  qq_SSE2;
128 #ifdef CALC_COUL_TAB
129     /* The force (PME mesh force) we need to subtract from 1/r^2 */
130     gmx_mm_pr  fsub_SSE0;
131     gmx_mm_pr  fsub_SSE2;
132 #endif
133 #ifdef CALC_COUL_EWALD
134     gmx_mm_pr  brsq_SSE0, brsq_SSE2;
135     gmx_mm_pr  ewcorr_SSE0, ewcorr_SSE2;
136 #endif
137
138     /* frcoul = (1/r - fsub)*r */
139     gmx_mm_pr  frcoul_SSE0;
140     gmx_mm_pr  frcoul_SSE2;
141 #ifdef CALC_COUL_TAB
142     /* For tables: r, rs=r/sp, rf=floor(rs), frac=rs-rf */
143     gmx_mm_pr  r_SSE0, rs_SSE0, rf_SSE0, frac_SSE0;
144     gmx_mm_pr  r_SSE2, rs_SSE2, rf_SSE2, frac_SSE2;
145     /* Table index: rs truncated to an int */
146 #if !(defined GMX_MM256_HERE && defined GMX_DOUBLE)
147     gmx_epi32  ti_SSE0, ti_SSE2;
148 #else
149     __m128i    ti_SSE0, ti_SSE2;
150 #endif
151     /* Linear force table values */
152     gmx_mm_pr  ctab0_SSE0, ctab1_SSE0;
153     gmx_mm_pr  ctab0_SSE2, ctab1_SSE2;
154 #ifdef CALC_ENERGIES
155     /* Quadratic energy table value */
156     gmx_mm_pr  ctabv_SSE0;
157     gmx_mm_pr  ctabv_SSE2;
158 #endif
159 #endif
160 #if defined CALC_ENERGIES && (defined CALC_COUL_EWALD || defined CALC_COUL_TAB)
161     /* The potential (PME mesh) we need to subtract from 1/r */
162     gmx_mm_pr  vc_sub_SSE0;
163     gmx_mm_pr  vc_sub_SSE2;
164 #endif
165 #ifdef CALC_ENERGIES
166     /* Electrostatic potential */
167     gmx_mm_pr  vcoul_SSE0;
168     gmx_mm_pr  vcoul_SSE2;
169 #endif
170 #endif
171     /* The force times 1/r */
172     gmx_mm_pr  fscal_SSE0;
173     gmx_mm_pr  fscal_SSE2;
174
175 #ifdef CALC_LJ
176 #ifdef LJ_COMB_LB
177     /* LJ sigma_j/2 and sqrt(epsilon_j) */
178     gmx_mm_pr  hsig_j_SSE, seps_j_SSE;
179     /* LJ sigma_ij and epsilon_ij */
180     gmx_mm_pr  sig_SSE0, eps_SSE0;
181 #ifndef HALF_LJ
182     gmx_mm_pr  sig_SSE2, eps_SSE2;
183 #endif
184 #ifdef CALC_ENERGIES
185     gmx_mm_pr  sig2_SSE0, sig6_SSE0;
186 #ifndef HALF_LJ
187     gmx_mm_pr  sig2_SSE2, sig6_SSE2;
188 #endif
189 #endif /* LJ_COMB_LB */
190 #endif /* CALC_LJ */
191
192 #ifdef LJ_COMB_GEOM
193     gmx_mm_pr  c6s_j_SSE, c12s_j_SSE;
194 #endif
195
196 #if defined LJ_COMB_GEOM || defined LJ_COMB_LB
197     /* Index for loading LJ parameters, complicated when interleaving */
198     int         aj2;
199 #endif
200
201 #ifndef FIX_LJ_C
202     /* LJ C6 and C12 parameters, used with geometric comb. rule */
203     gmx_mm_pr  c6_SSE0, c12_SSE0;
204 #ifndef HALF_LJ
205     gmx_mm_pr  c6_SSE2, c12_SSE2;
206 #endif
207 #endif
208
209     /* Intermediate variables for LJ calculation */
210 #ifndef LJ_COMB_LB
211     gmx_mm_pr  rinvsix_SSE0;
212 #ifndef HALF_LJ
213     gmx_mm_pr  rinvsix_SSE2;
214 #endif
215 #endif
216 #ifdef LJ_COMB_LB
217     gmx_mm_pr  sir_SSE0, sir2_SSE0, sir6_SSE0;
218 #ifndef HALF_LJ
219     gmx_mm_pr  sir_SSE2, sir2_SSE2, sir6_SSE2;
220 #endif
221 #endif
222
223     gmx_mm_pr  FrLJ6_SSE0, FrLJ12_SSE0;
224 #ifndef HALF_LJ
225     gmx_mm_pr  FrLJ6_SSE2, FrLJ12_SSE2;
226 #endif
227 #ifdef CALC_ENERGIES
228     gmx_mm_pr  VLJ6_SSE0, VLJ12_SSE0, VLJ_SSE0;
229 #ifndef HALF_LJ
230     gmx_mm_pr  VLJ6_SSE2, VLJ12_SSE2, VLJ_SSE2;
231 #endif
232 #endif
233 #endif /* CALC_LJ */
234
235     /* j-cluster index */
236     cj            = l_cj[cjind].cj;
237
238     /* Atom indices (of the first atom in the cluster) */
239     aj            = cj*UNROLLJ;
240 #if defined CALC_LJ && (defined LJ_COMB_GEOM || defined LJ_COMB_LB)
241 #if UNROLLJ == STRIDE
242     aj2           = aj*2;
243 #else
244     aj2           = (cj>>1)*2*STRIDE + (cj & 1)*UNROLLJ;
245 #endif
246 #endif
247 #if UNROLLJ == STRIDE
248     ajx           = aj*DIM;
249 #else
250     ajx           = (cj>>1)*DIM*STRIDE + (cj & 1)*UNROLLJ;
251 #endif
252     ajy           = ajx + STRIDE;
253     ajz           = ajy + STRIDE;
254
255 #ifdef CHECK_EXCLS
256     {
257         /* Load integer interaction mask */
258         /* With AVX there are no integer operations, so cast to real */
259         gmx_mm_pr mask_pr = gmx_mm_castsi256_pr(_mm256_set1_epi32(l_cj[cjind].excl));
260         /* Intel Compiler version 12.1.3 20120130 is buggy: use cast.
261          * With gcc we don't need the cast, but it's faster.
262          */
263 #define cast_cvt(x)  _mm256_cvtepi32_ps(_mm256_castps_si256(x))
264         int_SSE0  = gmx_cmpneq_pr(cast_cvt(gmx_and_pr(mask_pr, mask0)), zero_SSE);
265         int_SSE2  = gmx_cmpneq_pr(cast_cvt(gmx_and_pr(mask_pr, mask2)), zero_SSE);
266 #undef cast_cvt
267     }
268 #endif
269     /* load j atom coordinates */
270     jxSSE         = gmx_loaddh_pr(x+ajx);
271     jySSE         = gmx_loaddh_pr(x+ajy);
272     jzSSE         = gmx_loaddh_pr(x+ajz);
273
274     /* Calculate distance */
275     dx_SSE0       = gmx_sub_pr(ix_SSE0, jxSSE);
276     dy_SSE0       = gmx_sub_pr(iy_SSE0, jySSE);
277     dz_SSE0       = gmx_sub_pr(iz_SSE0, jzSSE);
278     dx_SSE2       = gmx_sub_pr(ix_SSE2, jxSSE);
279     dy_SSE2       = gmx_sub_pr(iy_SSE2, jySSE);
280     dz_SSE2       = gmx_sub_pr(iz_SSE2, jzSSE);
281
282     /* rsq = dx*dx+dy*dy+dz*dz */
283     rsq_SSE0      = gmx_calc_rsq_pr(dx_SSE0, dy_SSE0, dz_SSE0);
284     rsq_SSE2      = gmx_calc_rsq_pr(dx_SSE2, dy_SSE2, dz_SSE2);
285
286 #ifndef CUTOFF_BLENDV
287     wco_SSE0      = gmx_cmplt_pr(rsq_SSE0, rc2_SSE);
288     wco_SSE2      = gmx_cmplt_pr(rsq_SSE2, rc2_SSE);
289 #endif
290
291 #ifdef CHECK_EXCLS
292 #ifdef EXCL_FORCES
293     /* Only remove the (sub-)diagonal to avoid double counting */
294 #if UNROLLJ == UNROLLI
295     if (cj == ci_sh)
296     {
297         wco_SSE0  = gmx_and_pr(wco_SSE0, diag_SSE0);
298         wco_SSE2  = gmx_and_pr(wco_SSE2, diag_SSE2);
299     }
300 #else
301 #error "only UNROLLJ == UNROLLI currently supported in the joined kernels"
302 #endif
303 #else /* EXCL_FORCES */
304       /* Remove all excluded atom pairs from the list */
305     wco_SSE0      = gmx_and_pr(wco_SSE0, int_SSE0);
306     wco_SSE2      = gmx_and_pr(wco_SSE2, int_SSE2);
307 #endif
308 #endif
309
310 #ifdef COUNT_PAIRS
311     {
312         int  i, j;
313         real tmp[UNROLLJ];
314         for (i = 0; i < UNROLLI; i++)
315         {
316             gmx_storeu_pr(tmp, i == 0 ? wco_SSE0 : (i == 1 ? wco_SSE1 : (i == 2 ? wco_SSE2 : wco_SSE3)));
317             for (j = 0; j < UNROLLJ; j++)
318             {
319                 if (!(tmp[j] == 0))
320                 {
321                     npair++;
322                 }
323             }
324         }
325     }
326 #endif
327
328 #ifdef CHECK_EXCLS
329     /* For excluded pairs add a small number to avoid r^-6 = NaN */
330     rsq_SSE0      = gmx_add_pr(rsq_SSE0, gmx_andnot_pr(int_SSE0, avoid_sing_SSE));
331     rsq_SSE2      = gmx_add_pr(rsq_SSE2, gmx_andnot_pr(int_SSE2, avoid_sing_SSE));
332 #endif
333
334     /* Calculate 1/r */
335     rinv_SSE0     = gmx_invsqrt_pr(rsq_SSE0);
336     rinv_SSE2     = gmx_invsqrt_pr(rsq_SSE2);
337
338 #ifdef CALC_COULOMB
339     /* Load parameters for j atom */
340     jq_SSE        = gmx_loaddh_pr(q+aj);
341     qq_SSE0       = gmx_mul_pr(iq_SSE0, jq_SSE);
342     qq_SSE2       = gmx_mul_pr(iq_SSE2, jq_SSE);
343 #endif
344
345 #ifdef CALC_LJ
346
347 #if !defined LJ_COMB_GEOM && !defined LJ_COMB_LB && !defined FIX_LJ_C
348     load_lj_pair_params2(nbfp0, nbfp1, type, aj, c6_SSE0, c12_SSE0);
349 #ifndef HALF_LJ
350     load_lj_pair_params2(nbfp2, nbfp3, type, aj, c6_SSE2, c12_SSE2);
351 #endif
352 #endif /* not defined any LJ rule */
353
354 #ifdef LJ_COMB_GEOM
355     c6s_j_SSE     = gmx_loaddh_pr(ljc+aj2+0);
356     c12s_j_SSE    = gmx_loaddh_pr(ljc+aj2+STRIDE);
357     c6_SSE0       = gmx_mul_pr(c6s_SSE0, c6s_j_SSE );
358 #ifndef HALF_LJ
359     c6_SSE2       = gmx_mul_pr(c6s_SSE2, c6s_j_SSE );
360 #endif
361     c12_SSE0      = gmx_mul_pr(c12s_SSE0, c12s_j_SSE);
362 #ifndef HALF_LJ
363     c12_SSE2      = gmx_mul_pr(c12s_SSE2, c12s_j_SSE);
364 #endif
365 #endif /* LJ_COMB_GEOM */
366
367 #ifdef LJ_COMB_LB
368     hsig_j_SSE    = gmx_loaddh_pr(ljc+aj2+0);
369     seps_j_SSE    = gmx_loaddh_pr(ljc+aj2+STRIDE);
370
371     sig_SSE0      = gmx_add_pr(hsig_i_SSE0, hsig_j_SSE);
372     eps_SSE0      = gmx_mul_pr(seps_i_SSE0, seps_j_SSE);
373 #ifndef HALF_LJ
374     sig_SSE2      = gmx_add_pr(hsig_i_SSE2, hsig_j_SSE);
375     eps_SSE2      = gmx_mul_pr(seps_i_SSE2, seps_j_SSE);
376 #endif
377 #endif /* LJ_COMB_LB */
378
379 #endif /* CALC_LJ */
380
381 #ifndef CUTOFF_BLENDV
382     rinv_SSE0     = gmx_and_pr(rinv_SSE0, wco_SSE0);
383     rinv_SSE2     = gmx_and_pr(rinv_SSE2, wco_SSE2);
384 #else
385     /* We only need to mask for the cut-off: blendv is faster */
386     rinv_SSE0     = gmx_blendv_pr(rinv_SSE0, zero_SSE, gmx_sub_pr(rc2_SSE, rsq_SSE0));
387     rinv_SSE2     = gmx_blendv_pr(rinv_SSE2, zero_SSE, gmx_sub_pr(rc2_SSE, rsq_SSE2));
388 #endif
389
390     rinvsq_SSE0   = gmx_mul_pr(rinv_SSE0, rinv_SSE0);
391     rinvsq_SSE2   = gmx_mul_pr(rinv_SSE2, rinv_SSE2);
392
393 #ifdef CALC_COULOMB
394     /* Note that here we calculate force*r, not the usual force/r.
395      * This allows avoiding masking the reaction-field contribution,
396      * as frcoul is later multiplied by rinvsq which has been
397      * masked with the cut-off check.
398      */
399
400 #ifdef EXCL_FORCES
401     /* Only add 1/r for non-excluded atom pairs */
402     rinv_ex_SSE0  = gmx_and_pr(rinv_SSE0, int_SSE0);
403     rinv_ex_SSE2  = gmx_and_pr(rinv_SSE2, int_SSE2);
404 #else
405     /* No exclusion forces, we always need 1/r */
406 #define     rinv_ex_SSE0    rinv_SSE0
407 #define     rinv_ex_SSE2    rinv_SSE2
408 #endif
409
410 #ifdef CALC_COUL_RF
411     /* Electrostatic interactions */
412     frcoul_SSE0   = gmx_mul_pr(qq_SSE0, gmx_add_pr(rinv_ex_SSE0, gmx_mul_pr(rsq_SSE0, mrc_3_SSE)));
413     frcoul_SSE2   = gmx_mul_pr(qq_SSE2, gmx_add_pr(rinv_ex_SSE2, gmx_mul_pr(rsq_SSE2, mrc_3_SSE)));
414
415 #ifdef CALC_ENERGIES
416     vcoul_SSE0    = gmx_mul_pr(qq_SSE0, gmx_add_pr(rinv_ex_SSE0, gmx_add_pr(gmx_mul_pr(rsq_SSE0, hrc_3_SSE), moh_rc_SSE)));
417     vcoul_SSE2    = gmx_mul_pr(qq_SSE2, gmx_add_pr(rinv_ex_SSE2, gmx_add_pr(gmx_mul_pr(rsq_SSE2, hrc_3_SSE), moh_rc_SSE)));
418 #endif
419 #endif
420
421 #ifdef CALC_COUL_EWALD
422     /* We need to mask (or limit) rsq for the cut-off,
423      * as large distances can cause an overflow in gmx_pmecorrF/V.
424      */
425 #ifndef CUTOFF_BLENDV
426     brsq_SSE0     = gmx_mul_pr(beta2_SSE, gmx_and_pr(rsq_SSE0, wco_SSE0));
427     brsq_SSE2     = gmx_mul_pr(beta2_SSE, gmx_and_pr(rsq_SSE2, wco_SSE2));
428 #else
429     /* Strangely, putting mul on a separate line is slower (icc 13) */
430     brsq_SSE0     = gmx_mul_pr(beta2_SSE, gmx_blendv_pr(rsq_SSE0, zero_SSE, gmx_sub_pr(rc2_SSE, rsq_SSE0)));
431     brsq_SSE2     = gmx_mul_pr(beta2_SSE, gmx_blendv_pr(rsq_SSE2, zero_SSE, gmx_sub_pr(rc2_SSE, rsq_SSE2)));
432 #endif
433     ewcorr_SSE0   = gmx_mul_pr(gmx_pmecorrF_pr(brsq_SSE0), beta_SSE);
434     ewcorr_SSE2   = gmx_mul_pr(gmx_pmecorrF_pr(brsq_SSE2), beta_SSE);
435     frcoul_SSE0   = gmx_mul_pr(qq_SSE0, gmx_add_pr(rinv_ex_SSE0, gmx_mul_pr(ewcorr_SSE0, brsq_SSE0)));
436     frcoul_SSE2   = gmx_mul_pr(qq_SSE2, gmx_add_pr(rinv_ex_SSE2, gmx_mul_pr(ewcorr_SSE2, brsq_SSE2)));
437
438 #ifdef CALC_ENERGIES
439     vc_sub_SSE0   = gmx_mul_pr(gmx_pmecorrV_pr(brsq_SSE0), beta_SSE);
440     vc_sub_SSE2   = gmx_mul_pr(gmx_pmecorrV_pr(brsq_SSE2), beta_SSE);
441 #endif
442
443 #endif /* CALC_COUL_EWALD */
444
445 #ifdef CALC_COUL_TAB
446     /* Electrostatic interactions */
447     r_SSE0        = gmx_mul_pr(rsq_SSE0, rinv_SSE0);
448     r_SSE2        = gmx_mul_pr(rsq_SSE2, rinv_SSE2);
449     /* Convert r to scaled table units */
450     rs_SSE0       = gmx_mul_pr(r_SSE0, invtsp_SSE);
451     rs_SSE2       = gmx_mul_pr(r_SSE2, invtsp_SSE);
452     /* Truncate scaled r to an int */
453     ti_SSE0       = gmx_cvttpr_epi32(rs_SSE0);
454     ti_SSE2       = gmx_cvttpr_epi32(rs_SSE2);
455 #ifdef GMX_X86_SSE4_1
456     /* SSE4.1 floor is faster than gmx_cvtepi32_ps int->float cast */
457     rf_SSE0       = gmx_floor_pr(rs_SSE0);
458     rf_SSE2       = gmx_floor_pr(rs_SSE2);
459 #else
460     rf_SSE0       = gmx_cvtepi32_pr(ti_SSE0);
461     rf_SSE2       = gmx_cvtepi32_pr(ti_SSE2);
462 #endif
463     frac_SSE0     = gmx_sub_pr(rs_SSE0, rf_SSE0);
464     frac_SSE2     = gmx_sub_pr(rs_SSE2, rf_SSE2);
465
466     /* Load and interpolate table forces and possibly energies.
467      * Force and energy can be combined in one table, stride 4: FDV0
468      * or in two separate tables with stride 1: F and V
469      * Currently single precision uses FDV0, double F and V.
470      */
471 #ifndef CALC_ENERGIES
472     load_table_f(tab_coul_F, ti_SSE0, ti0, ctab0_SSE0, ctab1_SSE0);
473     load_table_f(tab_coul_F, ti_SSE2, ti2, ctab0_SSE2, ctab1_SSE2);
474 #else
475 #ifdef TAB_FDV0
476     load_table_f_v(tab_coul_F, ti_SSE0, ti0, ctab0_SSE0, ctab1_SSE0, ctabv_SSE0);
477     load_table_f_v(tab_coul_F, ti_SSE2, ti2, ctab0_SSE2, ctab1_SSE2, ctabv_SSE2);
478 #else
479     load_table_f_v(tab_coul_F, tab_coul_V, ti_SSE0, ti0, ctab0_SSE0, ctab1_SSE0, ctabv_SSE0);
480     load_table_f_v(tab_coul_F, tab_coul_V, ti_SSE2, ti2, ctab0_SSE2, ctab1_SSE2, ctabv_SSE2);
481 #endif
482 #endif
483     fsub_SSE0     = gmx_add_pr(ctab0_SSE0, gmx_mul_pr(frac_SSE0, ctab1_SSE0));
484     fsub_SSE2     = gmx_add_pr(ctab0_SSE2, gmx_mul_pr(frac_SSE2, ctab1_SSE2));
485     frcoul_SSE0   = gmx_mul_pr(qq_SSE0, gmx_sub_pr(rinv_ex_SSE0, gmx_mul_pr(fsub_SSE0, r_SSE0)));
486     frcoul_SSE2   = gmx_mul_pr(qq_SSE2, gmx_sub_pr(rinv_ex_SSE2, gmx_mul_pr(fsub_SSE2, r_SSE2)));
487
488 #ifdef CALC_ENERGIES
489     vc_sub_SSE0   = gmx_add_pr(ctabv_SSE0, gmx_mul_pr(gmx_mul_pr(mhalfsp_SSE, frac_SSE0), gmx_add_pr(ctab0_SSE0, fsub_SSE0)));
490     vc_sub_SSE2   = gmx_add_pr(ctabv_SSE2, gmx_mul_pr(gmx_mul_pr(mhalfsp_SSE, frac_SSE2), gmx_add_pr(ctab0_SSE2, fsub_SSE2)));
491 #endif
492 #endif /* CALC_COUL_TAB */
493
494 #if defined CALC_ENERGIES && (defined CALC_COUL_EWALD || defined CALC_COUL_TAB)
495 #ifndef NO_SHIFT_EWALD
496     /* Add Ewald potential shift to vc_sub for convenience */
497 #ifdef CHECK_EXCLS
498     vc_sub_SSE0   = gmx_add_pr(vc_sub_SSE0, gmx_and_pr(sh_ewald_SSE, int_SSE0));
499     vc_sub_SSE2   = gmx_add_pr(vc_sub_SSE2, gmx_and_pr(sh_ewald_SSE, int_SSE2));
500 #else
501     vc_sub_SSE0   = gmx_add_pr(vc_sub_SSE0, sh_ewald_SSE);
502     vc_sub_SSE2   = gmx_add_pr(vc_sub_SSE2, sh_ewald_SSE);
503 #endif
504 #endif
505
506     vcoul_SSE0    = gmx_mul_pr(qq_SSE0, gmx_sub_pr(rinv_ex_SSE0, vc_sub_SSE0));
507     vcoul_SSE2    = gmx_mul_pr(qq_SSE2, gmx_sub_pr(rinv_ex_SSE2, vc_sub_SSE2));
508 #endif
509
510 #ifdef CALC_ENERGIES
511     /* Mask energy for cut-off and diagonal */
512     vcoul_SSE0    = gmx_and_pr(vcoul_SSE0, wco_SSE0);
513     vcoul_SSE2    = gmx_and_pr(vcoul_SSE2, wco_SSE2);
514 #endif
515
516 #endif /* CALC_COULOMB */
517
518 #ifdef CALC_LJ
519     /* Lennard-Jones interaction */
520
521 #ifdef VDW_CUTOFF_CHECK
522     wco_vdw_SSE0  = gmx_cmplt_pr(rsq_SSE0, rcvdw2_SSE);
523 #ifndef HALF_LJ
524     wco_vdw_SSE2  = gmx_cmplt_pr(rsq_SSE2, rcvdw2_SSE);
525 #endif
526 #else
527     /* Same cut-off for Coulomb and VdW, reuse the registers */
528 #define     wco_vdw_SSE0    wco_SSE0
529 #define     wco_vdw_SSE2    wco_SSE2
530 #endif
531
532 #ifndef LJ_COMB_LB
533     rinvsix_SSE0  = gmx_mul_pr(rinvsq_SSE0, gmx_mul_pr(rinvsq_SSE0, rinvsq_SSE0));
534 #ifdef EXCL_FORCES
535     rinvsix_SSE0  = gmx_and_pr(rinvsix_SSE0, int_SSE0);
536 #endif
537 #ifndef HALF_LJ
538     rinvsix_SSE2  = gmx_mul_pr(rinvsq_SSE2, gmx_mul_pr(rinvsq_SSE2, rinvsq_SSE2));
539 #ifdef EXCL_FORCES
540     rinvsix_SSE2  = gmx_and_pr(rinvsix_SSE2, int_SSE2);
541 #endif
542 #endif
543 #ifdef VDW_CUTOFF_CHECK
544     rinvsix_SSE0  = gmx_and_pr(rinvsix_SSE0, wco_vdw_SSE0);
545 #ifndef HALF_LJ
546     rinvsix_SSE2  = gmx_and_pr(rinvsix_SSE2, wco_vdw_SSE2);
547 #endif
548 #endif
549     FrLJ6_SSE0    = gmx_mul_pr(c6_SSE0, rinvsix_SSE0);
550 #ifndef HALF_LJ
551     FrLJ6_SSE2    = gmx_mul_pr(c6_SSE2, rinvsix_SSE2);
552 #endif
553     FrLJ12_SSE0   = gmx_mul_pr(c12_SSE0, gmx_mul_pr(rinvsix_SSE0, rinvsix_SSE0));
554 #ifndef HALF_LJ
555     FrLJ12_SSE2   = gmx_mul_pr(c12_SSE2, gmx_mul_pr(rinvsix_SSE2, rinvsix_SSE2));
556 #endif
557 #endif /* not LJ_COMB_LB */
558
559 #ifdef LJ_COMB_LB
560     sir_SSE0      = gmx_mul_pr(sig_SSE0, rinv_SSE0);
561 #ifndef HALF_LJ
562     sir_SSE2      = gmx_mul_pr(sig_SSE2, rinv_SSE2);
563 #endif
564     sir2_SSE0     = gmx_mul_pr(sir_SSE0, sir_SSE0);
565 #ifndef HALF_LJ
566     sir2_SSE2     = gmx_mul_pr(sir_SSE2, sir_SSE2);
567 #endif
568     sir6_SSE0     = gmx_mul_pr(sir2_SSE0, gmx_mul_pr(sir2_SSE0, sir2_SSE0));
569 #ifdef EXCL_FORCES
570     sir6_SSE0     = gmx_and_pr(sir6_SSE0, int_SSE0);
571 #endif
572 #ifndef HALF_LJ
573     sir6_SSE2     = gmx_mul_pr(sir2_SSE2, gmx_mul_pr(sir2_SSE2, sir2_SSE2));
574 #ifdef EXCL_FORCES
575     sir6_SSE2     = gmx_and_pr(sir6_SSE2, int_SSE2);
576 #endif
577 #endif
578 #ifdef VDW_CUTOFF_CHECK
579     sir6_SSE0     = gmx_and_pr(sir6_SSE0, wco_vdw_SSE0);
580 #ifndef HALF_LJ
581     sir6_SSE2     = gmx_and_pr(sir6_SSE2, wco_vdw_SSE2);
582 #endif
583 #endif
584     FrLJ6_SSE0    = gmx_mul_pr(eps_SSE0, sir6_SSE0);
585 #ifndef HALF_LJ
586     FrLJ6_SSE2    = gmx_mul_pr(eps_SSE2, sir6_SSE2);
587 #endif
588     FrLJ12_SSE0   = gmx_mul_pr(FrLJ6_SSE0, sir6_SSE0);
589 #ifndef HALF_LJ
590     FrLJ12_SSE2   = gmx_mul_pr(FrLJ6_SSE2, sir6_SSE2);
591 #endif
592 #if defined CALC_ENERGIES
593     /* We need C6 and C12 to calculate the LJ potential shift */
594     sig2_SSE0     = gmx_mul_pr(sig_SSE0, sig_SSE0);
595 #ifndef HALF_LJ
596     sig2_SSE2     = gmx_mul_pr(sig_SSE2, sig_SSE2);
597 #endif
598     sig6_SSE0     = gmx_mul_pr(sig2_SSE0, gmx_mul_pr(sig2_SSE0, sig2_SSE0));
599 #ifndef HALF_LJ
600     sig6_SSE2     = gmx_mul_pr(sig2_SSE2, gmx_mul_pr(sig2_SSE2, sig2_SSE2));
601 #endif
602     c6_SSE0       = gmx_mul_pr(eps_SSE0, sig6_SSE0);
603 #ifndef HALF_LJ
604     c6_SSE2       = gmx_mul_pr(eps_SSE2, sig6_SSE2);
605 #endif
606     c12_SSE0      = gmx_mul_pr(c6_SSE0, sig6_SSE0);
607 #ifndef HALF_LJ
608     c12_SSE2      = gmx_mul_pr(c6_SSE2, sig6_SSE2);
609 #endif
610 #endif
611 #endif /* LJ_COMB_LB */
612
613 #endif /* CALC_LJ */
614
615 #ifdef CALC_ENERGIES
616 #ifdef ENERGY_GROUPS
617     /* Extract the group pair index per j pair.
618      * Energy groups are stored per i-cluster, so things get
619      * complicated when the i- and j-cluster size don't match.
620      */
621     {
622         int egps_j;
623 #if UNROLLJ == 2
624         egps_j    = nbat->energrp[cj>>1];
625         egp_jj[0] = ((egps_j >> ((cj & 1)*egps_jshift)) & egps_jmask)*egps_jstride;
626 #else
627         /* We assume UNROLLI <= UNROLLJ */
628         int jdi;
629         for (jdi = 0; jdi < UNROLLJ/UNROLLI; jdi++)
630         {
631             int jj;
632             egps_j = nbat->energrp[cj*(UNROLLJ/UNROLLI)+jdi];
633             for (jj = 0; jj < (UNROLLI/2); jj++)
634             {
635                 egp_jj[jdi*(UNROLLI/2)+jj] = ((egps_j >> (jj*egps_jshift)) & egps_jmask)*egps_jstride;
636             }
637         }
638 #endif
639     }
640 #endif
641
642 #ifdef CALC_COULOMB
643 #ifndef ENERGY_GROUPS
644     vctotSSE      = gmx_add_pr(vctotSSE, gmx_add_pr(vcoul_SSE0, vcoul_SSE2));
645 #else
646     add_ener_grp_halves(vcoul_SSE0, vctp[0], vctp[1], egp_jj);
647     add_ener_grp_halves(vcoul_SSE2, vctp[2], vctp[3], egp_jj);
648 #endif
649 #endif
650
651 #ifdef CALC_LJ
652     /* Calculate the LJ energies */
653     VLJ6_SSE0     = gmx_mul_pr(sixthSSE, gmx_sub_pr(FrLJ6_SSE0, gmx_mul_pr(c6_SSE0, sh_invrc6_SSE)));
654 #ifndef HALF_LJ
655     VLJ6_SSE2     = gmx_mul_pr(sixthSSE, gmx_sub_pr(FrLJ6_SSE2, gmx_mul_pr(c6_SSE2, sh_invrc6_SSE)));
656 #endif
657     VLJ12_SSE0    = gmx_mul_pr(twelvethSSE, gmx_sub_pr(FrLJ12_SSE0, gmx_mul_pr(c12_SSE0, sh_invrc12_SSE)));
658 #ifndef HALF_LJ
659     VLJ12_SSE2    = gmx_mul_pr(twelvethSSE, gmx_sub_pr(FrLJ12_SSE2, gmx_mul_pr(c12_SSE2, sh_invrc12_SSE)));
660 #endif
661
662     VLJ_SSE0      = gmx_sub_pr(VLJ12_SSE0, VLJ6_SSE0);
663 #ifndef HALF_LJ
664     VLJ_SSE2      = gmx_sub_pr(VLJ12_SSE2, VLJ6_SSE2);
665 #endif
666     /* The potential shift should be removed for pairs beyond cut-off */
667     VLJ_SSE0      = gmx_and_pr(VLJ_SSE0, wco_vdw_SSE0);
668 #ifndef HALF_LJ
669     VLJ_SSE2      = gmx_and_pr(VLJ_SSE2, wco_vdw_SSE2);
670 #endif
671 #ifdef CHECK_EXCLS
672     /* The potential shift should be removed for excluded pairs */
673     VLJ_SSE0      = gmx_and_pr(VLJ_SSE0, int_SSE0);
674 #ifndef HALF_LJ
675     VLJ_SSE2      = gmx_and_pr(VLJ_SSE2, int_SSE2);
676 #endif
677 #endif
678 #ifndef ENERGY_GROUPS
679     VvdwtotSSE    = gmx_add_pr(VvdwtotSSE,
680 #ifndef HALF_LJ
681                                gmx_add_pr(VLJ_SSE0, VLJ_SSE2)
682 #else
683                                VLJ_SSE0
684 #endif
685                                );
686 #else
687     add_ener_grp_halves(VLJ_SSE0, vvdwtp[0], vvdwtp[1], egp_jj);
688 #ifndef HALF_LJ
689     add_ener_grp_halves(VLJ_SSE2, vvdwtp[2], vvdwtp[3], egp_jj);
690 #endif
691 #endif
692 #endif /* CALC_LJ */
693 #endif /* CALC_ENERGIES */
694
695 #ifdef CALC_LJ
696     fscal_SSE0    = gmx_mul_pr(rinvsq_SSE0,
697 #ifdef CALC_COULOMB
698                                gmx_add_pr(frcoul_SSE0,
699 #else
700                                (
701 #endif
702                                           gmx_sub_pr(FrLJ12_SSE0, FrLJ6_SSE0)));
703 #else
704     fscal_SSE0    = gmx_mul_pr(rinvsq_SSE0, frcoul_SSE0);
705 #endif /* CALC_LJ */
706 #if defined CALC_LJ && !defined HALF_LJ
707     fscal_SSE2    = gmx_mul_pr(rinvsq_SSE2,
708 #ifdef CALC_COULOMB
709                                gmx_add_pr(frcoul_SSE2,
710 #else
711                                (
712 #endif
713                                           gmx_sub_pr(FrLJ12_SSE2, FrLJ6_SSE2)));
714 #else
715     /* Atom 2 and 3 don't have LJ, so only add Coulomb forces */
716     fscal_SSE2    = gmx_mul_pr(rinvsq_SSE2, frcoul_SSE2);
717 #endif
718
719     /* Calculate temporary vectorial force */
720     tx_SSE0       = gmx_mul_pr(fscal_SSE0, dx_SSE0);
721     tx_SSE2       = gmx_mul_pr(fscal_SSE2, dx_SSE2);
722     ty_SSE0       = gmx_mul_pr(fscal_SSE0, dy_SSE0);
723     ty_SSE2       = gmx_mul_pr(fscal_SSE2, dy_SSE2);
724     tz_SSE0       = gmx_mul_pr(fscal_SSE0, dz_SSE0);
725     tz_SSE2       = gmx_mul_pr(fscal_SSE2, dz_SSE2);
726
727     /* Increment i atom force */
728     fix_SSE0      = gmx_add_pr(fix_SSE0, tx_SSE0);
729     fix_SSE2      = gmx_add_pr(fix_SSE2, tx_SSE2);
730     fiy_SSE0      = gmx_add_pr(fiy_SSE0, ty_SSE0);
731     fiy_SSE2      = gmx_add_pr(fiy_SSE2, ty_SSE2);
732     fiz_SSE0      = gmx_add_pr(fiz_SSE0, tz_SSE0);
733     fiz_SSE2      = gmx_add_pr(fiz_SSE2, tz_SSE2);
734
735     /* Decrement j atom force */
736     gmx_store_hpr(f+ajx,
737                   gmx_sub_hpr( gmx_load_hpr(f+ajx), gmx_sum4_hpr(tx_SSE0, tx_SSE2) ));
738     gmx_store_hpr(f+ajy,
739                   gmx_sub_hpr( gmx_load_hpr(f+ajy), gmx_sum4_hpr(ty_SSE0, ty_SSE2) ));
740     gmx_store_hpr(f+ajz,
741                   gmx_sub_hpr( gmx_load_hpr(f+ajz), gmx_sum4_hpr(tz_SSE0, tz_SSE2) ));
742 }
743
744 #undef  rinv_ex_SSE0
745 #undef  rinv_ex_SSE2
746
747 #undef  wco_vdw_SSE0
748 #undef  wco_vdw_SSE2
749
750 #undef  CUTOFF_BLENDV
751
752 #undef  EXCL_FORCES