summaryrefslogtreecommitdiff
path: root/src/split.c
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-09-04 01:03:00 -0700
committerScott Gasch <[email protected]>2026-09-04 01:03:00 -0700
commit5c8d794782d3be6368dbba613ef129b11d878d97 (patch)
treebd43bd7c72aa32a4c99001147416e503142a7590 /src/split.c
parentdddcaa09ad12f1972a3128748b5d90d22f9a9326 (diff)
Fix passed-pawn bitboard bit-clear bug, LMR gate coupling, inline hot bitboard helpers
- bitboard.c: CoorFromBitBoardRank1ToRank8 cleared the lowest set bit unconditionally instead of the reported (highest) one, silently mis-walking doubled-pawn files in eval.c's passed-pawn detection. - search.c/searchsup.c: move GetLMRReduction's precondition checks from inside the function to the caller in search.c (pre-existing work), finishing the split with a matching gate in split.c's HelpSearch -- the parallel-search call site had no gate at all, letting it call GetLMRReduction unconditionally (including for checking moves), reachable only under real multithreading (--cpus > 1) and the intermittent root cause of assertion crashes seen under --cpus 4. - eval.c: redirect CountBits/CoorFromBitBoardRank8ToRank1/ CoorFromBitBoardRank1ToRank8 to inline compiler-builtin versions (gated !CROUTINES) instead of the real out-of-line asm calls, on eval.c's ~20 existing production call sites. CountBits' asm body isn't O(1) popcnt, it's a Kernighan bit-clearing loop plus call overhead, paid on every Eval() call. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Jntky4yGUTyQVaGCXms4F2
Diffstat (limited to 'src/split.c')
-rwxr-xr-xsrc/split.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/src/split.c b/src/split.c
index a1f9d32..f8da7ed 100755
--- a/src/split.c
+++ b/src/split.c
@@ -1138,6 +1138,27 @@ Return value:
//
// Decide how much (if any) to reduce this move's depth.
//
+ // Gate matches search.c's non-split move loop exactly (the
+ // preconditions used to live inside GetLMRReduction itself;
+ // a refactor moved them out to the caller in search.c but
+ // this call site was missed, so GetLMRReduction ran
+ // unconditionally here -- including on checking moves,
+ // captures, PV nodes, etc. -- and its own internal
+ // ASSERT(!InCheck(...)) could fire for any checking move
+ // that also passed the killer-move/fail-high filter still
+ // inside GetLMRReduction. Only reachable through a split
+ // (i.e. only under real multithreading), which is why this
+ // looked like a rare, hard-to-reproduce race rather than
+ // the deterministic missing-gate bug it actually was.
+ //
+ if ((uDepth > TWO_PLY) &&
+ !(ctx->sPlyInfo[ctx->uPly].fPvNode) &&
+ !(ctx->sPlyInfo[ctx->uPly - 1].fPvNode) &&
+ ((g_SplitInfo[u].uAlreadyDone + uMoveNum + 1) > 5) &&
+ (0 == iExtend) &&
+ (!IS_ESCAPING_CHECK(mv)) &&
+ (!IS_CAPTURE_OR_PROMOTION(mv)) &&
+ (!IS_CHECKING_MOVE(mv)))
{
INT iLMR = GetLMRReduction(iEval,
iAlpha,