Mike's "unsafe" version is a trailing zero count, while your MSB is no leading zero count. I would prefer to return -1 for empty sets, since 64 somehow implies leading zero count, which it isn't due to missing xor 63 for none empty setsbob wrote: Terrible idea. When a company (Intel) says "operation is undefined" it is foolish to try it out, and then _depend_ on the specific behaviour you notice. You can find a perfectly safe PopCnt() in Crafty that returns 64 when no bits are set, and which does not depend on undefined behaviour that can change in the next processor generation without anyone knowing.
Here is a 32 bit version that does not depend on undefined behaviour and which only has two extra instructions.Code: Select all
int static __inline__ MSB(BITBOARD word) { int dummy1, dummy2, dummy3; asm(" bsr %1, %0 " "\n\t" " jnz 1f " "\n\t" " bsr %2, %0 " "\n\t" " jnz 2f " "\n\t" " movl $64, %0 " "\n\t" " jmp 2f " "\n\t" "1: addl $32,%0 " "\n\t" "2: " "\n\t" : "=&q"(dummy1), "=&q"(dummy2), "=&q"(dummy3) : "1"((int) (word >> 32)), "2"((int) word) : "cc"); return (dummy1); }

I'll vote for to use leading/trailing zero counts for all sets including the empty, but assume MSB/LSB aka bitscan reverse/forward for none empty bitboards like in typical while (bits) loops. Safes one conditional jump and Mike's version becomes safe and even shorter.
Code: Select all
__inline s32 bitscanForward(u64 bits)
{
assert (bits != 0);
__asm
{
bsf eax, dword ptr bits
jnz done
bsf eax, dword ptr bits+4
add eax, 32
done:
}
}

