6 votes

Conversion entre SSE et NEON Intrinsics-Shuffling

J'essaie de convertir un code écrit en SSE3 intrinsèque en NEON SIMD et je suis bloqué à cause d'une fonction shuffle. GCC Intrinsèque s , Manuels ARM et d'autres forums, mais je n'ai pas trouvé de solution.

CODE :

_m128i upper = _mm_loadu_si128((__m128i*)p1);

register __m128i mask1 = _mm_set_epi8 (0x80,0x80,0x80,0x80,0x80,0x80,0x80,12,0x80,10,0x80,7,0x80,4,0x80,1);
register __m128i mask2 = _mm_set_epi8 (0x80,0x80,0x80,0x80,0x80,0x80,12,0x80,10,0x80,7,0x80,4,0x80,1,0x80);
__m128i temp1_upper = _mm_or_si128(_mm_shuffle_epi8(upper,mask1),_mm_shuffle_epi8(upper,mask2));

Bien que l'instruction vtbl1_u8(uint8x8_t,uint8x8_t) crée une table de recherche qui peut être utilisée pour affecter des valeurs à un registre de destination, elle n'opère que sur des registres de 64 bits. De plus, l'opération de mélange effectue une comparaison au départ qui doit être effectuée dans NEON et je ne sais pas comment le faire efficacement.

r0 = (mask0 & 0x80) ? 0 : SELECT(a, mask0 & 0x0f) // SELECT(a,n) extrait le nième paramètre de 8 bits de a.

r1 = (mask1 & 0x80) ? 0 : SELECT(a, mask1 & 0x0f)

...

Je ne trouve pas d'instruction qui vérifie d'abord le bit de poids fort du masque et qui sélectionne ensuite les 4 bits inférieurs du masque de manière efficace.Je sais que nous pouvons comparer chaque bit dans le registre et sélectionner ensuite les 4 bits inférieurs si la condition est spécifiée,mais j'espérais le faire de manière efficace.J'espère que quelqu'un pourra m'aider ou me fournir une référence.

Merci beaucoup,

Santé !

3voto

Jake 'Alquimista' LEE Points 1830

VTBL renvoie 0 lorsque l'index est hors plage.

Étant donné qu'il prend en charge jusqu'à deux registres Q en tant que table de recherche, il serait assez simple :

  1. charger la table de recherche dans un registre Q (Q8 par exemple)
  2. vtbl.8 d0, {q8}, d0 (où d0 contient votre masque)

Cela fera l'affaire.

Si vous voulez que les bits 4~6 restent à l'écart, vous pouvez les masquer avant vtbl.

Malheureusement, le VBIC est absolument inutile pour les applications immédiates à 8 bits.

Il faut donc sacrifier un registre initialisé en tant qu'opérande de masque de bit.

  1. vmov.u8, d1, #0x70
  2. charger la table de recherche dans un registre Q (Q8 par exemple)
  3. vbic.i8 d0, d0, d1
  4. vtbl.8 d0, {q8}, d0 (où d0 contient votre masque)

3voto

Trevor Robinson Points 3657

Il vous suffit d'utiliser vtbl2_u8 deux fois, en divisant l'entrée et en joignant la sortie de manière appropriée :

#define uint8x16_to_8x8x2(v) ((uint8x8x2_t) { vget_low_u8(v), vget_high_u8(v) })

uint8x16_t a = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
uint8x16_t b = { 0x80, 0x0f, 0x01, 0x0e, 0x02, 0x0d, 0x03, 0x0c, 0x04, 0x0b, 0x05, 0x0a, 0x06, 0x09, 0x07, 0x08 };
uint8x16_t c = vcombine_u8(vtbl2_u8(uint8x16_to_8x8x2(a), vget_low_u8(b)), vtbl2_u8(uint8x16_to_8x8x2(a), vget_high_u8(b)));
// c = 00 ff 11 ee 22 dd 33 cc 44 bb 55 aa 66 99 77 88

Comme l'a dit Jake, vtbl renvoie 0 lorsque l'index est en dehors de la plage, vous ne devriez donc pas avoir besoin d'un traitement spécial pour la fonction 0x80 cas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X