GCC(4.6+)___builtin_clz
_の実装は何ですか? Intel x86_64 (AVX)
の一部のCPU命令に対応していますか?
Bit Scan Reverse 命令に変換し、減算する必要があります。 BSRは、先頭の1のインデックスを提供し、Wordのサイズからそれを引くと、先頭のゼロの数を取得できます。
編集: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
Clzではなくbsrが本当に必要な場合は、31-clz(32ビット整数の場合)を実行する必要があることに注意してください。これは、XOR 31 as x XOR 31 == 31-x(このIDは、2 ^ y-1からの数にのみ当てはまります)したがって、
num = __builtin_clz(num) ^ 31;
収量
bsrl %edi, %eax
ret