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