Rewrite Todd Lehman's answer so that it is more general:
#include <climits> template<typename N> constexpr N ilog2(N n) { N i = 0; for (N k = sizeof(N) * CHAR_BIT; 0 < (k /= 2);) { if (n >= static_cast<N>(1) << k) { i += k; n >>= k; } } return i; }
Clang with -O3 expands the loop:
0000000100000f50 pushq %rbp 0000000100000f51 movq %rsp, %rbp 0000000100000f54 xorl %eax, %eax 0000000100000f56 cmpl $0xffff, %edi 0000000100000f5c setg %al 0000000100000f5f shll $0x4, %eax 0000000100000f62 movl %eax, %ecx 0000000100000f64 sarl %cl, %edi 0000000100000f66 xorl %edx, %edx 0000000100000f68 cmpl $0xff, %edi 0000000100000f6e setg %dl 0000000100000f71 leal (,%rdx,8), %ecx 0000000100000f78 sarl %cl, %edi 0000000100000f7a leal (%rax,%rdx,8), %eax 0000000100000f7d xorl %edx, %edx 0000000100000f7f cmpl $0xf, %edi 0000000100000f82 setg %dl 0000000100000f85 leal (,%rdx,4), %ecx 0000000100000f8c sarl %cl, %edi 0000000100000f8e leal (%rax,%rdx,4), %eax 0000000100000f91 xorl %edx, %edx 0000000100000f93 cmpl $0x3, %edi 0000000100000f96 setg %dl 0000000100000f99 leal (%rdx,%rdx), %ecx 0000000100000f9c sarl %cl, %edi 0000000100000f9e leal (%rax,%rdx,2), %ecx 0000000100000fa1 xorl %eax, %eax 0000000100000fa3 cmpl $0x1, %edi 0000000100000fa6 setg %al 0000000100000fa9 orl %ecx, %eax 0000000100000fab popq %rbp
When n constant, the result is computed at compile time.
wonder.mice Jun 16 '18 at 19:07 2018-06-16 19:07
source share