[X86] Redundant spill/reloads when indexing ext_vector_type with non-constant
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
This appears to happen only in specific circumstances when the vector comes from memory (indexing vectors from a large struct appears to be fine, minus the redundant index masking). The spill is never hoisted from the loop in the from-register case, but the pointer-cast workaround has been reliable.
Godbolt: https://godbolt.org/z/veTnvaqGP
```cpp
using v_int = int [[clang::ext_vector_type(16)]];
int ProcessItems(v_int a, int mask) {
int s = 0;
for (; mask != 0; mask &= mask - 1) {
int i = __builtin_ctz(mask);
s += a[i];
}
return s;
}
int ProcessItems_B(const v_int& a, int mask) {
int s = 0;
for (; mask != 0; mask &= mask - 1) {
int i = __builtin_ctz(mask);
s += a[i];
}
return s;
}
// Workaround
int ProcessItems_C(const v_int& a, int mask) {
int s = 0;
for (; mask != 0; mask &= mask - 1) {
int i = __builtin_ctz(mask);
s += ((int*)&a)[i];
}
return s;
}
```
```asm
ProcessItems_B(int vector[16] const&, int):
test esi, esi
je .LBB1_1
push rbp
mov rbp, rsp
and rsp, -32
sub rsp, 96
vmovaps ymm0, ymmword ptr [rdi]
vmovaps ymm1, ymmword ptr [rdi + 32]
xor eax, eax
.LBB1_4:
tzcnt ecx, esi
vmovaps ymmword ptr [rsp], ymm0
vmovaps ymmword ptr [rsp + 32], ymm1
and ecx, 15
add eax, dword ptr [rsp + 4*rcx]
blsr esi, esi
jne .LBB1_4
mov rsp, rbp
pop rbp
vzeroupper
ret
.LBB1_1:
xor eax, eax
ret
```
```asm
ProcessItems_C(int vector[16] const&, int):
xor eax, eax
test esi, esi
je .LBB2_2
.LBB2_1:
tzcnt ecx, esi
add eax, dword ptr [rdi + 4*rcx]
blsr esi, esi
jne .LBB2_1
.LBB2_2:
ret
```
Contributor guide
Research direction
Start with the Godbolt reproducer and compare ProcessItems_B with the pointer-cast workaround in ProcessItems_C. Investigate the compiler path for non-constant indexing of ext_vector_type values passed by reference, then verify generated x86 code. Done means the reference case no longer emits redundant per-iteration vector spills and reloads while preserving the loop's result.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100