https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126101

--- Comment #2 from Reshma Roy <Reshma.Roy at amd dot com> ---
In oneAPI it builds the vector and then tears them down to scalar at the
boundary. Only (d,c) lane pair is vectorized. Fast_d, fast_c and vdw_d, vdw_c
live in 2-lane %xmm; fast_a, fast_b stays scalar.  It does not keep
fast_{d,c,b,a} vectorized through the polynomial. The net is still profitable
(SLP vectorized with cost -4 and with tree size 11): the win is the two packed
FMAs plus the vaddpd, and the only added overhead is the vmovddup build-ups and
a vshufpd tear-down. 

The snippet of the assembly generated from oneapi. Hope this clarifies it.

vmovddup        %xmm8, %xmm10               # xmm10 = xmm8[0,0]  -> {B, B}
vmulpd  -32(%rbp), %xmm10, %xmm10           # {B*t[2] , B*t[3]}
:
vmovddup        %xmm9, %xmm14               # xmm14 = xmm9[0,0]  -> {A, A}
vfmsub231pd     -48(%rbp), %xmm14, %xmm10   # xmm10 = (xmm14 * mem) - xmm10  ->
{A*t[0], A*t[1]} - xmm10  -> {vdw_d, vdw_c}
:
vmovddup        %xmm11, %xmm13              # xmm13 = xmm11[0,0] -> {kqq, kqq}
vmulpd  16(%rbp), %xmm13, %xmm13            # {kqq * table_four_i[8],
kqq*table_four_i[9] -> {fast_d, fast_c}
:
vaddpd  %xmm10, %xmm13, %xmm11              # {fast_d + vdw_d,  fast_c + vdw_c}
vshufpd $1, %xmm11, %xmm11, %xmm15          # xmm15 = xmm11[1,0]  -> fast_c +
vdw_c into a loc
vfmadd231sd %xmm11, %xmm7, %xmm15           # xmm15 = (xmm7 * xmm11) + xmm15 ->
fast_dir
:

vmovddup        %xmm15, %xmm11       # xmm11 = xmm15[0,0] -> broadcast fast_dir
vsubpd  %xmm11, %xmm16, %xmm11       # f_j->{x,y} -= fast_dir
vmovupd %xmm11, (%r11,%r13,8)        # store x,y
vmovsd  16(%r11,%r13,8), %xmm11      # xmm11 = mem[0],zero  # load f_j->z
vsubsd  %xmm15, %xmm11, %xmm11       # f_j->z -= fast_dir  (scalar)
vmovsd  %xmm11, 16(%r11,%r13,8)      # store z

Reply via email to