https://gcc.gnu.org/bugzilla/show_bug.cgi?id=72785
--- Comment #15 from dhowells at redhat dot com <dhowells at redhat dot com> --- (In reply to Jakub Jelinek from comment #14) > (In reply to dhowe...@redhat.com from comment #13) > ... > Ugh, no. Why not just x && (x & -x) == x ? __builtin_ctz (x) : -1 > (or ctzl or ctzll depending on what the type is)? Comparing the kernel's ilog2() to your suggestion: int kernel_ilog2(unsigned long x) { return ilog2(x); } int jakub_ilog2(unsigned long x) { return x && (x & -x) == x ? __builtin_ctz (x) : -1; } compiled with -Os for x86_64 gives: 0000000000000000 <kernel_ilog2>: 0: 83 c8 ff or $0xffffffff,%eax 3: 48 0f bd c7 bsr %rdi,%rax 7: c3 retq 0000000000000008 <jakub_ilog2>: 8: 83 c8 ff or $0xffffffff,%eax b: 48 85 ff test %rdi,%rdi e: 74 17 je 27 <jakub_ilog2+0x1f> 10: 48 89 fa mov %rdi,%rdx 13: 0f bc c7 bsf %edi,%eax 16: 48 f7 da neg %rdx 19: 48 21 fa and %rdi,%rdx 1c: 48 39 d7 cmp %rdx,%rdi 1f: ba ff ff ff ff mov $0xffffffff,%edx 24: 0f 45 c2 cmovne %edx,%eax 27: c3 retq Note that in the kernel variant, the initial OR instruction is superfluous, but is required by fls() and fls64() which x86_64 is using behind the scenes. Not all arches, however, use fls() and fls64() to implement ilog2().