Code: Select all
int HashProbe(TREE * RESTRICT tree, int ply, int depth, int wtm, int *alpha,
int beta)
{
register BITBOARD word1, word2;
register int type, draft, avoid_null = 0, val, probe;
BITBOARD temp_hashkey;
HASH_ENTRY *htable;
/*
************************************************************
* *
* We loop thru two entries. The first entry is the *
* depth-priority entry (the first in a triplet of *
* entries). The second is one of the two following *
* entries, dictated by the rightmost bit of the hash *
* signature that was not used to address the table *
* triplet. *
* *
* We also return an "avoid_null" status if neither hash *
* entry has enough draft to terminate the current search *
* but one of them does have enough draft to prove that *
* a null-move search would not fail high. This avoids *
* the null-move search overhead in positions where it is *
* simply a waste of time to try it. *
* *
************************************************************
*/
tree->hash_move[ply] = 0;
temp_hashkey = (wtm) ? HashKey : ~HashKey;
htable = trans_ref + 3 * (temp_hashkey & hash_mask);
for (probe = 0; probe < 2; probe++) {
word1 = htable->word1;
word2 = htable->word2;
if (word2 == temp_hashkey) {
htable->word1 =
(word1 & 0x1fffffffffffffffULL) | ((BITBOARD) transposition_id << 61);
val = (word1 & 0x1ffff) - 65536;
draft = (word1 >> 17) & 0x7fff;
if (!tree->hash_move[ply])
tree->hash_move[ply] = (word1 >> 32) & 0x1fffff;
type = (word1 >> 59) & 3;
if ((type & UPPER) && depth - null_depth - 1 <= draft && val < beta)
avoid_null = AVOID_NULL_MOVE;
if (depth <= draft) {
if (val > MATE - 300)
val -= ply - 1;
else if (val < -MATE + 300)
val += ply - 1;
switch (type) {
case EXACT:
*alpha = val;
if (draft != MAX_DRAFT)
return (EXACT);
else
return (EXACTEGTB);
case UPPER:
if (val <= *alpha)
return (UPPER);
break;
case LOWER:
if (val >= beta)
return (LOWER);
break;
}
}
}
htable += ((temp_hashkey >> log_hash) & 1) + 1;
}
return (avoid_null);
}
It's about this line:
Code: Select all
" htable->word1 =
(word1 & 0x1fffffffffffffffULL) | ((BITBOARD) transposition_id << 61);
"
This is why you could post about a dead old crafty 22.9 and not 23.x series which have a better implementation there.
Also between the read and the write there is a branch that gets mispredicted as odds is tiny you take it. Let's say a clock or 20 you lose there in a non-pgo'ed compile, as it's an expensive branch, which increases the bug's odds to occur.
So there is quite some clocks between the read and the 8 bytes write.
If another core writes a different entry to this slot, then you have with quite some big odds, i'd guess 70% roughly, an illegal move in there...
So for this bug to exist there is no need for some instruction stream interruption (which has very small odds of occuring at exactly this spot).
It's a bug.