2013-03-13 9 views
5

Sto cercando il modo più veloce per verificare se un registro di 128 NEON contiene tutti gli zeri, usando gli intrinseci NEON. Attualmente sto usando 3 O operazioni, e 2 MOV:Il modo più veloce per testare un registro NEON a 128 bit per un valore pari a 0 utilizzando intrinseche?

uint32x4_t vr = vorrq_u32(vcmp0, vcmp1); 

uint64x2_t v0 = vreinterpretq_u64_u32(vr); 
uint64x1_t v0or = vorr_u64(vget_high_u64(v0), vget_low_u64(v0)); 

uint32x2_t v1 = vreinterpret_u32_u64 (v0or); 
uint32_t r = vget_lane_u32(v1, 0) | vget_lane_u32(v1, 1); 

if (r == 0) { // do stuff } 

Questo si traduce da gcc al seguente codice assembly:

VORR  q9, q9, q10 
VORR  d16, d18, d19 
VMOV.32 r3, d16[0] 
VMOV.32 r2, d16[1] 
VORRS r2, r2, r3 
BEQ  ... 

Qualcuno ha un'idea di un modo più veloce?

risposta

1

Lei sembra essere alla ricerca di intrinseche e questo è il modo: la risposta di

inline bool is_zero(int32x4_t v) noexcept 
{ 
    v = v == int32x4{}; 

    return !int32x2_t(
    vtbl2_s8(
     int8x8x2_t{ 
     int8x8_t(vget_low_s32(v)), 
     int8x8_t(vget_high_s32(v)) 
     }, 
     int8x8_t{0, 4, 8, 12} 
    ) 
)[0]; 
} 

Nils Pipenbrinck ha un difetto in quanto egli assume il controllo di qualità, la bandiera di saturazione cumulativo per essere chiari.

6

Mentre questa risposta può essere un po 'in ritardo, c'è un modo semplice per fare la prova con solo 3 istruzioni e nessun registro aggiuntivi:

inline uint32_t is_not_zero(uint32x4_t v) 
{ 
    uint32x2_t tmp = vorr_u32(vget_low_u32(v), vget_high_u32(v)); 
    return vget_lane_u32(vpmax_u32(tmp, tmp), 0); 
} 

Il valore di ritorno sarà diverso da zero se qualsiasi bit nella 128 -al registro NEON è stato impostato.

2

Se sei targeting AArch64 NEON, è possibile utilizzare il seguente per ottenere un valore di testare con solo due istruzioni:

inline uint64_t is_not_zero(uint32x4_t v) 
{ 
    uint64x2_t v64 = vreinterpretq_u64_u32(v); 
    uint32x2_t v32 = vqmovn_u64(v64); 
    uint64x1_t result = vreinterpret_u64_u32(v32); 
    return result[0]; 
} 
0

Se avete AArch64 si può fare ancora più facile. Hanno una nuova istruzione per progettato per questo.

inline uint32_t is_not_zero(uint32x4_t v) 
{ 
    return vaddvq_u32(v); 
} 
+0

Questo sembra vulnerabile a trabocchi, però. – wolfv