__builtin_ia32_cvtb2mask512()
是gnu c内置的vpmovb2m k, zmm
。 Intel的内在是
_mm512_movepi8_mask
。
SSE2和AVX2指令
pmovmskb
和vpmovmskb
_mm_movemask_epi8
和
_mm256_movemask_epi8
)
我希望ARM的实现比以下更快我想实施武器霓虹灯 我想为ARMSVE
进行实施我已经在C中附加了基本标量实现。对于那些试图用手臂实现的人,我们关心高位,但是每个字节的高钻头(在128位向量中)可以轻松地使用手臂将其转移到低位霓虹灯内在:vshrq_n_u8()。 请注意,我希望不将位图存储到内存中,它应该只是该函数的返回值,类似于以下函数。
#define _(n) __attribute((vector_size(1<<n),aligned(1)))
typedef char V _(6); // 64 bytes, 512 bits
typedef unsigned long U;
#undef _
U generic_cvtb2mask512(V v) {
U mask=0;int i=0;
while(i<64){
// shift mask by 1 and OR with MSB of v[i] byte
mask=(mask<<1)|((v[i]&0x80)>>7);
i++;}
return mask;
}
#define _(n) __attribute((vector_size(1<<n),aligned(1)))
typedef char g4 _(4); // 16 bytes, 128 bits
typedef char g3 _(3); // 8 bytes, 64 bits
typedef unsigned long U;
#undef _
unsigned short get_16msb(g4 v) {
unsigned short = ret;
// per byte, make every bit same as msb
g4 msb = vdupq_n_u8(0x80);
g4 filled = vceqq_u8(v, msb);
// create a mask of each bit value
g4 b = {0x80, 0x40, 0x20, 0x01, 0x08, 0x04, 0x02, 0x01,
0x80, 0x40, 0x20, 0x01, 0x08, 0x04, 0x02, 0x01};
// and vectors together
g4 z = vandq_u8 (filled,b);
// extract lower 8 bytes, hi 8 bytes
g3 lo = vget_low_u8(z);
g3 hi = vget_high_u8(z);
// 'or' the 8 bytes of lo together ...
// put in byte 1 of ret
// 'or' the 8 bytes of hi together ...
// put in byte 2 of ret
return ret;
}
// per byte, make every bit same as msb
g4 msb = vdupq_n_u8(0x80);
g4 filled = vceqq_u8(v, msb);
不会在性能上有所作为,但是它在检查是否设置了标志位,所以只需
vcltzq_s8(v)
。即,而不是仅在签名比较中检查值是负的。
如果您只关心是否有一个具有签名位设置的值,那么对于Adv Simd,您只能在比较结果上使用v == 0x80
,然后才能使用:vpmaxq_s8
对于SVE,您不需要它,因为比较本身设置标志。您可以在比较和分支的谓词结果上做
if (vgetq_lane_s64 (vreinterpretq_s64_s8 (res), 0))
。编译器应在优化期间删除ptest
。如果您需要使用哪个元素,则有多种方法。 正如彼得·科德斯(Peter Cordes)在评论中所说的那样,您可以使用AN和特殊面具,然后使用ADV。 simd.
这些模式很常见,并且本质上是标准库中的。 因此,对于最佳序列,我建议您在ARM优化的例程中检查我们在找到更好的方法时不断更新的任何内容。for neon:https://github.com/arm-software/optimized-routines/blob/master/string/aarch64/strchr.s
是文件,如上所述。
for sve:https://github.com/arm-software/optimized-routines/blob/master/string/aarch64/strchr-sve.s,在那里还有一些其他代码,因为
ptest
需要检查null的null终结者,但总体想法是相同的。
clz