Non, à moins que je suis absent Quelque chose d'intelligent, ptest
avec deux registres inconnus n'est généralement pas utile pour vérifier certaines propriétés sur les deux. (Autre que des choses évidentes que vous auriez déjà besoin d'un bit-AND pour, comme l'intersection entre deux bitmaps).
Pour tester deux registres pour les deux étant tout à zéro, OU les ensemble et PTEST que contre lui-même.
ptest xmm0, xmm1
produit deux résultats:
- ZF = est
xmm0 & xmm1
tout à zéro?
- CF = est
(~xmm0) & xmm1
tout-zéro?
Si le deuxième vecteur est entièrement nul, les indicateurs ne dépendent pas du tout des bits du premier vecteur.
Il peut être utile de considérer les vérifications "tout-zéro" comme NOT(bitwise horizontal-OR())
des résultats AND et ANDNOT. Mais probablement pas, parce que c'est trop d'étapes pour que mon cerveau puisse y réfléchir facilement. Cette séquence de AND vertical et d'OR-OU peut-être plus facile à comprendre pourquoi PTEST ne vous en dit pas beaucoup sur une combinaison de deux registres inconnus, tout comme l'instruction TEST entière.
Voici une table de vérité pour un ptest a,mask
à 2 bits. Espérons que cela aide à penser à des mélanges de zéros et de zéros avec des entrées 128b.
Notez que CF(a,mask) == ZF(~a,mask)
.
a mask ZF CF
00 00 1 1
01 00 1 1
10 00 1 1
11 00 1 1
00 01 1 0
01 01 0 1
10 01 1 0
11 01 0 1
00 10 1 0
01 10 1 0
10 10 0 1
11 10 0 1
00 11 1 0
01 11 0 0
10 11 0 0
11 11 0 1
Intel's intrinsics guide lists 2 interesting intrinsics for it. Notez le nom des arguments: a
et mask
sont un indice qu'ils vous disent sur les parties de a
sélectionnés par un masque AND connu.
_mm_test_mix_ones_zeros (__m128i a, __m128i mask)
: retourne (ZF == 0 && CF == 0)
_mm_test_all_zeros (__m128i a, __m128i mask)
: retourne ZF
Il y a aussi les versions plus simplement nommées:
int _mm_testc_si128 (__m128i a, __m128i b)
: retourne CF
int _mm_testnzc_si128 (__m128i a, __m128i b)
: retour s (ZF == 0 && CF == 0)
int _mm_testz_si128 (__m128i a, __m128i b)
: retourne ZF
Il y a AVX2 __m256i
versions de ces intrinsics, mais le guide répertorie uniquement les all_zeros et mix_ones_zeros des versions noms pour __m128i
opérandes.
Si vous voulez tester une autre condition de C ou C++, vous devez utiliser testc
et testz
avec les mêmes opérandes, et nous espérons que votre compilateur se rend compte qu'il n'a besoin que de faire un PTEST, et je l'espère même utiliser un seul JCC , SETCC ou CMOVCC pour implémenter votre logique. (Je vous recommande de vérifier l'asm, au moins pour le compilateur le plus pour vous.)
Notez que _mm_testz_si128(v, set1(0xff))
est toujours le même que _mm_testz_si128(v,v)
, parce que c'est et comment fonctionne. Mais ce n'est pas vrai pour le résultat des FC.
Vous pouvez vérifier un vecteur étant tous-les utilisant
bool is_all_ones = _mm_testc_si128(v, _mm_set1_epi8(0xff));
Ceci est probablement pas plus rapide, mais plus petite taille du code, qu'un PCMPEQB contre un vecteur de tous-les, puis l'habituel movemask + cmp. Cela n'évite pas la nécessité d'une constante vectorielle. PTEST présente l'avantage de ne détruire aucun opérande d'entrée, même sans AVX.