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
This commit is contained in:
Carlos Esparza
2026-06-10 12:37:12 +02:00
committed by Joost VandeVondele
parent 7c7fe322ea
commit 278a755fb5
+23 -23
View File
@@ -946,27 +946,6 @@ void Position::do_move(Move m,
st->castlingRights &= ~(castlingRightsMask[from] | castlingRightsMask[to]); st->castlingRights &= ~(castlingRightsMask[from] | castlingRightsMask[to]);
k ^= Zobrist::castling[st->castlingRights]; 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 the moving piece is a pawn do some special extra work
if (type_of(pc) == PAWN) 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]; 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 // Update the key with the final value
st->key = k; st->key = k;
if (tt)
prefetch(tt->first_entry(key()));
if (history) if (history)
{ {
@@ -1050,6 +1029,27 @@ void Position::do_move(Move m,
prefetch(&history->nonpawn_correction_entry<BLACK>(*this)); prefetch(&history->nonpawn_correction_entry<BLACK>(*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 // Set capture piece
st->capturedPiece = captured; st->capturedPiece = captured;