执行__builtin_clz
GCC(4.6+)__builtin_clz的实施是什么? 它是否与Intel x86_64 (AVX)
上的某些CPU指令相对应?
它应转换为位扫描反转指令和减法。 BSR给出前导1的索引,然后您可以从字大小中减去该值以获得前导零的数量。
编辑:如果你的CPU支持LZCNT(前导零计数),那么这也许可以解决问题,但并非所有x86-64芯片都有该指令。
是的,不。
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