Skip to content

Commit 8fb45ca

Browse files
mstemberazamar
authored andcommitted
Simplify popcnt
Also a speedup(about 1%) on 64-bit w/o hardware popcnt Retire Max15 and Full template parameters (Contributed by Marco Costalba) Now that we have just SW and HW versions, use template default parameter to get rid of explicit template parameters. Retire bitcount.h and move the only defined function to bitboard.h No functional change Resolves #620
1 parent 900279a commit 8fb45ca

File tree

8 files changed

+60
-129
lines changed

8 files changed

+60
-129
lines changed

src/bitboard.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
#include <algorithm>
2222

2323
#include "bitboard.h"
24-
#include "bitcount.h"
2524
#include "misc.h"
2625

26+
uint8_t PopCnt16[1 << 16];
2727
int SquareDistance[SQUARE_NB][SQUARE_NB];
2828

2929
Bitboard RookMasks [SQUARE_NB];
@@ -74,6 +74,16 @@ namespace {
7474
return Is64Bit ? (b * DeBruijn64) >> 58
7575
: ((unsigned(b) ^ unsigned(b >> 32)) * DeBruijn32) >> 26;
7676
}
77+
78+
79+
// popcount16() counts the non-zero bits using SWAR-Popcount algorithm
80+
81+
uint8_t popcount16(uint16_t u) {
82+
u -= (u >> 1) & 0x5555U;
83+
u = ((u >> 2) & 0x3333U) + (u & 0x3333U);
84+
u = ((u >> 4) + u) & 0x0F0FU;
85+
return (u * 0x0101U) >> 8;
86+
}
7787
}
7888

