Implementation of __builtin_clz

Yes, and no.

CLZ (count leading zero) and BSR (bit-scan reverse) are related but different. CLZ equals (type bit width less one) – BSR. CTZ (count trailing zero), also know as FFS (find first set) is the same as BSF (bit-scan forward.)

Note that all of these are undefined when operating on zero!

In answer to your question, most of the time on x86 and x86_64, __builtin_clz generates BSR operation subtracted from 31 (or whatever your type width is), and __builting_ctz generates a BSF operation.

If you want to know what assembler GCC is generating, the best way to know is to see. The -S flag will have gcc output the assembler it generated for the given input:

gcc -S -o test.S test.c

Consider:

unsigned int clz(unsigned int num) {
    return __builtin_clz(num);
}

unsigned int ctz(unsigned int num) {
    return __builtin_ctz(num);
}

On x86 for clz gcc (-O2) generates:

bsrl    %edi, %eax
xorl    $31, %eax
ret

and for ctz:

bsfl    %edi, %eax
ret

Note that if you really want bsr, and not clz, you need to do 31 – clz (for 32-bit integers.) This explains the XOR 31, as x XOR 31 == 31 – x (this identity is only true for numbers of the from 2^y – 1) So:

num = __builtin_clz(num) ^ 31;

yields

bsrl    %edi, %eax
ret

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)