<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/70259>70259</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
SLP vectorization causes 1.75x slowdown with march=skylake-avx512 due to vgatherdps
</td>
</tr>
<tr>
<th>Labels</th>
<td>
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
abadams
</td>
</tr>
</table>
<pre>
I think the SLP cost model might be wrong for vector gathers on skylake.
Consider the following code which repeatedly permutes an array:
```
void f(const float *__restrict__ src, const int *__restrict__ idx, float *__restrict__ dst, int n) {
for (int i = 0; i < n; i += 8) {
dst[i] = src[idx[i]];
dst[i + 1] = src[idx[i + 1]];
dst[i + 2] = src[idx[i + 2]];
dst[i + 3] = src[idx[i + 3]];
dst[i + 4] = src[idx[i + 4]];
dst[i + 5] = src[idx[i + 5]];
dst[i + 6] = src[idx[i + 6]];
dst[i + 7] = src[idx[i + 7]];
}
}
int main(int argc, char **argv) {
const int n = 16 * 1024;
float src[n], dst[n];
int idx[n];
for (int i = 0; i < n; i++) {
// Some arbitrary permutation
idx[i] = (i * 17 + 37) % n;
src[i] = dst[i] = 0;
}
src[17] = 17.0f;
for (int i = 0; i < 100000; i++) {
f(&src[0], &idx[0], &dst[0], n);
f(&dst[0], &idx[0], &src[0], n);
}
// Introduce a dependence on the output
return dst[0] == 17.0f ? 1 : 0;
}
```
Compiled with top of tree clang with `-march=skylake -O3` it takes about 4.2 seconds to run on my i9-9960X. Compiled with `-march=skylake -O3 -fno-slp-vectorization` it takes 2.4 seconds.
The only salient difference in the assembly is that slp vectorization has packed the eight stores in `f` into a gather intrinsic. Here's the inner loop assembly with slp vectorization on (with unrolling off for brevity):
```
.LBB1_4: # %for.body.i
# Parent Loop BB1_3 Depth=1
# => This Inner Loop Header: Depth=2
vmovups 32(%rsp,%rcx,4), %ymm0
vpxor %xmm1, %xmm1, %xmm1
vpcmpeqd %ymm2, %ymm2, %ymm2
vgatherdps %ymm2, (%r14,%ymm0,4), %ymm1
vmovups %ymm1, 65568(%rsp,%rcx,4)
addq $8, %rcx
cmpq $16376, %rcx # imm = 0x3FF8
jb .LBB1_4
```
and here it is with slp vectorization off:
```
.LBB1_4: # %for.body.i
# Parent Loop BB1_3 Depth=1
# => This Inner Loop Header: Depth=2
movslq 131104(%rsp,%rcx,4), %rdx
vmovss 65536(%rsp,%rdx,4), %xmm0 # xmm0 = mem[0],zero,zero,zero
vmovss %xmm0, 32(%rsp,%rcx,4)
movslq 131108(%rsp,%rcx,4), %rdx
vmovss 65536(%rsp,%rdx,4), %xmm0 # xmm0 = mem[0],zero,zero,zero
vmovss %xmm0, 36(%rsp,%rcx,4)
movslq 131112(%rsp,%rcx,4), %rdx
vmovss 65536(%rsp,%rdx,4), %xmm0 # xmm0 = mem[0],zero,zero,zero
vmovss %xmm0, 40(%rsp,%rcx,4)
movslq 131116(%rsp,%rcx,4), %rdx
vmovss 65536(%rsp,%rdx,4), %xmm0 # xmm0 = mem[0],zero,zero,zero
vmovss %xmm0, 44(%rsp,%rcx,4)
movslq 131120(%rsp,%rcx,4), %rdx
vmovss 65536(%rsp,%rdx,4), %xmm0 # xmm0 = mem[0],zero,zero,zero
vmovss %xmm0, 48(%rsp,%rcx,4)
movslq 131124(%rsp,%rcx,4), %rdx
vmovss 65536(%rsp,%rdx,4), %xmm0 # xmm0 = mem[0],zero,zero,zero
vmovss %xmm0, 52(%rsp,%rcx,4)
movslq 131128(%rsp,%rcx,4), %rdx
vmovss 65536(%rsp,%rdx,4), %xmm0 # xmm0 = mem[0],zero,zero,zero
vmovss %xmm0, 56(%rsp,%rcx,4)
movslq 131132(%rsp,%rcx,4), %rdx
vmovd 65536(%rsp,%rdx,4), %xmm0 # xmm0 = mem[0],zero,zero,zero
vmovd %xmm0, 60(%rsp,%rcx,4)
addq $8, %rcx
cmpq $16376, %rcx # imm = 0x3FF8
jb .LBB1_4
```
Interestingly, llvm-mca has the right idea. It says the version with SLP vectorization on is 2310 cycles per 100 iterations, and the version with it off is 813 cycles per 100 iterations.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWMtu6zgS_Rp6U7AhUZZsL7zIY4wOcIG5wO3F7AJaLFnsSKSapBy7v35QlBxHfsTJZpALjGE4Elmnqk7x8BXhnNpoxCVL71n6OBKtL41dirWQonajtZH75RP4UukX8CXCrx8_ITfOQ20kVlCrTelhjfBqjd5AYSxsMffGwkb4Eq0Do8G97CvxghMWPbLorvt9MNopiTY4LUxVmVelN5AbifBaqrwEiw0Kj7LaQ4O2bj06EBqEtWLPkrv3zlgW9d_wujVKQsH4PDfaeSgqIzwwfvf8bNF5q3L__AzO5ow_QGei9LmBkjsyuIyWzlMn4TTjC2Cz-y42AIQqMD6nTgUseYSIJffh8QF0_8jvqWN-hqUPOU_vFUsfA5oyTe8pna6RvsllCPmF-CLwresWnF-H80_Ak-vw5BPw6XX49BT-Hpdex6WfCJtdh2cfhZ1dx80uhGWzx16xbw_hl6RSC6V71Qi76cRZClLSHeN3wm62Z2I5ileHJOKMrCGO-HQQttNwl6KmnPhDz0KfZhhEG1icdd2WNamavhc0zfiK8RX8MjWCsGvlrbCHiS28MnpoflR7iERhO2qzTkmzEISnIXAP7YfggDmZRdHlgaCXDhi_jWU8m0TFm_nnChBH9LlVBVqUGM-6gFE_EoxnHd13DV3yhwZaYo7p906GJpecDMMMnQzEeGzqRulJe2tkmyMIkNiglqhzpKWcVmvT-qb1R5BF31oNx3yoNm91BJasIAaW3L0bgmPo4cp92BvqRlUo4VX5ErxpwBTgLSLkldCbrpll0bgWNi9Z8thvMDD-d8KyCJQHL15ou1ib1sN0wsFhbrR04A3YVhOTeg9qMV4ssug_ExhGvOIaxoU2Y1c1426LU_90wn0fkU-mh1iD7e5Pqpuu9uBEpVB7kKoo0Iayqq6swjms19UelANf0nytGhhEglI4aET-gjIgMGy-zhuLjrywLCpCNtobEP0OTG9WaafyCfyBFhmfuYBWWqOFypjmGDrQP49rNOk-dLbamqqirdoURZgRa4tb5fdBXR_typMf9_fx85SEcOPDeEJzuzB2QuePiRpOos_AAX4KS3X-QfwocAKP2Hga0vjr7oKg_wXwZ6kcPIXCBcd_oJBoidLBOT9UYLGtzbZtHIsWCQ8zNrWuYfyBHnI6WkypZGGmpvu6jo7AZmcsixaMp7u6jnuT08ejdV43-LfsAPu65kefg8c3QKcLGVIb2IUc42mXY0jpNMn4ArtDD3-ALE2z-XWuB6yQ8u8AnM5712R06M3rpu-Ns2SWHS2uDY6q62413iWr1fzNz19rFi0Oorsuy-5XaAklWqSZrNzVeVAU_9f4e43XZusqGq04ieNoekvmVu4GAnKknyxNk-wUKU-Qu7qO3uUaXmnMa6yPW9w_aM3Jn7NovS9y-9G0vEzwA21_S4JnUW8QjG8uVN-L4DT6KsEPKvItCX4wpS4S5B9U5FsS_MR2MST4my0y6VcXGf6bLTLpVxeZ26ehU4Lyf8lPDulln1hivuF55kl7tOi80ptqTyGraluP61yEOwQd_224PCiJYgJPHpzYd-1btI7OOuEI9OvHz_OrgHLAkziCfJ9X6OgOT7dfUB5tsHEUjw5UZ-6UD7cG5WAeJ9fxg5vTSC4TuUgWYoTLOFvM-SzKOB-Vy7nMkzyZ8-liXsikSBDnQiSLeYQoF-soHqkljyhRnvI4jTif5AXP5DqK81wm0Xwes2mEtVDVhIozMXYzUs61uJxFPF2MKrHGyh3-L2qXoYLrduPYNKqU8-4I88pXuDwvVi5ahw7iySzdgavMqzSvfSlO7pdjsd2lMQfZIt1Rj2f0UWurZel94-jkGa7nG-XLdj3JTc34inLo_4wba_7C3DO-Cjwc46tA5b8BAAD___5Z3k0">