From 278a755fb552131b7e2a5da24256b6a4b13246fc Mon Sep 17 00:00:00 2001 From: Carlos Esparza Date: Wed, 10 Jun 2026 12:37:12 +0200 Subject: [PATCH] Reorder operations in do_move Passed STC https://tests.stockfishchess.org/tests/view/6a2682ce351b79f679cc47c5 LLR: 2.93 (-2.94,2.94) <0.00,2.00> Total: 57248 W: 14730 L: 14399 D: 28119 Ptnml(0-2): 145, 6159, 15698, 6464, 158 Reordering operations in `do_move` allows us to effectively prefetch the TT entry earlier, since the piece moving helpers don't actually modify the position key. I suspect that with threat inputs, `put_piece` and friends got a lot more expensive, and so this helps us a lot. vondele's machine: ==== master ==== 1 Nodes/second : 294311526 2 Nodes/second : 297068312 3 Nodes/second : 297418763 Average (over 3): 296266200 ==== pfearly ==== 1 Nodes/second : 303986449 2 Nodes/second : 304221719 3 Nodes/second : 305302969 Average (over 3): 304503712 (+2.78%) Locally, `bench`: Result of 200 runs speedup = +0.0158 P(speedup > 0) = 1.0000 As expected it helps even more in a large-hash, NUMA setting. closes https://github.com/official-stockfish/Stockfish/pull/6891 No functional change --- src/position.cpp | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index 4744d5102..e87091783 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -946,27 +946,6 @@ void Position::do_move(Move m, st->castlingRights &= ~(castlingRightsMask[from] | castlingRightsMask[to]); k ^= Zobrist::castling[st->castlingRights]; - // Move the piece. The tricky Chess960 castling is handled earlier - if (m.type_of() != CASTLING) - { - Piece toPc = pc; - if (m.type_of() == PROMOTION) - toPc = make_piece(us, m.promotion_type()); - - if (captured && m.type_of() != EN_PASSANT) - { - remove_piece(from, &dts); - swap_piece(to, toPc, &dts); - } - else if (pc == toPc) - move_piece(from, to, &dts); - else - { - remove_piece(from, &dts); - put_piece(toPc, to, &dts); - } - } - // If the moving piece is a pawn do some special extra work if (type_of(pc) == PAWN) { @@ -1036,10 +1015,10 @@ void Position::do_move(Move m, st->minorPieceKey ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to]; } + if (tt) + prefetch(tt->first_entry(adjust_key50(k))); // Update the key with the final value st->key = k; - if (tt) - prefetch(tt->first_entry(key())); if (history) { @@ -1050,6 +1029,27 @@ void Position::do_move(Move m, prefetch(&history->nonpawn_correction_entry(*this)); } + // Move the piece. The tricky Chess960 castling is handled earlier + if (m.type_of() != CASTLING) + { + Piece toPc = pc; + if (m.type_of() == PROMOTION) + toPc = make_piece(us, m.promotion_type()); + + if (captured && m.type_of() != EN_PASSANT) + { + remove_piece(from, &dts); + swap_piece(to, toPc, &dts); + } + else if (pc == toPc) + move_piece(from, to, &dts); + else + { + remove_piece(from, &dts); + put_piece(toPc, to, &dts); + } + } + // Set capture piece st->capturedPiece = captured;