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/testsup.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/testsup.c')
| -rw-r--r-- | src/testsup.c | 59 |
1 files changed, 12 insertions, 47 deletions
diff --git a/src/testsup.c b/src/testsup.c index 0cbc9a4..c5c62c2 100644 --- a/src/testsup.c +++ b/src/testsup.c @@ -67,7 +67,7 @@ void GenerateRandomLegalPosition(POSITION *pos) { COOR c, c1; - ULONG x, uIndex; + ULONG x; ULONG uColor; PIECE p; ULONG u; @@ -78,15 +78,7 @@ GenerateRandomLegalPosition(POSITION *pos) // Clear the board // memset(pos, 0, sizeof(POSITION)); - for (u = 0; u < ARRAY_SIZE(pos->cPawns[WHITE]); u++) - { - pos->cPawns[WHITE][u] = pos->cPawns[BLACK][u] = ILLEGAL_COOR; - } - - for (u = 0; u < ARRAY_SIZE(pos->cNonPawns[WHITE]); u++) - { - pos->cNonPawns[WHITE][u] = pos->cNonPawns[BLACK][u] = ILLEGAL_COOR; - } + pos->cKingSq[WHITE] = pos->cKingSq[BLACK] = ILLEGAL_COOR; // memset above zeroes cEpSquare to 0x00 (A8), a real on-board // square, not the "no en passant" sentinel -- every random @@ -112,10 +104,8 @@ GenerateRandomLegalPosition(POSITION *pos) c = RANDOM_COOR; ASSERT(IS_ON_BOARD(c)); pos->rgSquare[c].pPiece = WHITE_KING; - ASSERT(pos->cNonPawns[WHITE][0] == ILLEGAL_COOR); - pos->cNonPawns[WHITE][0] = c; - pos->uNonPawnCount[WHITE][KING] = 1; - pos->uNonPawnCount[WHITE][0] = 1; + ASSERT(pos->cKingSq[WHITE] == ILLEGAL_COOR); + pos->cKingSq[WHITE] = c; pos->uNonPawnMaterial[WHITE] = VALUE_KING; pos->bbOccupied |= COOR_TO_BB(c); pos->bbOccupiedSide[WHITE] |= COOR_TO_BB(c); @@ -127,10 +117,8 @@ GenerateRandomLegalPosition(POSITION *pos) while(DISTANCE(c, c1) < 2); ASSERT(IS_ON_BOARD(c1)); pos->rgSquare[c1].pPiece = BLACK_KING; - ASSERT(pos->cNonPawns[BLACK][0] == ILLEGAL_COOR); - pos->cNonPawns[BLACK][0] = c1; - pos->uNonPawnCount[BLACK][KING] = 1; - pos->uNonPawnCount[BLACK][0] = 1; + ASSERT(pos->cKingSq[BLACK] == ILLEGAL_COOR); + pos->cKingSq[BLACK] = c1; pos->uNonPawnMaterial[BLACK] = VALUE_KING; pos->bbOccupied |= COOR_TO_BB(c1); pos->bbOccupiedSide[BLACK] |= COOR_TO_BB(c1); @@ -169,20 +157,12 @@ GenerateRandomLegalPosition(POSITION *pos) ASSERT(GET_COLOR(p) == uColor); if (IS_PAWN(p) && - (pos->uPawnCount[uColor] < 8) && - (!RANK1(c)) && + (FastCountBits(pos->bbPawns[uColor]) < 8) && + (!RANK1(c)) && (!RANK8(c))) { - // - // The pawn list is not ordered at all, add - // the new pawn's location to the list and - // point from the pawn to the list. - // - pos->cPawns[uColor][pos->uPawnCount[uColor]] = c; - pos->rgSquare[c].uIndex = pos->uPawnCount[uColor]; + pos->rgSquare[c].uIndex = INVALID_PIECE_INDEX; pos->rgSquare[c].pPiece = p; - pos->uPawnCount[uColor]++; - pos->uPawnMaterial[uColor] += VALUE_PAWN; pos->bbPawns[uColor] |= COOR_TO_BB(c); pos->bbOccupied |= COOR_TO_BB(c); pos->bbOccupiedSide[uColor] |= COOR_TO_BB(c); @@ -191,23 +171,12 @@ GenerateRandomLegalPosition(POSITION *pos) else if (!IS_KING(p) && (IS_VALID_PIECE(p))) { - uIndex = pos->uNonPawnCount[uColor][0]; - pos->cNonPawns[uColor][uIndex] = c; - pos->uNonPawnCount[uColor][0]++; - pos->uNonPawnCount[uColor][PIECE_TYPE(p)]++; pos->rgSquare[c].pPiece = p; - pos->rgSquare[c].uIndex = uIndex; + pos->rgSquare[c].uIndex = INVALID_PIECE_INDEX; pos->uNonPawnMaterial[uColor] += PIECE_VALUE(p); pos->bbPieces[uColor][PIECE_TYPE(p)] |= COOR_TO_BB(c); pos->bbOccupied |= COOR_TO_BB(c); pos->bbOccupiedSide[uColor] |= COOR_TO_BB(c); - if (IS_BISHOP(p)) - { - if (IS_WHITE_SQUARE_COOR(c)) - { - pos->uWhiteSqBishopCount[uColor]++; - } - } break; } } @@ -216,19 +185,15 @@ GenerateRandomLegalPosition(POSITION *pos) } // next piece } // next color - ASSERT(pos->uNonPawnCount[WHITE][KING] == 1); - ASSERT(pos->uNonPawnCount[BLACK][KING] == 1); - //pos->uNonPawnCount[WHITE][0]--; - //pos->uNonPawnCount[BLACK][0]--; // // Do the rest of the position // pos->iMaterialBalance[WHITE] = ((SCORE)(pos->uNonPawnMaterial[WHITE] + - pos->uPawnMaterial[WHITE]) - + PawnMaterial(pos, WHITE)) - (SCORE)(pos->uNonPawnMaterial[BLACK] + - pos->uPawnMaterial[BLACK])); + PawnMaterial(pos, BLACK))); pos->iMaterialBalance[BLACK] = -pos->iMaterialBalance[WHITE]; pos->uToMove = RANDOM_COLOR; pos->uFifty = rand() % 100; |
