Skip to content

Commit

Permalink
Speedups (#452)
Browse files Browse the repository at this point in the history
Bench: 4873539

Additional speedups for more optimal occupied squares calculations and pinned pieces.

`5.310 %  +/-  1.737 %`
  • Loading branch information
jhonnold authored Jan 21, 2023
1 parent 89eae2f commit 7f804cd
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 100 deletions.
3 changes: 1 addition & 2 deletions src/attacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,7 @@ BitBoard SetPieceLayoutOccupancy(int idx, int bits, BitBoard attacks) {
BitBoard occupany = 0;

for (int i = 0; i < bits; i++) {
int sq = LSB(attacks);
PopLSB(attacks);
int sq = PopLSB(&attacks);

if (idx & (1 << i))
occupany |= (1ULL << sq);
Expand Down
5 changes: 2 additions & 3 deletions src/bits.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
#define PopBit(bb, sq) ((bb) &= ~Bit(sq))
#define FlipBit(bb, sq) ((bb) ^= Bit(sq))
#define FlipBits(bb, sq1, sq2) ((bb) ^= Bit(sq1) ^ Bit(sq2))
#define PopLSB(bb) ((bb) &= (bb) -1)
#define LSB(bb) (__builtin_ctzll(bb))
#define MSB(bb) (63 ^ __builtin_clzll(bb))

Expand Down Expand Up @@ -82,9 +81,9 @@ INLINE uint8_t PawnFiles(BitBoard pawns) {
return (uint8_t) ((pawns | (pawns >> 32)) & 0xFF);
}

INLINE int popAndGetLsb(BitBoard* bb) {
INLINE int PopLSB(BitBoard* bb) {
int sq = LSB(*bb);
PopLSB(*bb);
*bb &= *bb - 1;
return sq;
}

Expand Down
92 changes: 42 additions & 50 deletions src/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,11 @@ void ParseFen(char* fen, Board* board) {

sscanf(fen, " %d %d", &board->fmr, &board->moveNo);

SetOccupancies(board);
OccBB(WHITE) = OccBB(BLACK) = OccBB(BOTH) = 0;
for (int i = WHITE_PAWN; i <= BLACK_KING; i++)
OccBB(i & 1) |= board->pieces[i];
OccBB(BOTH) = OccBB(WHITE) | OccBB(BLACK);

SetSpecialPieces(board);

board->zobrist = Zobrist(board);
Expand Down Expand Up @@ -245,56 +249,28 @@ inline int IsOCB(Board* board) {
BitCount((PieceBB(BISHOP, WHITE) | PieceBB(BISHOP, BLACK)) & DARK_SQS) == 1;
}

// Reset general piece locations on the board
inline void SetOccupancies(Board* board) {
OccBB(WHITE) = 0;
OccBB(BLACK) = 0;
OccBB(BOTH) = 0;

for (int i = WHITE_PAWN; i <= BLACK_KING; i++)
OccBB(i & 1) |= board->pieces[i];
OccBB(BOTH) = OccBB(WHITE) | OccBB(BLACK);
}

// Special pieces are those giving check, and those that are pinned
// these must be recalculated every move for faster move legality purposes
inline void SetSpecialPieces(Board* board) {
int kingSq = LSB(PieceBB(KING, board->stm));

// Reset pinned pieces
board->pinned = 0;
// checked can be initialized easily with non-blockable checks
board->checkers = (GetKnightAttacks(kingSq) & PieceBB(KNIGHT, board->xstm)) |
(GetPawnAttacks(kingSq, board->stm) & PieceBB(PAWN, board->xstm));

// for each side
for (int kingColor = WHITE; kingColor <= BLACK; kingColor++) {
int enemyColor = 1 - kingColor;
kingSq = LSB(PieceBB(KING, kingColor));

// get full rook/bishop rays from the king that intersect that piece type of
// the enemy
BitBoard enemyPiece = ((PieceBB(BISHOP, enemyColor) | PieceBB(QUEEN, enemyColor)) & GetBishopAttacks(kingSq, 0)) |
((PieceBB(ROOK, enemyColor) | PieceBB(QUEEN, enemyColor)) & GetRookAttacks(kingSq, 0));

while (enemyPiece) {
int sq = LSB(enemyPiece);
const int stm = board->stm;
const int xstm = board->xstm;

// is something in the way
BitBoard blockers = BetweenSquares(kingSq, sq) & OccBB(BOTH);
int kingSq = LSB(PieceBB(KING, stm));

if (!blockers)
// no? then its check
board->checkers |= (enemyPiece & -enemyPiece);
else if (BitCount(blockers) == 1)
// just 1? then its pinned
board->pinned |= (blockers & OccBB(kingColor));
board->pinned = 0;
board->checkers = (GetKnightAttacks(kingSq) & PieceBB(KNIGHT, xstm)) | // knight and
(GetPawnAttacks(kingSq, stm) & PieceBB(PAWN, xstm)); // pawns are easy

// TODO: Similar logic can be applied for discoveries, but apply for self
// pieces
BitBoard sliders = ((PieceBB(BISHOP, xstm) | PieceBB(QUEEN, xstm)) & GetBishopAttacks(kingSq, 0)) |
((PieceBB(ROOK, xstm) | PieceBB(QUEEN, xstm)) & GetRookAttacks(kingSq, 0));
while (sliders) {
int sq = PopLSB(&sliders);

PopLSB(enemyPiece);
}
BitBoard blockers = BetweenSquares(kingSq, sq) & OccBB(BOTH);
if (!blockers)
SetBit(board->checkers, sq);
else if (BitCount(blockers) == 1)
board->pinned |= (blockers & OccBB(stm));
}
}

Expand All @@ -320,8 +296,12 @@ void MakeMoveUpdate(Move move, Board* board, int update) {
board->fmr++;

FlipBits(board->pieces[piece], from, to);
FlipBits(OccBB(board->stm), from, to);
FlipBits(OccBB(BOTH), from, to);

board->squares[from] = NO_PIECE;
board->squares[to] = piece;

board->zobrist ^= ZOBRIST_PIECES[piece][from] ^ ZOBRIST_PIECES[piece][to];

if (IsCas(move)) {
Expand All @@ -330,6 +310,8 @@ void MakeMoveUpdate(Move move, Board* board, int update) {
int rook = Piece(ROOK, board->stm);

FlipBits(PieceBB(ROOK, board->stm), rookFrom, rookTo);
FlipBits(OccBB(board->stm), rookFrom, rookTo);
FlipBits(OccBB(BOTH), rookFrom, rookTo);

// chess960 can have the king going where the rook started
// do this check to prevent accidental wipe outs
Expand All @@ -344,7 +326,11 @@ void MakeMoveUpdate(Move move, Board* board, int update) {
board->squares[capSq] = NO_PIECE;

FlipBit(board->pieces[captured], capSq);
FlipBit(OccBB(board->xstm), capSq);
FlipBit(OccBB(BOTH), capSq);

board->zobrist ^= ZOBRIST_PIECES[captured][capSq];

board->piecesCounts -= PieceCount(captured);
board->phase -= PHASE_VALUES[PieceType(captured)];
board->fmr = 0;
Expand Down Expand Up @@ -384,8 +370,6 @@ void MakeMoveUpdate(Move move, Board* board, int update) {
board->fmr = 0;
}

SetOccupancies(board);

int stm = board->stm;

board->histPly++;
Expand Down Expand Up @@ -446,16 +430,20 @@ void UndoMove(Move move, Board* board) {
}

FlipBits(board->pieces[piece], to, from);
FlipBits(OccBB(board->stm), to, from);
FlipBits(OccBB(BOTH), to, from);

board->squares[from] = piece;
board->squares[to] = NO_PIECE;
board->squares[to] = NO_PIECE;

if (IsCas(move)) {
int rookFrom = board->cr[CASTLING_ROOK[to]];
int rookTo = CASTLE_ROOK_DEST[to];
int rook = Piece(ROOK, board->stm);

FlipBits(PieceBB(ROOK, board->stm), rookTo, rookFrom);
FlipBits(OccBB(board->stm), rookTo, rookFrom);
FlipBits(OccBB(BOTH), rookTo, rookFrom);

if (from != rookTo)
board->squares[rookTo] = NO_PIECE;
Expand All @@ -465,12 +453,14 @@ void UndoMove(Move move, Board* board) {
int captured = board->history[board->histPly].capture;

FlipBit(board->pieces[captured], capSq);
FlipBit(OccBB(board->xstm), capSq);
FlipBit(OccBB(BOTH), capSq);

board->squares[capSq] = captured;

board->piecesCounts += PieceCount(captured);
board->phase += PHASE_VALUES[PieceType(captured)];
}

SetOccupancies(board);
}

void MakeNullMove(Board* board) {
Expand All @@ -496,6 +486,8 @@ void MakeNullMove(Board* board) {

// Prefetch the hash entry for this board position
TTPrefetch(board->zobrist);

SetSpecialPieces(board);
}

void UndoNullMove(Board* board) {
Expand Down Expand Up @@ -707,7 +699,7 @@ int IsLegal(Move move, Board* board) {
if (AttacksToSquare(board, i, OccBB(BOTH)) & OccBB(board->xstm))
return 0;

return !CHESS_960 || !GetBit(board->pinned, To(move));
return 1;
}

if (PieceType(Moving(move)) == KING)
Expand Down
5 changes: 0 additions & 5 deletions src/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,14 @@
#define MDistance(a, b) (abs(Rank(a) - Rank(b)) + abs(File(a) - File(b)))
#define PieceCount(pc) (1ull << (pc * 4))

extern const int8_t PSQT[64];
extern const uint16_t KING_BUCKETS[64];

extern const uint64_t PIECE_COUNT_IDX[];

void ClearBoard(Board* board);
void ParseFen(char* fen, Board* board);
void BoardToFen(char* fen, Board* board);
void PrintBoard(Board* board);

void SetSpecialPieces(Board* board);
void SetOccupancies(Board* board);

int DoesMoveCheck(Move move, Board* board);

Expand All @@ -58,7 +54,6 @@ int IsMaterialDraw(Board* board);
int IsFiftyMoveRule(Board* board);

int HasNonPawn(Board* board);
int IsOCB(Board* board);

void MakeNullMove(Board* board);
void UndoNullMove(Board* board);
Expand Down
8 changes: 4 additions & 4 deletions src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ void Threats(Threat* threats, Board* board, int stm) {

BitBoard knights = PieceBB(KNIGHT, stm);
while (knights) {
BitBoard atx = GetKnightAttacks(popAndGetLsb(&knights));
BitBoard atx = GetKnightAttacks(PopLSB(&knights));

threats->sqs |= atx;
threats->pcs |= opponentPieces & atx;
}

BitBoard bishops = PieceBB(BISHOP, stm);
while (bishops) {
BitBoard atx = GetBishopAttacks(popAndGetLsb(&bishops), OccBB(BOTH));
BitBoard atx = GetBishopAttacks(PopLSB(&bishops), OccBB(BOTH));

threats->sqs |= atx;
threats->pcs |= opponentPieces & atx;
Expand All @@ -74,15 +74,15 @@ void Threats(Threat* threats, Board* board, int stm) {

BitBoard rooks = PieceBB(ROOK, stm);
while (rooks) {
BitBoard atx = GetRookAttacks(popAndGetLsb(&rooks), OccBB(BOTH));
BitBoard atx = GetRookAttacks(PopLSB(&rooks), OccBB(BOTH));

threats->sqs |= atx;
threats->pcs |= opponentPieces & atx;
}

BitBoard queens = PieceBB(QUEEN, stm);
while (queens)
threats->sqs |= GetQueenAttacks(popAndGetLsb(&queens), OccBB(BOTH));
threats->sqs |= GetQueenAttacks(PopLSB(&queens), OccBB(BOTH));

threats->sqs |= GetKingAttacks(LSB(PieceBB(KING, stm)));
}
Expand Down
16 changes: 0 additions & 16 deletions src/history.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,19 +99,3 @@ void UpdateHistories(Board* board,
AddHistoryHeuristic(&TH(piece, to, captured), -inc);
}
}

int GetQuietHistory(SearchStack* ss, ThreadData* thread, Move move, int stm, BitBoard threats) {
int history = HH(stm, move, threats);
history += (*(ss - 1)->ch)[Moving(move)][To(move)];
history += (*(ss - 2)->ch)[Moving(move)][To(move)];

return history;
}

int GetCaptureHistory(ThreadData* thread, Board* board, Move m) {
int piece = PieceType(Moving(m));
int to = To(m);
int captured = IsEP(m) ? PAWN : PieceType(board->squares[to]);

return TH(piece, to, captured);
}
15 changes: 13 additions & 2 deletions src/history.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,24 @@
#define HISTORY_H

#include "bits.h"
#include "board.h"
#include "move.h"
#include "types.h"
#include "util.h"

#define HH(stm, m, threats) (thread->hh[stm][!GetBit(threats, From(m))][!GetBit(threats, To(m))][FromTo(m)])
#define TH(p, e, c) (thread->caph[p][e][c])

INLINE int GetQuietHistory(SearchStack* ss, ThreadData* thread, Move move, int stm, BitBoard threats) {
return (int) HH(stm, move, threats) + //
(int) (*(ss - 1)->ch)[Moving(move)][To(move)] + //
(int) (*(ss - 2)->ch)[Moving(move)][To(move)];
}

INLINE int GetCaptureHistory(ThreadData* thread, Board* board, Move move) {
return TH(PieceType(Moving(move)), To(move), IsEP(move) ? PAWN : PieceType(board->squares[To(move)]));
}

void UpdateHistories(Board* board,
SearchStack* ss,
ThreadData* thread,
Expand All @@ -34,7 +47,5 @@ void UpdateHistories(Board* board,
Move captures[],
int nC,
BitBoard threats);
int GetQuietHistory(SearchStack* ss, ThreadData* thread, Move move, int stm, BitBoard threats);
int GetCaptureHistory(ThreadData* thread, Board* board, Move move);

#endif
Loading

0 comments on commit 7f804cd

Please sign in to comment.