7989
#ifdef NO_BSF
@@ -141,6 +151,9 @@ const std::string Bitboards::pretty(Bitboard b) {
141151

142152
void Bitboards::init() {
143153

154+
for (unsigned i = 0; i < (1 << 16); ++i)
155+
PopCnt16[i] = popcount16(i);
156+
144157
for (Square s = SQ_A1; s <= SQ_H8; ++s)
145158
{
146159
SquareBB[s] = 1ULL << s;
@@ -265,7 +278,7 @@ namespace {
265278
// the number of 1s of the mask. Hence we deduce the size of the shift to
266279
// apply to the 64 or 32 bits word to get the index.
267280
masks[s] = sliding_attack(deltas, s, 0) & ~edges;
268-
shifts[s] = (Is64Bit ? 64 : 32) - popcount<Max15>(masks[s]);
281+
shifts[s] = (Is64Bit ? 64 : 32) - popcount(masks[s]);
269282

270283
// Use Carry-Rippler trick to enumerate all subsets of masks[s] and
271284
// store the corresponding sliding attack bitboard in reference[].
@@ -296,7 +309,7 @@ namespace {
296309
do {
297310
do
298311
magics[s] = rng.sparse_rand<Bitboard>();
299-
while (popcount<Max15>((magics[s] * masks[s]) >> 56) < 6);
312+
while (popcount((magics[s] * masks[s]) >> 56) < 6);
300313

301314
// A good magic must map every possible occupancy to an index that
302315
// looks up the correct sliding attack in the attacks[s] database.

src/bitboard.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,32 @@ inline Bitboard attacks_bb(Piece pc, Square s, Bitboard occupied) {
257257
}
258258

259259

260+
/// popcount() counts the number of non-zero bits in a bitboard
261+
262+
inline int popcount(Bitboard b) {
263+
264+
#ifndef USE_POPCNT
265+
266+
extern uint8_t PopCnt16[1 << 16];
267+
union { Bitboard bb; uint16_t u[4]; } v = { b };
268+
return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]];
269+
270+
#elif defined(_MSC_VER) && defined(__INTEL_COMPILER)
271+
272+
return _mm_popcnt_u64(b);
273+
274+
#elif defined(_MSC_VER)
275+
276+
return (int)__popcnt64(b);
277+
278+
#else // Assumed gcc or compatible compiler
279+
280+
return __builtin_popcountll(b);
281+
282+
#endif
283+
}
284+
285+
260286
/// lsb() and msb() return the least/most significant bit in a non-zero bitboard
261287

262288
#if defined(__GNUC__)

src/bitcount.h

Lines changed: 0 additions & 105 deletions
This file was deleted.

src/endgame.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include <cassert>
2323

2424
#include "bitboard.h"
25-
#include "bitcount.h"
2625
#include "endgame.h"
2726
#include "movegen.h"
2827

src/evaluate.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#include <iomanip>
2525
#include <sstream>
2626

27-
#include "bitcount.h"
27+
#include "bitboard.h"
2828
#include "evaluate.h"
2929
#include "material.h"
3030
#include "pawns.h"
@@ -234,7 +234,7 @@ namespace {
234234
{
235235
ei.kingRing[Them] = b | shift_bb<Down>(b);
236236
b &= ei.attackedBy[Us][PAWN];
237-
ei.kingAttackersCount[Us] = b ? popcount<Max15>(b) : 0;
237+
ei.kingAttackersCount[Us] = b ? popcount(b) : 0;
238238
ei.kingAdjacentZoneAttacksCount[Us] = ei.kingAttackersWeight[Us] = 0;
239239
}
240240
else
@@ -278,15 +278,15 @@ namespace {
278278
ei.kingAttackersWeight[Us] += KingAttackWeights[Pt];
279279
bb = b & ei.attackedBy[Them][KING];
280280
if (bb)
281-
ei.kingAdjacentZoneAttacksCount[Us] += popcount<Max15>(bb);
281+
ei.kingAdjacentZoneAttacksCount[Us] += popcount(bb);
282282
}
283283

284284
if (Pt == QUEEN)
285285
b &= ~( ei.attackedBy[Them][KNIGHT]
286286
| ei.attackedBy[Them][BISHOP]
287287
| ei.attackedBy[Them][ROOK]);
288288

289-
int mob = popcount<Pt == QUEEN ? Full : Max15>(b & mobilityArea[Us]);
289+
int mob = popcount(b & mobilityArea[Us]);
290290

291291
mobility[Us] += MobilityBonus[Pt][mob];
292292

@@ -334,7 +334,7 @@ namespace {
334334
{
335335
Bitboard alignedPawns = pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s];
336336
if (alignedPawns)
337-
score += RookOnPawn * popcount<Max15>(alignedPawns);
337+
score += RookOnPawn * popcount(alignedPawns);
338338
}
339339

340340
// Bonus when on an open or semi-open file
@@ -399,7 +399,7 @@ namespace {
399399
// the pawn shelter (current 'score' value).
400400
attackUnits = std::min(72, ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them])
401401
+ 9 * ei.kingAdjacentZoneAttacksCount[Them]
402-
+ 27 * popcount<Max15>(undefended)
402+
+ 27 * popcount(undefended)
403403
+ 11 * !!ei.pinnedPieces[Us]
404404
- 64 * !pos.count<QUEEN>(Them)
405405
- mg_value(score) / 8;
@@ -415,7 +415,7 @@ namespace {
415415
| ei.attackedBy[Them][KING];
416416

417417
if (b)
418-
attackUnits += QueenContactCheck * popcount<Max15>(b);
418+
attackUnits += QueenContactCheck * popcount(b);
419419
}
420420

421421
// Analyse the enemy's safe distance checks for sliders and knights
@@ -513,7 +513,7 @@ namespace {
513513

514514
b = weak & ~ei.attackedBy[Them][ALL_PIECES];
515515
if (b)
516-
score += Hanging * popcount<Max15>(b);
516+
score += Hanging * popcount(b);
517517

518518
b = weak & ei.attackedBy[Us][KING];
519519
if (b)
@@ -533,7 +533,7 @@ namespace {
533533
& ~ei.attackedBy[Us][PAWN];
534534

535535
if (b)
536-
score += ThreatByPawnPush * popcount<Max15>(b);
536+
score += ThreatByPawnPush * popcount(b);
537537

538538
if (DoTrace)
539539
Trace::add(THREAT, Us, score);
@@ -656,7 +656,7 @@ namespace {
656656
assert(unsigned(safe >> (Us == WHITE ? 32 : 0)) == 0);
657657

658658
// ...count safe + (behind & safe) with a single popcount
659-
int bonus = popcount<Full>((Us == WHITE ? safe << 32 : safe >> 32) | (behind & safe));
659+
int bonus = popcount((Us == WHITE ? safe << 32 : safe >> 32) | (behind & safe));
660660
int weight = pos.count<KNIGHT>(Us) + pos.count<BISHOP>(Us)
661661
+ pos.count<KNIGHT>(Them) + pos.count<BISHOP>(Them);
662662

src/pawns.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include <cassert>
2323

2424
#include "bitboard.h"
25-
#include "bitcount.h"
2625
#include "pawns.h"
2726
#include "position.h"
2827
#include "thread.h"
@@ -114,7 +113,7 @@ namespace {
114113
e->kingSquares[Us] = SQ_NONE;
115114
e->semiopenFiles[Us] = 0xFF;
116115
e->pawnAttacks[Us] = shift_bb<Right>(ourPawns) | shift_bb<Left>(ourPawns);
117-
e->pawnsOnSquares[Us][BLACK] = popcount<Max15>(ourPawns & DarkSquares);
116+
e->pawnsOnSquares[Us][BLACK] = popcount(ourPawns & DarkSquares);
118117
e->pawnsOnSquares[Us][WHITE] = pos.count<PAWN>(Us) - e->pawnsOnSquares[Us][BLACK];
119118

120119
// Loop through all pawns of the current color and score each pawn
@@ -233,7 +232,7 @@ Entry* probe(const Position& pos) {
233232

234233
e->key = key;
235234
e->score = evaluate<WHITE>(pos, e) - evaluate<BLACK>(pos, e);
236-
e->asymmetry = popcount<Max15>(e->semiopenFiles[WHITE] ^ e->semiopenFiles[BLACK]);
235+
e->asymmetry = popcount(e->semiopenFiles[WHITE] ^ e->semiopenFiles[BLACK]);
237236
return e;
238237
}
239238

src/position.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#include <iomanip>
2525
#include <sstream>
2626

27-
#include "bitcount.h"
27+
#include "bitboard.h"
2828
#include "misc.h"
2929
#include "movegen.h"
3030
#include "position.h"
@@ -1170,7 +1170,7 @@ bool Position::pos_is_ok(int* failedStep) const {
11701170
for (Color c = WHITE; c <= BLACK; ++c)
11711171
for (PieceType pt = PAWN; pt <= KING; ++pt)
11721172
{
1173-
if (pieceCount[c][pt] != popcount<Full>(pieces(c, pt)))
1173+
if (pieceCount[c][pt] != popcount(pieces(c, pt)))
11741174
return false;
11751175

11761176
for (int i = 0; i < pieceCount[c][pt]; ++i)

src/syzygy/tbprobe.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include "../movegen.h"
1616
#include "../bitboard.h"
1717
#include "../search.h"
18-
#include "../bitcount.h"
1918

2019
#include "tbprobe.h"
2120
#include "tbcore.h"
@@ -39,12 +38,12 @@ static void prt_str(Position& pos, char *str, int mirror)
3938

4039
color = !mirror ? WHITE : BLACK;
4140
for (pt = KING; pt >= PAWN; --pt)
42-
for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
41+
for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
4342
*str++ = pchr[6 - pt];
4443
*str++ = 'v';
4544
color = ~color;
4645
for (pt = KING; pt >= PAWN; --pt)
47-
for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
46+
for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
4847
*str++ = pchr[6 - pt];
4948
*str++ = 0;
5049
}
@@ -60,11 +59,11 @@ static uint64 calc_key(Position& pos, int mirror)
6059

6160
color = !mirror ? WHITE : BLACK;
6261
for (pt = PAWN; pt <= KING; ++pt)
63-
for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
62+
for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
6463
key ^= Zobrist::psq[WHITE][pt][i - 1];
6564
color = ~color;
6665
for (pt = PAWN; pt <= KING; ++pt)
67-
for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
66+
for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
6867
key ^= Zobrist::psq[BLACK][pt][i - 1];
6968

7069
return key;

0 commit comments

Comments
 (0)