diff options
| author | Scott Gasch <[email protected]> | 2026-09-16 08:02:21 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-09-16 08:02:21 -0700 |
| commit | 966a0ef4da9cf3911eb3da0533179199808717b4 (patch) | |
| tree | e09363b574215ef0d8996155a5ab24314db2dd69 /src/root.c | |
| parent | b91c8453f3fe21c8ccd3568923d8e39141c9c945 (diff) | |
Retire cPawns/cNonPawns piece-location lists in favor of bbPawns/bbPieces/cKingSq, and hoist two redundant TotalNonPawnCount POPCNT calls out of per-node hot loops.
POSITION no longer stores cPawns[2][8], cNonPawns[2][16], uPawnCount[2],
uNonPawnCount[2][8], or uWhiteSqBishopCount[2] -- every reader now goes
through PawnMaterial/TotalNonPawnCount/WhiteSqBishopCount/KingPosition
(chess.h), computed from the already-incrementally-maintained bbPawns/
bbPieces/cKingSq bitboards via a single -mpopcnt POPCNT instead of a
stored counter. move.c's make/unmake loses the list-swap-on-removal
bookkeeping entirely. GNUmakefile now passes -mpopcnt so the popcount
builtins actually compile to one instruction instead of clang's ~15-op
SWAR fallback.
Measured a small but real nps regression from the naive swap (search.c's
QSearch move-filter and eval.c's _EvalKing were each recomputing the same
TotalNonPawnCount sum on every candidate move / twice per node); hoisted
both to a single call per node instead. Net result across a same-code
self-play match: ~1541.5 knps candidate vs ~1505.7 knps head_reference.
A third hoist (FindEnprisePiece out of SelectBestWithHistory) was tried
and reverted -- its cache isn't actually loop-invariant within a node
(populated from inside Eval(), which doesn't run before every selection
call), caught by a DEBUG-build ASSERT before it landed.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'src/root.c')
| -rw-r--r-- | src/root.c | 31 |
1 files changed, 16 insertions, 15 deletions
@@ -1033,19 +1033,22 @@ _DetectPreMoveTerminalStates(SEARCHER_THREAD_CONTEXT *ctx, // Look for insufficient material. FOREACH_COLOR(u) { - uMajors[u] = (pos->uNonPawnCount[u][ROOK] + - pos->uNonPawnCount[u][QUEEN]); - uMinors[u] = (pos->uNonPawnCount[u][KNIGHT] + - pos->uNonPawnCount[u][BISHOP]); - uWhiteBishops[u] = pos->uWhiteSqBishopCount[u]; - uBlackBishops[u] = pos->uNonPawnCount[u][BISHOP] - uWhiteBishops[u]; + uMajors[u] = (FastCountBits(pos->bbPieces[u][ROOK]) + + FastCountBits(pos->bbPieces[u][QUEEN])); + uMinors[u] = (FastCountBits(pos->bbPieces[u][KNIGHT]) + + FastCountBits(pos->bbPieces[u][BISHOP])); + uWhiteBishops[u] = WhiteSqBishopCount(pos, u); + uBlackBishops[u] = FastCountBits(pos->bbPieces[u][BISHOP]) - uWhiteBishops[u]; } FOREACH_COLOR(u) { - if ((pos->uPawnCount[u] != 0) || - (pos->uPawnCount[FLIP(u)] != 0)) { + ULONG uNonKing = FastCountBits(NON_KING_PIECES_BB(pos, u)); + ULONG uNonKingFlip = FastCountBits(NON_KING_PIECES_BB(pos, FLIP(u))); + + if ((pos->bbPawns[u] != 0) || + (pos->bbPawns[FLIP(u)] != 0)) { continue; } - if (pos->uNonPawnCount[u][0] == 1) { + if (uNonKing == 0) { if (uMajors[FLIP(u)] == 0 && uMinors[FLIP(u)] == 1) { ret.eResult = RESULT_DRAW; @@ -1058,12 +1061,10 @@ _DetectPreMoveTerminalStates(SEARCHER_THREAD_CONTEXT *ctx, strcpy(ret.szDescription, "insufficient material"); return ret; } - } else if ((pos->uNonPawnCount[u][0] == 1 + uWhiteBishops[u] && - pos->uNonPawnCount[FLIP(u)][0] == - 1 + uWhiteBishops[FLIP(u)]) || - (pos->uNonPawnCount[u][0] == 1 + uBlackBishops[u] && - pos->uNonPawnCount[FLIP(u)][0] == - 1 + uBlackBishops[FLIP(u)])) { + } else if ((uNonKing == uWhiteBishops[u] && + uNonKingFlip == uWhiteBishops[FLIP(u)]) || + (uNonKing == uBlackBishops[u] && + uNonKingFlip == uBlackBishops[FLIP(u)])) { ret.eResult = RESULT_DRAW; strcpy(ret.szDescription, "insufficient material"); return ret; |
