https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126101
Bug ID: 126101
Summary: GCC trunk vs Intel oneAPI : Missed SLP vectorization
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: Reshma.Roy at amd dot com
Target Milestone: ---
Created attachment 64927
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=64927&action=edit
The preprocessed input file to be used for the command mentioned in the
description
----------------------------------------------------------------------
GCC trunk vs Intel oneAPI : Missed SLP vectorization
----------------------------------------------------------------------
Compiler Versions
oneAPI : Intel oneAPI 2025.3
gcc trunk : gcc (GCC) 17.0.0 20260623 (experimental)
The gcc behavior is compared with oneapi for a portion of the code in the
508.namd_r benchmark at location ComputeNonbondedBase2.h:129. Oneapi vectorizes
it whereas gcc failed to do so.
Reduced testcase from the benchmark:
------------------------------------
typedef double BigReal;
typedef float Charge;
typedef struct { BigReal x, y, z; } Vector;
typedef Vector Position;
typedef Vector Force;
typedef struct {
Position position;
Charge charge;
short vdwType;
unsigned char partition;
unsigned int bits;
} CompAtom;
typedef struct { BigReal A, B; } LJTableEntry;
__attribute__((noinline))
void calc_pair_energy_fullelect(
int npairi,
const int *restrict pairlisti,
const unsigned int *restrict r2iilist,
int r2_delta_expc,
const BigReal *restrict r2list,
const BigReal *restrict r2_table,
const BigReal *restrict table_four,
const CompAtom *restrict p_1,
const LJTableEntry *restrict lj_row,
BigReal scaling, BigReal kq_i,
Force *restrict f_1,
BigReal *restrict out_vdwEnergy,
BigReal *restrict out_electEnergy)
{
BigReal vdwEnergy = 0, electEnergy = 0;
for (int k = 0; k < npairi; ++k) {
int table_i = (r2iilist[2 * k] >> 14) + r2_delta_expc;
const int j = pairlisti[k];
const CompAtom *p_j = p_1 + j;
BigReal diffa = r2list[k] - r2_table[table_i];
const BigReal *const table_four_i = table_four + 16 * table_i;
const LJTableEntry *lj_pars = lj_row + 2 * p_j->vdwType;
BigReal kqq = kq_i * p_j->charge;
/* ---- the opportunity:(Base2.h:129-132) ------------------ */
const BigReal A = scaling * lj_pars->A;
const BigReal B = scaling * lj_pars->B;
BigReal vdw_d = A * table_four_i[0] - B * table_four_i[2];
BigReal vdw_c = A * table_four_i[1] - B * table_four_i[3];
BigReal vdw_b = A * table_four_i[4] - B * table_four_i[6];
BigReal vdw_a = A * table_four_i[5] - B * table_four_i[7];
/* ----------------------------------------------------------*/
BigReal vdw_val =
((diffa * vdw_d * (1 / 6.) + vdw_c * (1 / 4.)) * diffa
+ vdw_b * (1 / 2.)) * diffa + vdw_a;
vdwEnergy -= vdw_val;
BigReal fast_d = kqq * table_four_i[8];
BigReal fast_c = kqq * table_four_i[9];
BigReal fast_b = kqq * table_four_i[10];
BigReal fast_a = kqq * table_four_i[11];
BigReal fast_val =
((diffa * fast_d * (1 / 6.) + fast_c * (1 / 4.)) * diffa
+ fast_b * (1 / 2.)) * diffa + fast_a;
electEnergy -= fast_val;
/*--------------------------------------------*/
fast_d += vdw_d;
fast_c += vdw_c;
fast_b += vdw_b;
fast_a += vdw_a;
/* --------------------------------------------*/
BigReal fast_dir = (diffa * fast_d + fast_c) * diffa + fast_b;
Force *f_j = f_1 + j;
f_j->x -= fast_dir;
f_j->y -= fast_dir;
f_j->z -= fast_dir;
}
*out_vdwEnergy = vdwEnergy;
*out_electEnergy = electEnergy;
}
Commands used:
---------------
gcc -O3 -march=znver5 -fdump-tree-slp-details -fopt-info-vec-missed -S -o
opp3_vdw_coeff.s opp3_vdw_coeff.i 2> gcc_vec_missed.txt
icx -O3 -march=graniterapids -S -Rpass=slp-vectorizer -o opp3_vdw_coeff_icx.s
opp3_vdw_coeff.i 2> icx_vect.log
>From the gcc slp dump, we could not see any logs stating the discovery of SLP
for fast_* which is the reduction that consumes the vdw_*. Also, the missed-opt
log contains only loop-vectorizer messages unrelated to the coefficient group;
there is no BB-SLP missed-opt entry for vdw_*, looks like SLP is never seeded
on it in the first place. Even though BB-SLP is active and succeeds on the
neighboring store group. In icx the Rpass log states successful vectorization.
opp3_vdw_coeff.c:175:16: remark: SLP vectorized with cost -4 and with tree size
11 [-Rpass=slp-vectorizer]
5 175 | fast_c += vdw_c;
6 | ^
In gcc, the vdw_* group is emitted as scalar vmulsd + vfmsub231sd/vfmsub132sd.
icx, in contrast, reports SLP vectorized with cost -4 and tree size 11 at
fast_c += vdw_c and packs the group into 2-lane %xmm (vmovddup + vmulpd +
vfmsub231pd). This seems to be like SLP seed/discovery gap on straight-line
group of four A*table_four_i[i] - B*table_four_i[j] expression which share
scalars A,B and use contiguous loads.