Micro optimize pawn moves generation

It is very rare we have pawns on 7(2) rank, so we
can skip the promotion handling stuff in most cases.

With this patch pawn moves generation is almost 20% faster.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
Marco Costalba
2009-07-14 08:53:22 +02:00
parent 2a461b4b74
commit 20ed03fc0b

View File

@@ -61,7 +61,7 @@ namespace {
MoveStack* generate_pawn_captures(const Position& pos, MoveStack* mlist); MoveStack* generate_pawn_captures(const Position& pos, MoveStack* mlist);
template<Color Us, SquareDelta Diagonal> template<Color Us, SquareDelta Diagonal>
MoveStack* generate_pawn_captures_diagonal(MoveStack* mlist, Bitboard pawns, Bitboard enemyPieces); MoveStack* generate_pawn_captures_diagonal(MoveStack* mlist, Bitboard pawns, Bitboard enemyPieces, bool promotion);
template<Color Us> template<Color Us>
MoveStack* generate_pawn_noncaptures(const Position& pos, MoveStack* mlist); MoveStack* generate_pawn_noncaptures(const Position& pos, MoveStack* mlist);
@@ -611,7 +611,7 @@ namespace {
} }
template<Color Us, SquareDelta Diagonal> template<Color Us, SquareDelta Diagonal>
MoveStack* generate_pawn_captures_diagonal(MoveStack* mlist, Bitboard pawns, Bitboard enemyPieces) { MoveStack* generate_pawn_captures_diagonal(MoveStack* mlist, Bitboard pawns, Bitboard enemyPieces, bool promotion) {
// Calculate our parametrized parameters at compile time // Calculate our parametrized parameters at compile time
const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB); const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
@@ -626,18 +626,21 @@ namespace {
Bitboard b1 = move_pawns<Us, Diagonal>(pawns) & ~TFileABB & enemyPieces; Bitboard b1 = move_pawns<Us, Diagonal>(pawns) & ~TFileABB & enemyPieces;
// Capturing promotions // Capturing promotions
if (promotion)
{
Bitboard b2 = b1 & TRank8BB; Bitboard b2 = b1 & TRank8BB;
b1 &= ~TRank8BB;
while (b2) while (b2)
{ {
to = pop_1st_bit(&b2); to = pop_1st_bit(&b2);
(*mlist++).move = make_promotion_move(to - TTDELTA_NE, to, QUEEN); (*mlist++).move = make_promotion_move(to - TTDELTA_NE, to, QUEEN);
} }
}
// Capturing non-promotions // Capturing non-promotions
b2 = b1 & ~TRank8BB; while (b1)
while (b2)
{ {
to = pop_1st_bit(&b2); to = pop_1st_bit(&b1);
(*mlist++).move = make_move(to - TTDELTA_NE, to); (*mlist++).move = make_move(to - TTDELTA_NE, to);
} }
return mlist; return mlist;
@@ -649,23 +652,28 @@ namespace {
// Calculate our parametrized parameters at compile time // Calculate our parametrized parameters at compile time
const Color Them = (Us == WHITE ? BLACK : WHITE); const Color Them = (Us == WHITE ? BLACK : WHITE);
const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB); const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
const Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
const SquareDelta TDELTA_N = (Us == WHITE ? DELTA_N : DELTA_S); const SquareDelta TDELTA_N = (Us == WHITE ? DELTA_N : DELTA_S);
Square to; Square to;
Bitboard pawns = pos.pawns(Us); Bitboard pawns = pos.pawns(Us);
Bitboard enemyPieces = pos.pieces_of_color(opposite_color(Us)); Bitboard enemyPieces = pos.pieces_of_color(opposite_color(Us));
bool possiblePromotion = (pawns & TRank7BB);
// Standard captures and capturing promotions in both directions // Standard captures and capturing promotions in both directions
mlist = generate_pawn_captures_diagonal<Us, DELTA_NE>(mlist, pawns, enemyPieces); mlist = generate_pawn_captures_diagonal<Us, DELTA_NE>(mlist, pawns, enemyPieces, possiblePromotion);
mlist = generate_pawn_captures_diagonal<Us, DELTA_NW>(mlist, pawns, enemyPieces); mlist = generate_pawn_captures_diagonal<Us, DELTA_NW>(mlist, pawns, enemyPieces, possiblePromotion);
// Non-capturing promotions // Non-capturing promotions
if (possiblePromotion)
{
Bitboard b1 = move_pawns<Us, DELTA_N>(pawns) & pos.empty_squares() & TRank8BB; Bitboard b1 = move_pawns<Us, DELTA_N>(pawns) & pos.empty_squares() & TRank8BB;
while (b1) while (b1)
{ {
to = pop_1st_bit(&b1); to = pop_1st_bit(&b1);
(*mlist++).move = make_promotion_move(to - TDELTA_N, to, QUEEN); (*mlist++).move = make_promotion_move(to - TDELTA_N, to, QUEEN);
} }
}
// En passant captures // En passant captures
if (pos.ep_square() != SQ_NONE) if (pos.ep_square() != SQ_NONE)
@@ -673,7 +681,7 @@ namespace {
assert(Us != WHITE || square_rank(pos.ep_square()) == RANK_6); assert(Us != WHITE || square_rank(pos.ep_square()) == RANK_6);
assert(Us != BLACK || square_rank(pos.ep_square()) == RANK_3); assert(Us != BLACK || square_rank(pos.ep_square()) == RANK_3);
b1 = pawns & pos.pawn_attacks(Them, pos.ep_square()); Bitboard b1 = pawns & pos.pawn_attacks(Them, pos.ep_square());
assert(b1 != EmptyBoardBB); assert(b1 != EmptyBoardBB);
while (b1) while (b1)
@@ -690,6 +698,7 @@ namespace {
// Calculate our parametrized parameters at compile time // Calculate our parametrized parameters at compile time
const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB); const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
const Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB); const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
const SquareDelta TDELTA_NE = (Us == WHITE ? DELTA_NE : DELTA_SE); const SquareDelta TDELTA_NE = (Us == WHITE ? DELTA_NE : DELTA_SE);
const SquareDelta TDELTA_NW = (Us == WHITE ? DELTA_NW : DELTA_SW); const SquareDelta TDELTA_NW = (Us == WHITE ? DELTA_NW : DELTA_SW);
@@ -698,9 +707,12 @@ namespace {
Bitboard b1, b2; Bitboard b1, b2;
Square to; Square to;
Bitboard pawns = pos.pawns(Us); Bitboard pawns = pos.pawns(Us);
Bitboard enemyPieces = pos.pieces_of_color(opposite_color(Us));
Bitboard emptySquares = pos.empty_squares(); Bitboard emptySquares = pos.empty_squares();
if (pawns & TRank7BB) // There is some promotion candidate ?
{
Bitboard enemyPieces = pos.pieces_of_color(opposite_color(Us));
// Underpromotion captures in the a1-h8 (a8-h1 for black) direction // Underpromotion captures in the a1-h8 (a8-h1 for black) direction
b1 = move_pawns<Us, DELTA_NE>(pawns) & ~FileABB & enemyPieces & TRank8BB; b1 = move_pawns<Us, DELTA_NE>(pawns) & ~FileABB & enemyPieces & TRank8BB;
while (b1) while (b1)
@@ -721,17 +733,19 @@ namespace {
(*mlist++).move = make_promotion_move(to - TDELTA_NW, to, KNIGHT); (*mlist++).move = make_promotion_move(to - TDELTA_NW, to, KNIGHT);
} }
// Single pawn pushes // Underpromotion pawn pushes
b1 = move_pawns<Us, DELTA_N>(pawns) & emptySquares; b1 = move_pawns<Us, DELTA_N>(pawns) & emptySquares & TRank8BB;
b2 = b1 & TRank8BB; while (b1)
while (b2)
{ {
to = pop_1st_bit(&b2); to = pop_1st_bit(&b1);
(*mlist++).move = make_promotion_move(to - TDELTA_N, to, ROOK); (*mlist++).move = make_promotion_move(to - TDELTA_N, to, ROOK);
(*mlist++).move = make_promotion_move(to - TDELTA_N, to, BISHOP); (*mlist++).move = make_promotion_move(to - TDELTA_N, to, BISHOP);
(*mlist++).move = make_promotion_move(to - TDELTA_N, to, KNIGHT); (*mlist++).move = make_promotion_move(to - TDELTA_N, to, KNIGHT);
} }
b2 = b1 & ~TRank8BB; }
// Single pawn pushes
b2 = b1 = move_pawns<Us, DELTA_N>(pawns) & emptySquares & ~TRank8BB;
while (b2) while (b2)
{ {
to = pop_1st_bit(&b2); to = pop_1st_bit(&b2);