When the stored TT value equals the static value set a
proper flag so to not call evaluation() if we hit the
same position again but use the stored TT value instead.
This is another trick to avoid calling costly evaluation()
in qsearch.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
if (isCheck)
staticValue = -VALUE_INFINITE;
if (isCheck)
staticValue = -VALUE_INFINITE;
- else if (tte && tte->type() == VALUE_TYPE_EVAL)
+ else if (tte && (tte->type() == VALUE_TYPE_EVAL || tte->staticValue()))
{
// Use the cached evaluation score if possible
assert(tte->value() == evaluate(pos, ei, threadID));
{
// Use the cached evaluation score if possible
assert(tte->value() == evaluate(pos, ei, threadID));
if (!pvNode)
{
Depth d = (depth == Depth(0) ? Depth(0) : Depth(-1));
if (!pvNode)
{
Depth d = (depth == Depth(0) ? Depth(0) : Depth(-1));
+ Value v = value_to_tt(bestValue, ply);
+ TTEntry* e;
- TT.store(pos, value_to_tt(bestValue, ply), d, MOVE_NONE, VALUE_TYPE_UPPER);
+ e = TT.store(pos, v, d, MOVE_NONE, VALUE_TYPE_UPPER);
- TT.store(pos, value_to_tt(bestValue, ply), d, MOVE_NONE, VALUE_TYPE_LOWER);
+ e = TT.store(pos, v, d, MOVE_NONE, VALUE_TYPE_LOWER);
+
+ assert(e && e == TT.retrieve(pos));
+ assert(!e->staticValue());
+
+ // If the just stored value happens to be equal to the static evaluation
+ // score then set the flag, so to avoid calling evaluation() next time we
+ // hit this position.
+ if (staticValue == v && !ei.futilityMargin)
+ e->setStaticValue();
}
// Update killers only for good check moves
}
// Update killers only for good check moves
/// current search and t2 is from a previous search, or if the depth of t1
/// is bigger than the depth of t2.
/// current search and t2 is from a previous search, or if the depth of t1
/// is bigger than the depth of t2.
-void TranspositionTable::store(const Position &pos, Value v, Depth d,
+TTEntry* TranspositionTable::store(const Position &pos, Value v, Depth d,
Move m, ValueType type) {
TTEntry *tte, *replace;
Move m, ValueType type) {
TTEntry *tte, *replace;
m = tte->move();
*tte = TTEntry(pos.get_key(), v, type, d, m, generation);
m = tte->move();
*tte = TTEntry(pos.get_key(), v, type, d, m, generation);
}
else if (i == 0) // replace would be a no-op in this common case
continue;
}
else if (i == 0) // replace would be a no-op in this common case
continue;
}
*replace = TTEntry(pos.get_key(), v, type, d, m, generation);
writes++;
}
*replace = TTEntry(pos.get_key(), v, type, d, m, generation);
writes++;
/// the 32 bits of the data field are so defined
///
/// bit 0-16: move
/// the 32 bits of the data field are so defined
///
/// bit 0-16: move
+/// bit 17: stored value equals static value
+/// bit 18-19: not used
/// bit 20-22: value type
/// bit 23-31: generation
/// bit 20-22: value type
/// bit 23-31: generation
Value value() const { return Value(value_); }
ValueType type() const { return ValueType((data >> 20) & 7); }
int generation() const { return (data >> 23); }
Value value() const { return Value(value_); }
ValueType type() const { return ValueType((data >> 20) & 7); }
int generation() const { return (data >> 23); }
+ bool staticValue() const { return ((data >> 17) & 1); }
+ void setStaticValue() { data |= (1 << 17); }
~TranspositionTable();
void set_size(unsigned mbSize);
void clear();
~TranspositionTable();
void set_size(unsigned mbSize);
void clear();
- void store(const Position &pos, Value v, Depth d, Move m, ValueType type);
+ TTEntry* store(const Position &pos, Value v, Depth d, Move m, ValueType type);
TTEntry* retrieve(const Position &pos) const;
void new_search();
void insert_pv(const Position &pos, Move pv[]);
TTEntry* retrieve(const Position &pos) const;
void new_search();
void insert_pv(const Position &pos, Move pv[]);