From edf4c07d251f1d6c709d47969bfe1452194d9430 Mon Sep 17 00:00:00 2001 From: lucasart Date: Mon, 12 Mar 2018 06:56:14 +0800 Subject: [PATCH] Use intrinsics only for LSB/MSB 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: https://github.com/official-stockfish/Stockfish/pull/1447 and: https://github.com/official-stockfish/Stockfish/pull/1479 No functional change. --- src/bitboard.cpp | 62 ------------------------------------------------ src/bitboard.h | 41 +++++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 68 deletions(-) diff --git a/src/bitboard.cpp b/src/bitboard.cpp index ba00c78d..994ee17f 100644 --- a/src/bitboard.cpp +++ b/src/bitboard.cpp @@ -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) { @@ -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. @@ -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; diff --git a/src/bitboard.h b/src/bitboard.h index 9fc53ee7..ed01eada 100644 --- a/src/bitboard.h +++ b/src/bitboard.h @@ -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); @@ -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); @@ -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 -- 2.39.2