Podczas korzystania z rozszerzeń wektorów GCC dla C, jak mogę sprawdzić, czy wszystkie wartości na wektorze są równe zero?Uzyskiwanie instrukcji GCC w celu wygenerowania instrukcji PTEST podczas korzystania z rozszerzeń wektorów
Na przykład:
#include <stdint.h>
typedef uint32_t v8ui __attribute__ ((vector_size (32)));
v8ui*
foo(v8ui *mem) {
v8ui v;
for (v = (v8ui){ 1, 1, 1, 1, 1, 1, 1, 1 };
v[0] || v[1] || v[2] || v[3] || v[4] || v[5] || v[6] || v[7];
mem++)
v &= *(mem);
return mem;
}
SSE4.2 ma dyspozycję PTEST
który pozwala uruchomić test podobny do tego stosowanego jako warunek for
ale kod generowany przez GCC prostu rozpakowuje wektor i sprawdza pojedyncze elementy jeden po drugim:
.L2:
vandps (%rax), %ymm1, %ymm1
vmovdqa %xmm1, %xmm0
addq $32, %rax
vmovd %xmm0, %edx
testl %edx, %edx
jne .L2
vpextrd $1, %xmm0, %edx
testl %edx, %edx
jne .L2
vpextrd $2, %xmm0, %edx
testl %edx, %edx
jne .L2
vpextrd $3, %xmm0, %edx
testl %edx, %edx
jne .L2
vextractf128 $0x1, %ymm1, %xmm0
vmovd %xmm0, %edx
testl %edx, %edx
jne .L2
vpextrd $1, %xmm0, %edx
testl %edx, %edx
jne .L2
vpextrd $2, %xmm0, %edx
testl %edx, %edx
jne .L2
vpextrd $3, %xmm0, %edx
testl %edx, %edx
jne .L2
vzeroupper
ret
Czy istnieje sposób, aby GCC wygenerować skuteczny test na to bez powrotu do korzystania z wewnętrznej?
Aktualizacja: odsyłającym kodu przy użyciu wbudowanych nieprzenośne GCC dla (V)PTEST
:
typedef uint32_t v8ui __attribute__ ((vector_size (32)));
typedef long long int v4si __attribute__ ((vector_size (32)));
const v8ui ones = { 1, 1, 1, 1, 1, 1, 1, 1 };
v8ui*
foo(v8ui *mem) {
v8ui v;
for (v = ones;
!__builtin_ia32_ptestz256((v4si)v,
(v4si)ones);
mem++)
v &= *(mem);
return mem;
}
Nie ma sposobu, aby GCC użył prawie wszystkich instrukcji, a jeśli znajdziesz sposób, prawdopodobnie nie będzie działać na innych poziomach optymalizacji lub innych wersjach gcc. co gorsza, wyłudzanie kompilatora w celu wysłania konkretnej instrukcji zasadniczo powoduje, że twój program działa tylko (pod względem wydajności) na jednym kompilatorze. czy to naprawdę jest bardziej przenośne niż wewnętrzne lub asm? –
również z wiadomością, ptest nigdy nie będzie równoznaczny z v [0] || v [1] || v [2] || v [3] || v [4] || v [5] || v [6] || v [7], ponieważ ocena zwarcia wymaga skoku po każdym indywidualnym wyrażeniu boolowskim –
@SteveCox, może moje sformułowanie nie było jasne, moim celem jest przekonanie GCC do wygenerowania wydajnego kodu maszynowego. PTEST to tylko jeden ze sposobów. – salva