[X86] `movmsk(por(andn(bits,mask), andn(bits,mask)))` gets pessimized
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
https://c.godbolt.org/z/7YYEz9r51
This code:
```c
#include
#include
int any_signaling_nan(double* src, uint64_t n) {
for (uint64_t i = 0; i < n; i += 2) {
__m128i a = _mm_loadu_si128((void*)(src + i*2));
__m128i b = _mm_loadu_si128((void*)(src + i*2 + 2));
__m128i a_nan = (__m128i)_mm_cmpunord_pd((__m128d)a, (__m128d)a);
__m128i b_nan = (__m128i)_mm_cmpunord_pd((__m128d)b, (__m128d)b);
__m128i a_bad = _mm_andnot_si128(_mm_slli_epi32(a, 12), a_nan);
__m128i b_bad = _mm_andnot_si128(_mm_slli_epi32(b, 12), b_nan);
__m128i any_bad = _mm_or_si128(a_bad, b_bad);
if (_mm_movemask_pd((__m128d)any_bad) != 0) return 1;
}
return 0;
}
```
on baseline x86, compiles to a core loop of:
```asm
.LBB0_5:
movupd xmm2, xmmword ptr [rdi - 16]
movupd xmm3, xmmword ptr [rdi]
movapd xmm4, xmm2
cmpunordpd xmm4, xmm0
movapd xmm5, xmm3
cmpunordpd xmm5, xmm0
pslld xmm2, 12
pslld xmm3, 12
pand xmm2, xmm4
pandn xmm4, xmm1
por xmm4, xmm2
pand xmm3, xmm5
pandn xmm5, xmm1
por xmm5, xmm3
pand xmm5, xmm4
movmskpd ecx, xmm5
cmp ecx, 3
jne .LBB0_6
add rax, 2
add rdi, 32
cmp rax, rsi
jb .LBB0_5
```
which is four more SIMD instructions than the literal translation (which gcc produces); seems the 2\*+`pandn`+`por` gets compiled to 2\*`pandn`+3\*`pand`+2\*`por`.
(for a slightly-more-reduced version, the `_mm_slli_epi32`s can be replaced with their first argument, so it's not the unusual element width transition)
Contributor guide
Assessment
This issue has not been assessed yet.