summaryrefslogtreecommitdiff
path: root/src/root.c
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-09-16 08:02:21 -0700
committerScott Gasch <[email protected]>2026-09-16 08:02:21 -0700
commit966a0ef4da9cf3911eb3da0533179199808717b4 (patch)
treee09363b574215ef0d8996155a5ab24314db2dd69 /src/root.c
parentb91c8453f3fe21c8ccd3568923d8e39141c9c945 (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.c31
1 files changed, 16 insertions, 15 deletions
diff --git a/src/root.c b/src/root.c
index f5fe4c1..314395a 100644
--- a/src/root.c
+++ b/src/root.c
@@ -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;