2013-04-02 66 views
3

我必须提取__m128i寄存器的非零值。例如,我有一个八个无符号短裤的向量。从SSE中提取_m128i寄存器的非零值

__m128i vector {40, 0, 22, 0, 0, 0, 0, 8} 

我想用最少量的SSE指令提取40,22和8。 非零值将存储在非零值的数组中。

{40, 22, 8, more values from different vectors ... } 

它可能洗牌或有一个很好的固有提取和存储?

+0

我们可以假设SSE 4? –

+0

是的,我们可以但我更喜欢SSSE3。 –

+0

是否需要保留非零值的顺序? –

回答

2

如果你看看at this paper,作者描述了如何使用_mm_cmpestrm指令做基本上想要的。其算法的核心是这个(我已经稍微修改,做你想要什么,而不是他们想要的东西):

__m128i res_v = _mm_cmpestrm(
    vector, 
    8, 
    mm_setzero_si128(), 
    8, 
    _SIDD_UWORD_OPS|_SIDD_CMP_EQUAL_ANY|_SIDD_BIT_MASK|_SIDD_NEGATIVE_POLARITY); 
int r = _mm_extract_epi32(res_v, 0); 

__m128i p = _mm_shuffle_epi8(vector, sh_mask[r]); 

如果构建了查表sh_mask在论文中描述,然后p应该有非零元素(没有任何重新排序),然后是零元素。在r中设置的位数将告诉你非零元素的数量。

不幸的是_mm_cmpestrm在SSE4中。

+0

哇我不知道这个命令,sh_mask的技巧真的很酷。非常感谢。 –

2

基于anjruu的答案,这里是一个已经不以任何方式被测试的SSSE3版本:

; xmm0 = input 
pxor xmm1, xmm1 
pcmpeqb xmm1, xmm0 
pmovmskb eax, xmm1 
shl eax, 4 
pshufb xmm0, [table + eax] 

table不同的是当然的,但不是很难奏效,只要记住了索引是“倒置的” - 例如,索引0对应于不具有零,并且0xFFFF对应于全零。