Unify BitCountType selection
authorMarco Costalba <mcostalba@gmail.com>
Sat, 31 Dec 2011 08:46:43 +0000 (09:46 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Sat, 31 Dec 2011 09:46:14 +0000 (10:46 +0100)
Now that HasPopCnt is a compile time constant we can
centralize and unify the BitCountType selection.

Also rename count_1s() in the more standard popcount()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/bitboard.cpp
src/bitcount.h
src/endgame.cpp
src/evaluate.cpp
src/pawns.cpp
src/position.cpp

index 04e5204b5d680d417c7df587379e3d3a9f0c35d5..e4e409583bcd4b71ebc0bc853746a7c6b0062f1c 100644 (file)
@@ -154,7 +154,7 @@ Square pop_1st_bit(Bitboard* bb) {
 void bitboards_init() {
 
   for (Bitboard b = 0; b < 256; b++)
-      BitCount8Bit[b] = (uint8_t)count_1s<CNT32_MAX15>(b);
+      BitCount8Bit[b] = (uint8_t)popcount<Max15>(b);
 
   for (Square s = SQ_A1; s <= SQ_H8; s++)
   {
@@ -321,7 +321,7 @@ namespace {
         // the number of 1s of the mask. Hence we deduce the size of the shift to
         // apply to the 64 or 32 bits word to get the index.
         masks[s]  = sliding_attacks(pt, s, 0) & ~edges;
-        shifts[s] = (Is64Bit ? 64 : 32) - count_1s<CNT32_MAX15>(masks[s]);
+        shifts[s] = (Is64Bit ? 64 : 32) - popcount<Max15>(masks[s]);
 
         // Use Carry-Rippler trick to enumerate all subsets of masks[s] and
         // store the corresponding sliding attacks bitboard in reference[].
index 72ee37ca98dc997cf6fd9ed46696752a637c1b1e..9d25a5e5c1b4d7b7bd19c0bd0cd60234209741a5 100644 (file)
 #if !defined(BITCOUNT_H_INCLUDED)
 #define BITCOUNT_H_INCLUDED
 
+#include <cassert>
 #include "types.h"
 
 enum BitCountType {
-    CNT64,
-    CNT64_MAX15,
-    CNT32,
-    CNT32_MAX15,
-    CNT_POPCNT
+  CNT_64,
+  CNT_64_MAX15,
+  CNT_32,
+  CNT_32_MAX15,
+  CNT_HW_POPCNT
 };
 
-/// count_1s() counts the number of nonzero bits in a bitboard.
-/// We have different optimized versions according if platform
-/// is 32 or 64 bits, and to the maximum number of nonzero bits.
-/// We also support hardware popcnt instruction. See Readme.txt
-/// on how to pgo compile with popcnt support.
-template<BitCountType> inline int count_1s(Bitboard);
+/// Determine at compile time the best popcount<> specialization according if
+/// platform is 32 or 64 bits, to the maximum number of nonzero bits to count or
+/// use hardware popcnt instruction when available.
+const BitCountType Full  = HasPopCnt ? CNT_HW_POPCNT : Is64Bit ? CNT_64 : CNT_32;
+const BitCountType Max15 = HasPopCnt ? CNT_HW_POPCNT : Is64Bit ? CNT_64_MAX15 : CNT_32_MAX15;
+
+
+/// popcount() counts the number of nonzero bits in a bitboard
+template<BitCountType> inline int popcount(Bitboard);
 
 template<>
-inline int count_1s<CNT64>(Bitboard b) {
+inline int popcount<CNT_64>(Bitboard b) {
   b -= ((b>>1) & 0x5555555555555555ULL);
   b = ((b>>2) & 0x3333333333333333ULL) + (b & 0x3333333333333333ULL);
   b = ((b>>4) + b) & 0x0F0F0F0F0F0F0F0FULL;
@@ -48,7 +52,7 @@ inline int count_1s<CNT64>(Bitboard b) {
 }
 
 template<>
-inline int count_1s<CNT64_MAX15>(Bitboard b) {
+inline int popcount<CNT_64_MAX15>(Bitboard b) {
   b -= (b>>1) & 0x5555555555555555ULL;
   b = ((b>>2) & 0x3333333333333333ULL) + (b & 0x3333333333333333ULL);
   b *= 0x1111111111111111ULL;
@@ -56,7 +60,7 @@ inline int count_1s<CNT64_MAX15>(Bitboard b) {
 }
 
 template<>
-inline int count_1s<CNT32>(Bitboard b) {
+inline int popcount<CNT_32>(Bitboard b) {
   unsigned w = unsigned(b >> 32), v = unsigned(b);
   v -= (v >> 1) & 0x55555555; // 0-2 in 2 bits
   w -= (w >> 1) & 0x55555555;
@@ -69,7 +73,7 @@ inline int count_1s<CNT32>(Bitboard b) {
 }
 
 template<>
-inline int count_1s<CNT32_MAX15>(Bitboard b) {
+inline int popcount<CNT_32_MAX15>(Bitboard b) {
   unsigned w = unsigned(b >> 32), v = unsigned(b);
   v -= (v >> 1) & 0x55555555; // 0-2 in 2 bits
   w -= (w >> 1) & 0x55555555;
@@ -81,17 +85,27 @@ inline int count_1s<CNT32_MAX15>(Bitboard b) {
 }
 
 template<>
-inline int count_1s<CNT_POPCNT>(Bitboard b) {
+inline int popcount<CNT_HW_POPCNT>(Bitboard b) {
+
 #if !defined(USE_POPCNT)
+
+  assert(false);
   return int(b != 0); // Avoid 'b not used' warning
+
 #elif defined(_MSC_VER) && defined(__INTEL_COMPILER)
+
   return _mm_popcnt_u64(b);
+
 #elif defined(_MSC_VER)
+
   return (int)__popcnt64(b);
-#elif defined(__GNUC__)
+
+#else
+
   unsigned long ret;
   __asm__("popcnt %1, %0" : "=r" (ret) : "r" (b));
   return ret;
+
 #endif
 }
 
index e44212b887b042109f241dd89515c72ce2fa16b4..19c5b0b8c6c45c97d89d5538095ed447680c8c15 100644 (file)
@@ -369,7 +369,7 @@ Value Endgame<KBBKN>::operator()(const Position& pos) const {
   result += Value(square_distance(bksq, nsq) * 32);
 
   // Bonus for restricting the knight's mobility
-  result += Value((8 - count_1s<CNT32_MAX15>(pos.attacks_from<KNIGHT>(nsq))) * 8);
+  result += Value((8 - popcount<Max15>(pos.attacks_from<KNIGHT>(nsq))) * 8);
 
   return strongerSide == pos.side_to_move() ? result : -result;
 }
index 2f51b1c3c766382f54b690f2ab6c1598decd424e..a48dc13e7219422f1385f0d273f156842be70c20 100644 (file)
@@ -422,7 +422,6 @@ namespace {
   template<Color Us>
   void init_eval_info(const Position& pos, EvalInfo& ei) {
 
-    const BitCountType Max15 = HasPopCnt ? CNT_POPCNT : Is64Bit ? CNT64_MAX15 : CNT32_MAX15;
     const Color Them = (Us == WHITE ? BLACK : WHITE);
 
     Bitboard b = ei.attackedBy[Them][KING] = pos.attacks_from<KING>(pos.king_square(Them));
@@ -434,7 +433,7 @@ namespace {
     {
         ei.kingRing[Them] = (b | (Us == WHITE ? b >> 8 : b << 8));
         b &= ei.attackedBy[Us][PAWN];
-        ei.kingAttackersCount[Us] = b ? count_1s<Max15>(b) / 2 : 0;
+        ei.kingAttackersCount[Us] = b ? popcount<Max15>(b) / 2 : 0;
         ei.kingAdjacentZoneAttacksCount[Us] = ei.kingAttackersWeight[Us] = 0;
     } else
         ei.kingRing[Them] = ei.kingAttackersCount[Us] = 0;
@@ -478,8 +477,6 @@ namespace {
     File f;
     Score score = SCORE_ZERO;
 
-    const BitCountType Full  = HasPopCnt ? CNT_POPCNT : Is64Bit ? CNT64 : CNT32;
-    const BitCountType Max15 = HasPopCnt ? CNT_POPCNT : Is64Bit ? CNT64_MAX15 : CNT32_MAX15;
     const Color Them = (Us == WHITE ? BLACK : WHITE);
     const Square* pl = pos.piece_list(Us, Piece);
 
@@ -507,12 +504,12 @@ namespace {
             ei.kingAttackersWeight[Us] += KingAttackWeights[Piece];
             Bitboard bb = (b & ei.attackedBy[Them][KING]);
             if (bb)
-                ei.kingAdjacentZoneAttacksCount[Us] += count_1s<Max15>(bb);
+                ei.kingAdjacentZoneAttacksCount[Us] += popcount<Max15>(bb);
         }
 
         // Mobility
-        mob = (Piece != QUEEN ? count_1s<Max15>(b & mobilityArea)
-                              : count_1s<Full >(b & mobilityArea));
+        mob = (Piece != QUEEN ? popcount<Max15>(b & mobilityArea)
+                              : popcount<Full >(b & mobilityArea));
 
         mobility += MobilityBonus[Piece][mob];
 
@@ -667,7 +664,6 @@ namespace {
   template<Color Us, bool Trace>
   Score evaluate_king(const Position& pos, EvalInfo& ei, Value margins[]) {
 
-    const BitCountType Max15 = HasPopCnt ? CNT_POPCNT : Is64Bit ? CNT64_MAX15 : CNT32_MAX15;
     const Color Them = (Us == WHITE ? BLACK : WHITE);
 
     Bitboard undefended, b, b1, b2, safe;
@@ -695,7 +691,7 @@ namespace {
         // attacked and undefended squares around our king, the square of the
         // king, and the quality of the pawn shelter.
         attackUnits =  std::min(25, (ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them]) / 2)
-                     + 3 * (ei.kingAdjacentZoneAttacksCount[Them] + count_1s<Max15>(undefended))
+                     + 3 * (ei.kingAdjacentZoneAttacksCount[Them] + popcount<Max15>(undefended))
                      + InitKingDanger[relative_square(Us, ksq)]
                      - mg_value(ei.pi->king_shelter<Us>(pos, ksq)) / 32;
 
@@ -709,7 +705,7 @@ namespace {
                   | ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][ROOK]);
             if (b)
                 attackUnits +=  QueenContactCheckBonus
-                              * count_1s<Max15>(b)
+                              * popcount<Max15>(b)
                               * (Them == pos.side_to_move() ? 2 : 1);
         }
 
@@ -727,7 +723,7 @@ namespace {
                   | ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][QUEEN]);
             if (b)
                 attackUnits +=  RookContactCheckBonus
-                              * count_1s<Max15>(b)
+                              * popcount<Max15>(b)
                               * (Them == pos.side_to_move() ? 2 : 1);
         }
 
@@ -740,22 +736,22 @@ namespace {
         // Enemy queen safe checks
         b = (b1 | b2) & ei.attackedBy[Them][QUEEN];
         if (b)
-            attackUnits += QueenCheckBonus * count_1s<Max15>(b);
+            attackUnits += QueenCheckBonus * popcount<Max15>(b);
 
         // Enemy rooks safe checks
         b = b1 & ei.attackedBy[Them][ROOK];
         if (b)
-            attackUnits += RookCheckBonus * count_1s<Max15>(b);
+            attackUnits += RookCheckBonus * popcount<Max15>(b);
 
         // Enemy bishops safe checks
         b = b2 & ei.attackedBy[Them][BISHOP];
         if (b)
-            attackUnits += BishopCheckBonus * count_1s<Max15>(b);
+            attackUnits += BishopCheckBonus * popcount<Max15>(b);
 
         // Enemy knights safe checks
         b = pos.attacks_from<KNIGHT>(ksq) & ei.attackedBy[Them][KNIGHT] & safe;
         if (b)
-            attackUnits += KnightCheckBonus * count_1s<Max15>(b);
+            attackUnits += KnightCheckBonus * popcount<Max15>(b);
 
         // To index KingDangerTable[] attackUnits must be in [0, 99] range
         attackUnits = std::min(99, std::max(0, attackUnits));
@@ -879,8 +875,6 @@ namespace {
 
   Score evaluate_unstoppable_pawns(const Position& pos, EvalInfo& ei) {
 
-    const BitCountType Max15 = HasPopCnt ? CNT_POPCNT : Is64Bit ? CNT64_MAX15 : CNT32_MAX15;
-
     Bitboard b, b2, blockers, supporters, queeningPath, candidates;
     Square s, blockSq, queeningSquare;
     Color c, winnerSide, loserSide;
@@ -918,7 +912,7 @@ namespace {
             assert((queeningPath & pos.occupied_squares()) == (queeningPath & pos.pieces(c)));
 
             // Add moves needed to free the path from friendly pieces and retest condition
-            movesToGo += count_1s<Max15>(queeningPath & pos.pieces(c));
+            movesToGo += popcount<Max15>(queeningPath & pos.pieces(c));
 
             if (movesToGo >= oppMovesToGo && !pathDefended)
                 continue;
@@ -1046,7 +1040,6 @@ namespace {
   template<Color Us>
   int evaluate_space(const Position& pos, EvalInfo& ei) {
 
-    const BitCountType Max15 = HasPopCnt ? CNT_POPCNT : Is64Bit ? CNT64_MAX15 : CNT32_MAX15;
     const Color Them = (Us == WHITE ? BLACK : WHITE);
 
     // Find the safe squares for our pieces inside the area defined by
@@ -1062,7 +1055,7 @@ namespace {
     behind |= (Us == WHITE ? behind >>  8 : behind <<  8);
     behind |= (Us == WHITE ? behind >> 16 : behind << 16);
 
-    return count_1s<Max15>(safe) + count_1s<Max15>(behind & safe);
+    return popcount<Max15>(safe) + popcount<Max15>(behind & safe);
   }
 
 
index f05be8242196e5e3762ecb81da14e79b2b325758..35bc45aea2dd1f4105571db9aefb1a1fbc9b69ef 100644 (file)
@@ -116,7 +116,6 @@ template<Color Us>
 Score PawnInfoTable::evaluate_pawns(const Position& pos, Bitboard ourPawns,
                                     Bitboard theirPawns, PawnInfo* pi) {
 
-  const BitCountType Max15 = Is64Bit ? CNT64_MAX15 : CNT32_MAX15;
   const Color Them = (Us == WHITE ? BLACK : WHITE);
 
   Bitboard b;
@@ -183,7 +182,7 @@ Score PawnInfoTable::evaluate_pawns(const Position& pos, Bitboard ourPawns,
       // enemy pawns in the forward direction on the neighboring files.
       candidate =   !(opposed | passed | backward | isolated)
                  && (b = attack_span_mask(Them, s + pawn_push(Us)) & ourPawns) != 0
-                 &&  count_1s<Max15>(b) >= count_1s<Max15>(attack_span_mask(Us, s) & theirPawns);
+                 &&  popcount<Max15>(b) >= popcount<Max15>(attack_span_mask(Us, s) & theirPawns);
 
       // Passed pawns will be properly scored in evaluation because we need
       // full attack info to evaluate passed pawns. Only the frontmost passed
index a4712559163d132691d65ab072bab0b0ad8f13fb..7ee67e4ca9ef4efae68b87629d6cc8a70eb1993f 100644 (file)
@@ -1691,7 +1691,7 @@ bool Position::pos_is_ok(int* failedStep) const {
 
   // Is there more than 2 checkers?
   if (failedStep) (*failedStep)++;
-  if (debugCheckerCount && count_1s<CNT32>(st->checkersBB) > 2)
+  if (debugCheckerCount && popcount<Full>(st->checkersBB) > 2)
       return false;
 
   // Bitboards OK?
@@ -1760,7 +1760,7 @@ bool Position::pos_is_ok(int* failedStep) const {
   if (debugPieceCounts)
       for (Color c = WHITE; c <= BLACK; c++)
           for (PieceType pt = PAWN; pt <= KING; pt++)
-              if (pieceCount[c][pt] != count_1s<CNT32>(pieces(pt, c)))
+              if (pieceCount[c][pt] != popcount<Full>(pieces(pt, c)))
                   return false;
 
   if (failedStep) (*failedStep)++;