如何编写匹配对应lane输出0xFF的SWAR相等比较无分支代码?
无分支SWAR字节相等比较实现方案
可以实现无分支转换,原有实现的输出中匹配的字节仅最高位为1(值为0x80)、不匹配的字节全为0,只需将每个字节的最高位广播到该字节的全部8位,即可得到匹配输出0xFF、不匹配输出0x00的效果,以下是两种高效实现:
方案1:移位按位或实现(无乘法,兼容性最优)
uint64_t compare_eq (uint64_t x, uint64_t y) { uint64_t xored = x ^ y; uint64_t mask = 0x7F * 0x0101010101010101ULL; uint64_t tmp = (xored & mask) + mask; uint64_t res = ~(tmp | xored | mask); // 三次移位或完成最高位到全字节的广播 res |= res >> 1; res |= res >> 2; res |= res >> 4; return res; }
原理说明:仅需三次移位按位或操作,就可以把每个字节最高位的1扩散到整个字节的所有位,三次移位总覆盖位数为1+2+4=7,刚好覆盖单字节剩余的7个低位,无任何分支逻辑。
方案2:移位乘法实现(代码更简洁)
uint64_t compare_eq (uint64_t x, uint64_t y) { uint64_t xored = x ^ y; uint64_t mask = 0x7F * 0x0101010101010101ULL; uint64_t tmp = (xored & mask) + mask; uint64_t res = ~(tmp | xored | mask); // 提取每个字节最高位为1位标记,乘0xFF得到全1字节 return ((res >> 7) * 0xFFULL) & (0xFFULL * 0x0101010101010101ULL); }
原理说明:先将每个字节的最高位右移到最低位得到0x01/0x00的标记,乘以0xFF后对应字节变为0xFF/0x00,最后用掩码清除跨字节的乘法溢出位即可,同样全程无分支。
两种方案的性能和原有实现基本一致,都可以被编译器优化为纯寄存器操作,无任何跳转开销。
内容的提问来源于stack exchange,提问作者Koz Ross
相关产品推荐
相关产品推荐

