From 151e204cc83460d5fbfb2248616fd9115c709646 Mon Sep 17 00:00:00 2001 From: Guy Vreuls Date: Thu, 16 Jul 2026 08:23:22 +0200 Subject: [PATCH] Simplify bitboards This PR: - retires the unused distance() functions in bitboard.h including the 4K SquareDistance LUT, - makes the 64K PopCnt16 LUT constexpr and only compiles it in if we don't use a popcount intrinsic (we can't fully remove the LUT because it's faster than the intrinsic in the absence of a popcount machine instruction), - retires Bitboards::init(). Passed STC: https://tests.stockfishchess.org/tests/view/6a48e6d3f97ff95f78795a8f LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 162016 W: 42054 L: 41976 D: 77986 Ptnml(0-2): 383, 17375, 45454, 17373, 423 I didn't run LTC because the changes only really impact workers without popcount and there aren't any present on fishtest ATM. The correctness of the constexpr PopCnt16 LUT was verified locally with a x86-64 build; the build yields the same signature as master. closes https://github.com/official-stockfish/Stockfish/pull/6952 No functional change --- src/bitboard.cpp | 10 ---------- src/bitboard.h | 46 ++++++++++++++++++++++++++++------------------ src/main.cpp | 2 -- src/types.h | 2 +- 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/src/bitboard.cpp b/src/bitboard.cpp index 94f667b2a..4e24456a5 100644 --- a/src/bitboard.cpp +++ b/src/bitboard.cpp @@ -18,12 +18,8 @@ #include "bitboard.h" -#include - namespace Stockfish { -u8 PopCnt16[1 << 16]; - // Returns an ASCII representation of a bitboard suitable // to be printed to standard output. Useful for debugging. std::string Bitboards::pretty(Bitboard b) { @@ -45,10 +41,4 @@ std::string Bitboards::pretty(Bitboard b) { return s; } -// Initializes the popcount table at startup. -void Bitboards::init() { - for (unsigned i = 0; i < (1 << 16); ++i) - PopCnt16[i] = u8(std::bitset<16>(i).count()); -} - } // namespace Stockfish diff --git a/src/bitboard.h b/src/bitboard.h index 836035b33..49989d2e3 100644 --- a/src/bitboard.h +++ b/src/bitboard.h @@ -21,8 +21,8 @@ #include #include -#include #include +#include #include "types.h" #include "misc.h" @@ -31,7 +31,6 @@ namespace Stockfish { namespace Bitboards { -void init(); std::string pretty(Bitboard b); } // namespace Stockfish::Bitboards @@ -63,8 +62,6 @@ constexpr Bitboard Rank6BB = Rank1BB << (8 * 5); constexpr Bitboard Rank7BB = Rank1BB << (8 * 6); constexpr Bitboard Rank8BB = Rank1BB << (8 * 7); -extern u8 PopCnt16[1 << 16]; - constexpr Bitboard square_bb(Square s) { assert(is_ok(s)); return 1ULL << s; @@ -130,26 +127,39 @@ constexpr Bitboard pawn_single_push_bb(Color c, Bitboard b) { return c == WHITE ? shift(b) : shift(b); } -inline int edge_distance(File f) { return std::min(f, File(FILE_H - f)); } +constexpr int edge_distance(File f) { return std::min(f, File(FILE_H - f)); } -constexpr int constexpr_popcount(Bitboard b) { - b = b - ((b >> 1) & 0x5555555555555555ULL); - b = (b & 0x3333333333333333ULL) + ((b >> 2) & 0x3333333333333333ULL); - b = (b + (b >> 4)) & 0x0F0F0F0F0F0F0F0FULL; - return static_cast((b * 0x0101010101010101ULL) >> 56); + +template +constexpr int constexpr_popcount(T v) { + static_assert(std::is_integral_v, "constexpr_popcount is undefined for non-integral types"); + + if constexpr (sizeof(T) <= 8) + { + u64 b = static_cast>(v); + + b = b - ((b >> 1) & 0x5555555555555555ULL); + b = (b & 0x3333333333333333ULL) + ((b >> 2) & 0x3333333333333333ULL); + b = (b + (b >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + + return static_cast((b * 0x0101010101010101ULL) >> 56); + } + else + { + int result = 0; + + for (; v; v >>= static_cast(1)) + if (v & static_cast(1)) + ++result; + + return result; + } } // Counts the number of non-zero bits in a bitboard. inline int popcount(Bitboard b) { -#ifndef USE_POPCNT - - u16 indices[4]; - std::memcpy(indices, &b, sizeof(b)); - return PopCnt16[indices[0]] + PopCnt16[indices[1]] + PopCnt16[indices[2]] - + PopCnt16[indices[3]]; - -#elif defined(_MSC_VER) +#ifdef _MSC_VER return int(_mm_popcnt_u64(b)); diff --git a/src/main.cpp b/src/main.cpp index 7e36b23dc..304b2be06 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,7 +21,6 @@ #include #include "attacks.h" -#include "bitboard.h" #include "misc.h" #include "position.h" #include "tune.h" @@ -40,7 +39,6 @@ __attribute__((used)) // keep main alive int main(int argc, char* argv[]) { std::cout << engine_info() << std::endl; - Bitboards::init(); Attacks::init(); Position::init(); diff --git a/src/types.h b/src/types.h index c4eb1f8c1..71bc90812 100644 --- a/src/types.h +++ b/src/types.h @@ -76,7 +76,7 @@ #define IS_64BIT #endif - #if defined(USE_POPCNT) && defined(_MSC_VER) + #if defined(_MSC_VER) #include // Microsoft header for _mm_popcnt_u64() #endif