使用SSE 内在函数,可以这样编码:
char in[2];
char string[16];
__m128i zeroes = _mm_set1_epi8('0');
__m128i ones = _mm_set1_epi8('1');
__m128i mask = _mm_set_epi8(
0x80, 0x40, 0x20, 0x10, 8, 4, 2, 1,
0x80, 0x40, 0x20, 0x10, 8, 4, 2, 1);
__m128i val = _mm_set_epi8(
in[1], in[1], in[1], in[1], in[1], in[1], in[1], in[1],
in[0], in[0], in[0], in[0], in[0], in[0], in[0], in[0]);
val = _mm_cmplt_epi8(val, _mm_and_si128(val, mask));
val = _mm_or_si128(_mm_and_si128(val, zeroes), _mm_andnot_si128(val, ones));
_mm_storeu_si128(string, val);
该代码执行以下步骤:
- 将 2 字节输入复制到 XMM 寄存器的所有字节中,
_mm_set1_epi...()
- 创建一个掩码以从每个单词中提取不同的位
- 位提取使用并行和
- 将提取的位与掩码进行比较(低于)。
结果是一个数组,0xffff
或者0x0
如果该位被清除或设置。
- 使用该掩码提取
'0'
和字符,将它们组合起来。'1'
- 写出结果字节数组
这摆脱了移位和测试序列,但其代价是每个_mm_set*()
扩展成几个 SSE 指令的序列。它仍然比位测试循环的 128 次迭代快。