Don't copy around DirtyThreats

The contents of DirtyThreats gets memcpyed twice for each call to do_move.
(Return value optimization doesn't apply to the do_move function itself because
it constructs a std::pair, so it gets copied; and the calls to reset also
require a copy.) This patch inserts the dirty info in place.

Sometimes the caller of do_move ignores the DirtyThreats info, so we pass in
scratch objects. I found that stack-allocating these scratch objects was bad on
Fishtest, so I begrudgingly put them in the Position struct. Both templating
the do_move function on whether dirty threats are needed and putting a
null-check branch for each use of dirty threats were slowdowns locally. Of
course, nothing prevents a future attempt at cleaning this up.

passed STC
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 68448 W: 17770 L: 17418 D: 33260
Ptnml(0-2): 198, 7425, 18630, 7769, 202
https://tests.stockfishchess.org/tests/view/6914c01a7ca87818523318ba

closes https://github.com/official-stockfish/Stockfish/pull/6414

No functional change
This commit is contained in:
Timothy Herchen
2025-11-13 22:17:03 +01:00
committed by Joost VandeVondele
parent 3ae7684714
commit fa4f05d3ef
5 changed files with 55 additions and 37 deletions
+11 -13
View File
@@ -201,7 +201,7 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si) {
Square sq = SQ_A8;
std::istringstream ss(fenStr);
std::memset(this, 0, sizeof(Position));
std::memset(reinterpret_cast<char*>(this), 0, sizeof(Position));
std::memset(si, 0, sizeof(StateInfo));
st = si;
@@ -688,10 +688,12 @@ bool Position::gives_check(Move m) const {
// moves should be filtered out before this function is called.
// If a pointer to the TT table is passed, the entry for the new position
// will be prefetched
DirtyBoardData Position::do_move(Move m,
StateInfo& newSt,
bool givesCheck,
const TranspositionTable* tt = nullptr) {
void Position::do_move(Move m,
StateInfo& newSt,
bool givesCheck,
DirtyPiece& dp,
DirtyThreats& dts,
const TranspositionTable* tt = nullptr) {
assert(m.is_ok());
assert(&newSt != st);
@@ -720,12 +722,10 @@ DirtyBoardData Position::do_move(Move m,
bool checkEP = false;
DirtyPiece dp;
dp.pc = pc;
dp.from = from;
dp.to = to;
dp.add_sq = SQ_NONE;
DirtyThreats dts;
dp.pc = pc;
dp.from = from;
dp.to = to;
dp.add_sq = SQ_NONE;
dts.us = us;
dts.prevKsq = square<KING>(us);
dts.threatenedSqs = dts.threateningSqs = 0;
@@ -970,8 +970,6 @@ DirtyBoardData Position::do_move(Move m,
assert(!(bool(captured) || m.type_of() == CASTLING) ^ (dp.remove_sq != SQ_NONE));
assert(dp.from != SQ_NONE);
assert(!(dp.add_sq != SQ_NONE) ^ (m.type_of() == PROMOTION || m.type_of() == CASTLING));
return {dp, dts};
}