Skip to content

Commit

Permalink
Use intrinsics only for LSB/MSB
Browse files Browse the repository at this point in the history
The NO_BSF does not cover any real life use-case today. The only compilers that
can compile SF today, with the current Makefile and no source code changes, are
either GCC compatible (define __GNUC__) or MSVC compatible (define _MSC_VER). So
they all support LSB/MSB intrinsics.

This patch simplifies away the software fall-backs of LSB/MSB that were still
in Stockfish code, but unused in any of the officially supported compilers.

Note the (legacy) MSVC/WIN32 case, where we use a 32-bit BSF/BSR solution, as
64-bit intrinsics aren't available there.

Discussed in: #1447
and:          #1479

No functional change.
  • Loading branch information
lucasart authored and snicolet committed Mar 14, 2018
1 parent b605103 commit edf4c07
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 68 deletions.
62 changes: 0 additions & 62 deletions src/bitboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,11 @@ Magic BishopMagics[SQUARE_NB];

namespace {

// De Bruijn sequences. See chessprogramming.wikispaces.com/BitScan
const uint64_t DeBruijn64 = 0x3F79D71B4CB0A89ULL;
const uint32_t DeBruijn32 = 0x783A9B23;

int MSBTable[256]; // To implement software msb()
Square BSFTable[SQUARE_NB]; // To implement software bitscan
Bitboard RookTable[0x19000]; // To store rook attacks
Bitboard BishopTable[0x1480]; // To store bishop attacks

void init_magics(Bitboard table[], Magic magics[], Direction directions[]);

// bsf_index() returns the index into BSFTable[] to look up the bitscan. Uses
// Matt Taylor's folding for 32 bit case, extended to 64 bit by Kim Walisch.

unsigned bsf_index(Bitboard b) {
b ^= b - 1;
return Is64Bit ? (b * DeBruijn64) >> 58
: ((unsigned(b) ^ unsigned(b >> 32)) * DeBruijn32) >> 26;
}


// popcount16() counts the non-zero bits using SWAR-Popcount algorithm

unsigned popcount16(unsigned u) {
Expand All @@ -76,46 +60,6 @@ namespace {
}
}

#ifdef NO_BSF

/// Software fall-back of lsb() and msb() for CPU lacking hardware support

Square lsb(Bitboard b) {
assert(b);
return BSFTable[bsf_index(b)];
}

Square msb(Bitboard b) {

assert(b);
unsigned b32;
int result = 0;

if (b > 0xFFFFFFFF)
{
b >>= 32;
result = 32;
}

b32 = unsigned(b);

if (b32 > 0xFFFF)
{
b32 >>= 16;
result += 16;
}

if (b32 > 0xFF)
{
b32 >>= 8;
result += 8;
}

return Square(result + MSBTable[b32]);
}

#endif // ifdef NO_BSF


/// Bitboards::pretty() returns an ASCII representation of a bitboard suitable
/// to be printed to standard output. Useful for debugging.
Expand Down Expand Up @@ -145,13 +89,7 @@ void Bitboards::init() {
PopCnt16[i] = (uint8_t) popcount16(i);

for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
SquareBB[s] = 1ULL << s;
BSFTable[bsf_index(SquareBB[s])] = s;
}

for (Bitboard b = 2; b < 256; ++b)
MSBTable[b] = MSBTable[b - 1] + !more_than_one(b);

for (File f = FILE_A; f <= FILE_H; ++f)
FileBB[f] = f > FILE_A ? FileBB[f - 1] << 1 : FileABB;
Expand Down
41 changes: 35 additions & 6 deletions src/bitboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ inline int popcount(Bitboard b) {

/// lsb() and msb() return the least/most significant bit in a non-zero bitboard

#if defined(__GNUC__)
#if defined(__GNUC__) // GCC, Clang, ICC

inline Square lsb(Bitboard b) {
assert(b);
Expand All @@ -315,7 +315,9 @@ inline Square msb(Bitboard b) {
return Square(63 ^ __builtin_clzll(b));
}

#elif defined(_WIN64) && defined(_MSC_VER)
#elif defined(_MSC_VER) // MSVC

#ifdef _WIN64 // MSVC, WIN64

inline Square lsb(Bitboard b) {
assert(b);
Expand All @@ -331,12 +333,39 @@ inline Square msb(Bitboard b) {
return (Square) idx;
}

#else
#else // MSVC, WIN32

inline Square lsb(Bitboard b) {
assert(b);
unsigned long idx;

if (b & 0xffffffff) {
_BitScanForward(&idx, int32_t(b));
return Square(idx);
} else {
_BitScanForward(&idx, int32_t(b >> 32));
return Square(idx + 32);
}
}

inline Square msb(Bitboard b) {
assert(b);
unsigned long idx;

if (b >> 32) {
_BitScanReverse(&idx, int32_t(b >> 32));
return Square(idx + 32);
} else {
_BitScanReverse(&idx, int32_t(b));
return Square(idx);
}
}

#endif

#define NO_BSF // Fallback on software implementation for other cases
#else // Compiler is neither GCC nor MSVC compatible

Square lsb(Bitboard b);
Square msb(Bitboard b);
#error "Compiler not supported."

#endif

Expand Down

0 comments on commit edf4c07

Please sign in to comment.