GCC(4.6+)__builtin_clz
的实施是什么?它是否与英特尔x86_64 (AVX)
上的某些CPU指令相对应?
答案 0 :(得分:18)
它应该转换为Bit Scan Reverse指令和减法。 BSR给出前导1的索引,然后你可以从单词大小中减去它,得到前导零的数量。
编辑:如果你的CPU支持LZCNT(前导零计数),那么这也许可以解决问题,但并非所有x86-64芯片都有该指令。
答案 1 :(得分:17)
是的,没有。
CLZ(计数前导零)和BSR(位扫描反向)相关但不同。 CLZ等于(类型位宽小于1) - BSR。 CTZ(计数尾随零),也称为FFS(查找第一组)与BSF(位扫描前向)相同。
请注意,在零操作时,所有这些都是未定义的!
在回答你的问题时,大多数情况下在x86和x86_64上,__ builtin_clz会生成从31减去的BSR操作(或者你的类型宽度是什么),而__builting_ctz会生成BSF操作。
如果你想知道汇编程序GCC正在生成什么,最好的方法就是看。 -S标志将gcc输出为给定输入生成的汇编程序:
gcc -S -o test.S test.c
考虑:
unsigned int clz(unsigned int num) {
return __builtin_clz(num);
}
unsigned int ctz(unsigned int num) {
return __builtin_ctz(num);
}
在x86上为clz gcc(-O2)生成:
bsrl %edi, %eax
xorl $31, %eax
ret
和ctz:
bsfl %edi, %eax
ret
注意,如果你真的想要bsr而不是clz,你需要做31-clz(对于32位整数。)这解释了XOR 31,因为x XOR 31 == 31 - x(这个身份只是对于2 ^ y的数字为真 - 1)所以:
num = __builtin_clz(num) ^ 31;
产量
bsrl %edi, %eax
ret