Puisque je ne trouve pas de dupe approprié, je vais juste le poster.
L'idée principale ici est de faire usage de pshufb
à double usage d'une recherche de table parallèle de 16 entrées pour inverser les bits de chaque quartet. Inverser les octets est évident. Inverser l'ordre des deux grignoter dans chaque octet pourrait être fait en le construisant dans les tables de recherche (sauvegarde un décalage) ou en déplaçant explicitement la partie basse grignotant (sauvegarde une table).
Quelque chose comme ça au total, non testé:
__m256i rbit32(__m256i x) {
__m256i shufbytes = _mm256_setr_epi8(3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12);
__m256i luthigh = _mm256_setr_epi8(0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15, 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15);
__m256i lutlow = _mm256_slli_epi16(luthigh, 4);
__m256i lowmask = _mm256_set1_epi8(15);
__m256i rbytes = _mm256_shuffle_epi8(x, shufbytes);
__m256i high = _mm256_shuffle_epi8(lutlow, _mm256_and_si256(rbytes, lowmask));
__m256i low = _mm256_shuffle_epi8(luthigh, _mm256_and_si256(_mm256_srli_epi16(rbytes, 4), lowmask));
return _mm256_or_si256(low, high);
}
Dans un contexte typique dans une boucle, ces charges doivent être évacuées. Curieusement Clang uses 4 shuffles, il duplique le premier shuffle.
Vous voulez inverser les bits d'un seul int32 dans un registre d'entiers AVX2, ou vous voulez inverser les bits de chacun de ces 8 entiers? –
@JohnZwinck, ça n'a pas vraiment d'importance: une fois que j'ai l'idée de comment faire ça, je peux mélanger les valeurs de 32 bits dans le registre comme je le souhaite. –
L'ancienne façon (inverser les octets, inverser les groupes de 4 avec 'pshufb', résultats OU) généraliser à AVX2, je ne peux pas trouver immédiatement la dupe si – harold