Retire run-time detection of hardware POPCNT
authorMarco Costalba <mcostalba@gmail.com>
Fri, 30 Dec 2011 10:30:26 +0000 (11:30 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Fri, 30 Dec 2011 11:17:03 +0000 (12:17 +0100)
It was meant to build a single binary optimized
for any kind of CPU: with and without hardware POPCNT.

This is a nice idea but in practice was never used, or
people builds binary with popcnt enabled or not, mainly
according to their type of CPU. And it was also never
used in the official Jim's builds where, in case, would
be easier for a number of reasons, do build two different
versions: with and without SEE42 support.

So retire this feature and simplify the code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/bitboard.cpp
src/evaluate.cpp
src/main.cpp
src/misc.cpp
src/pawns.cpp
src/types.h

index d9a9daba8b854d4ebdcdb2c3701ff2e38cdb386d..8c7bb9ebfe5e4060d89fa4d5e16a28ece3c40b9d 100644 (file)
@@ -198,7 +198,7 @@ void bitboards_init() {
           SquareDistance[s1][s2] = std::max(file_distance(s1, s2), rank_distance(s1, s2));
 
   for (int i = 0; i < 64; i++)
-      if (!CpuIs64Bit) // Matt Taylor's folding trick for 32 bit systems
+      if (!Is64Bit) // Matt Taylor's folding trick for 32 bit systems
       {
           Bitboard b = 1ULL << i;
           b ^= b - 1;
@@ -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] = (CpuIs64Bit ? 64 : 32) - count_1s<CNT32_MAX15>(masks[s]);
+        shifts[s] = (Is64Bit ? 64 : 32) - count_1s<CNT32_MAX15>(masks[s]);
 
         // Use Carry-Rippler trick to enumerate all subsets of masks[s] and
         // store the corresponding sliding attacks bitboard in reference[].
@@ -337,7 +337,7 @@ namespace {
         if (s < SQ_H8)
             attacks[s + 1] = attacks[s] + size;
 
-        booster = MagicBoosters[CpuIs64Bit][rank_of(s)];
+        booster = MagicBoosters[Is64Bit][rank_of(s)];
 
         // Find a magic for square 's' picking up an (almost) random number
         // until we find the one that passes the verification test.
index 5e278242b742ddd2457d0a7f2312b63e47f5b081..b469050a1cd59b3d9d44e5fd0d6f7ec9aa5db572 100644 (file)
@@ -225,28 +225,27 @@ namespace {
   };
 
   // Function prototypes
-  template<bool HasPopCnt, bool Trace>
+  template<bool Trace>
   Value do_evaluate(const Position& pos, Value& margin);
 
-  template<Color Us, bool HasPopCnt>
+  template<Color Us>
   void init_eval_info(const Position& pos, EvalInfo& ei);
 
-  template<Color Us, bool HasPopCnt, bool Trace>
+  template<Color Us, bool Trace>
   Score evaluate_pieces_of_color(const Position& pos, EvalInfo& ei, Score& mobility);
 
-  template<Color Us, bool HasPopCnt, bool Trace>
+  template<Color Us, bool Trace>
   Score evaluate_king(const Position& pos, EvalInfo& ei, Value margins[]);
 
   template<Color Us>
   Score evaluate_threats(const Position& pos, EvalInfo& ei);
 
-  template<Color Us, bool HasPopCnt>
+  template<Color Us>
   int evaluate_space(const Position& pos, EvalInfo& ei);
 
   template<Color Us>
   Score evaluate_passed_pawns(const Position& pos, EvalInfo& ei);
 
-  template<bool HasPopCnt>
   Score evaluate_unstoppable_pawns(const Position& pos, EvalInfo& ei);
 
   inline Score apply_weight(Score v, Score weight);
@@ -261,15 +260,11 @@ namespace {
 /// evaluate() is the main evaluation function. It always computes two
 /// values, an endgame score and a middle game score, and interpolates
 /// between them based on the remaining material.
-Value evaluate(const Position& pos, Value& margin) {
-
-  return CpuHasPOPCNT ? do_evaluate<true, false>(pos, margin)
-                      : do_evaluate<false, false>(pos, margin);
-}
+Value evaluate(const Position& pos, Value& margin) { return do_evaluate<false>(pos, margin); }
 
 namespace {
 
-template<bool HasPopCnt, bool Trace>
+template<bool Trace>
 Value do_evaluate(const Position& pos, Value& margin) {
 
   EvalInfo ei;
@@ -304,19 +299,19 @@ Value do_evaluate(const Position& pos, Value& margin) {
   score += ei.pi->pawns_value();
 
   // Initialize attack and king safety bitboards
-  init_eval_info<WHITE, HasPopCnt>(pos, ei);
-  init_eval_info<BLACK, HasPopCnt>(pos, ei);
+  init_eval_info<WHITE>(pos, ei);
+  init_eval_info<BLACK>(pos, ei);
 
   // Evaluate pieces and mobility
-  score +=  evaluate_pieces_of_color<WHITE, HasPopCnt, Trace>(pos, ei, mobilityWhite)
-          - evaluate_pieces_of_color<BLACK, HasPopCnt, Trace>(pos, ei, mobilityBlack);
+  score +=  evaluate_pieces_of_color<WHITE, Trace>(pos, ei, mobilityWhite)
+          - evaluate_pieces_of_color<BLACK, Trace>(pos, ei, mobilityBlack);
 
   score += apply_weight(mobilityWhite - mobilityBlack, Weights[Mobility]);
 
   // Evaluate kings after all other pieces because we need complete attack
   // information when computing the king safety evaluation.
-  score +=  evaluate_king<WHITE, HasPopCnt, Trace>(pos, ei, margins)
-          - evaluate_king<BLACK, HasPopCnt, Trace>(pos, ei, margins);
+  score +=  evaluate_king<WHITE, Trace>(pos, ei, margins)
+          - evaluate_king<BLACK, Trace>(pos, ei, margins);
 
   // Evaluate tactical threats, we need full attack information including king
   score +=  evaluate_threats<WHITE>(pos, ei)
@@ -328,12 +323,12 @@ Value do_evaluate(const Position& pos, Value& margin) {
 
   // If one side has only a king, check whether exists any unstoppable passed pawn
   if (!pos.non_pawn_material(WHITE) || !pos.non_pawn_material(BLACK))
-      score += evaluate_unstoppable_pawns<HasPopCnt>(pos, ei);
+      score += evaluate_unstoppable_pawns(pos, ei);
 
   // Evaluate space for both sides, only in middle-game.
   if (ei.mi->space_weight())
   {
-      int s = evaluate_space<WHITE, HasPopCnt>(pos, ei) - evaluate_space<BLACK, HasPopCnt>(pos, ei);
+      int s = evaluate_space<WHITE>(pos, ei) - evaluate_space<BLACK>(pos, ei);
       score += apply_weight(make_score(s * ei.mi->space_weight(), 0), Weights[Space]);
   }
 
@@ -375,9 +370,9 @@ Value do_evaluate(const Position& pos, Value& margin) {
       trace_add(MOBILITY, apply_weight(mobilityWhite, Weights[Mobility]), apply_weight(mobilityBlack, Weights[Mobility]));
       trace_add(THREAT, evaluate_threats<WHITE>(pos, ei), evaluate_threats<BLACK>(pos, ei));
       trace_add(PASSED, evaluate_passed_pawns<WHITE>(pos, ei), evaluate_passed_pawns<BLACK>(pos, ei));
-      trace_add(UNSTOPPABLE, evaluate_unstoppable_pawns<false>(pos, ei));
-      Score w = make_score(ei.mi->space_weight() * evaluate_space<WHITE, false>(pos, ei), 0);
-      Score b = make_score(ei.mi->space_weight() * evaluate_space<BLACK, false>(pos, ei), 0);
+      trace_add(UNSTOPPABLE, evaluate_unstoppable_pawns(pos, ei));
+      Score w = make_score(ei.mi->space_weight() * evaluate_space<WHITE>(pos, ei), 0);
+      Score b = make_score(ei.mi->space_weight() * evaluate_space<BLACK>(pos, ei), 0);
       trace_add(SPACE, apply_weight(w, Weights[Space]), apply_weight(b, Weights[Space]));
       trace_add(TOTAL, score);
       TraceStream << "\nUncertainty margin: White: " << to_cp(margins[WHITE])
@@ -424,10 +419,10 @@ namespace {
   // init_eval_info() initializes king bitboards for given color adding
   // pawn attacks. To be done at the beginning of the evaluation.
 
-  template<Color Us, bool HasPopCnt>
+  template<Color Us>
   void init_eval_info(const Position& pos, EvalInfo& ei) {
 
-    const BitCountType Max15 = HasPopCnt ? CNT_POPCNT : CpuIs64Bit ? CNT64_MAX15 : CNT32_MAX15;
+    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));
@@ -474,7 +469,7 @@ namespace {
 
   // evaluate_pieces<>() assigns bonuses and penalties to the pieces of a given color
 
-  template<PieceType Piece, Color Us, bool HasPopCnt, bool Trace>
+  template<PieceType Piece, Color Us, bool Trace>
   Score evaluate_pieces(const Position& pos, EvalInfo& ei, Score& mobility, Bitboard mobilityArea) {
 
     Bitboard b;
@@ -483,8 +478,8 @@ namespace {
     File f;
     Score score = SCORE_ZERO;
 
-    const BitCountType Full  = HasPopCnt ? CNT_POPCNT : CpuIs64Bit ? CNT64 : CNT32;
-    const BitCountType Max15 = HasPopCnt ? CNT_POPCNT : CpuIs64Bit ? CNT64_MAX15 : CNT32_MAX15;
+    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);
 
@@ -644,7 +639,7 @@ namespace {
   // evaluate_pieces_of_color<>() assigns bonuses and penalties to all the
   // pieces of a given color.
 
-  template<Color Us, bool HasPopCnt, bool Trace>
+  template<Color Us, bool Trace>
   Score evaluate_pieces_of_color(const Position& pos, EvalInfo& ei, Score& mobility) {
 
     const Color Them = (Us == WHITE ? BLACK : WHITE);
@@ -654,10 +649,10 @@ namespace {
     // Do not include in mobility squares protected by enemy pawns or occupied by our pieces
     const Bitboard mobilityArea = ~(ei.attackedBy[Them][PAWN] | pos.pieces(Us));
 
-    score += evaluate_pieces<KNIGHT, Us, HasPopCnt, Trace>(pos, ei, mobility, mobilityArea);
-    score += evaluate_pieces<BISHOP, Us, HasPopCnt, Trace>(pos, ei, mobility, mobilityArea);
-    score += evaluate_pieces<ROOK,   Us, HasPopCnt, Trace>(pos, ei, mobility, mobilityArea);
-    score += evaluate_pieces<QUEEN,  Us, HasPopCnt, Trace>(pos, ei, mobility, mobilityArea);
+    score += evaluate_pieces<KNIGHT, Us, Trace>(pos, ei, mobility, mobilityArea);
+    score += evaluate_pieces<BISHOP, Us, Trace>(pos, ei, mobility, mobilityArea);
+    score += evaluate_pieces<ROOK,   Us, Trace>(pos, ei, mobility, mobilityArea);
+    score += evaluate_pieces<QUEEN,  Us, Trace>(pos, ei, mobility, mobilityArea);
 
     // Sum up all attacked squares
     ei.attackedBy[Us][0] =   ei.attackedBy[Us][PAWN]   | ei.attackedBy[Us][KNIGHT]
@@ -669,10 +664,10 @@ namespace {
 
   // evaluate_king<>() assigns bonuses and penalties to a king of a given color
 
-  template<Color Us, bool HasPopCnt, bool Trace>
+  template<Color Us, bool Trace>
   Score evaluate_king(const Position& pos, EvalInfo& ei, Value margins[]) {
 
-    const BitCountType Max15 = HasPopCnt ? CNT_POPCNT : CpuIs64Bit ? CNT64_MAX15 : CNT32_MAX15;
+    const BitCountType Max15 = HasPopCnt ? CNT_POPCNT : Is64Bit ? CNT64_MAX15 : CNT32_MAX15;
     const Color Them = (Us == WHITE ? BLACK : WHITE);
 
     Bitboard undefended, b, b1, b2, safe;
@@ -882,10 +877,9 @@ namespace {
   // evaluate_unstoppable_pawns() evaluates the unstoppable passed pawns for both sides, this is quite
   // conservative and returns a winning score only when we are very sure that the pawn is winning.
 
-  template<bool HasPopCnt>
   Score evaluate_unstoppable_pawns(const Position& pos, EvalInfo& ei) {
 
-    const BitCountType Max15 = HasPopCnt ? CNT_POPCNT : CpuIs64Bit ? CNT64_MAX15 : CNT32_MAX15;
+    const BitCountType Max15 = HasPopCnt ? CNT_POPCNT : Is64Bit ? CNT64_MAX15 : CNT32_MAX15;
 
     Bitboard b, b2, blockers, supporters, queeningPath, candidates;
     Square s, blockSq, queeningSquare;
@@ -1049,10 +1043,10 @@ namespace {
   // squares one, two or three squares behind a friendly pawn are counted
   // twice. Finally, the space bonus is scaled by a weight taken from the
   // material hash table. The aim is to improve play on game opening.
-  template<Color Us, bool HasPopCnt>
+  template<Color Us>
   int evaluate_space(const Position& pos, EvalInfo& ei) {
 
-    const BitCountType Max15 = HasPopCnt ? CNT_POPCNT : CpuIs64Bit ? CNT64_MAX15 : CNT32_MAX15;
+    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
@@ -1187,7 +1181,7 @@ std::string trace_evaluate(const Position& pos) {
     TraceStream << std::showpoint << std::showpos << std::fixed << std::setprecision(2);
     memset(TracedScores, 0, 2 * 16 * sizeof(Score));
 
-    do_evaluate<false, true>(pos, margin);
+    do_evaluate<true>(pos, margin);
 
     totals = TraceStream.str();
     TraceStream.str("");
index 1a8309700555bfd61ef916fad97619d48d50386f..9b1b5ecfe4f373ce3fc6849cb64a0b5c86e481e0 100644 (file)
 #include <string>
 
 #include "bitboard.h"
-#include "evaluate.h"
+#include "misc.h"
 #include "position.h"
-#include "thread.h"
 #include "search.h"
-#include "ucioption.h"
+#include "thread.h"
 
 using namespace std;
 
@@ -44,11 +43,7 @@ int main(int argc, char* argv[]) {
   if (argc < 2)
   {
       cout << engine_name() << " by " << engine_authors() << endl;
-
-      if (CpuHasPOPCNT)
-          cout << "Good! CPU has hardware POPCNT." << endl;
-
-      uci_loop(); // Enter the UCI loop and wait for user input
+      uci_loop();
   }
   else if (string(argv[1]) == "bench")
       benchmark(argc, argv);
index 5912514c23dbadaf63133281c130497fe3a63a72..9189e327fd1f49b2048e9a515e53ffc70c2bd6aa 100644 (file)
@@ -68,20 +68,21 @@ static const string AppTag  = "";
 const string engine_name() {
 
   const string months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec");
-  const string cpu64(CpuIs64Bit ? " 64bit" : "");
+  const string cpu64(Is64Bit ? " 64bit" : "");
+  const string popcnt(HasPopCnt ? " SSE4.2" : "");
 
   if (!EngineVersion.empty())
-      return AppName + " " + EngineVersion + cpu64;
+      return AppName + " " + EngineVersion + cpu64 + popcnt;
 
   stringstream s, date(__DATE__); // From compiler, format is "Sep 21 2008"
   string month, day, year;
 
   date >> month >> day >> year;
 
-  s << setfill('0') << AppName + " " + AppTag + " "
-    << year.substr(2, 2) << setw(2)
-    << (1 + months.find(month) / 4) << setw(2)
-    << day << cpu64;
+  s << AppName + " " + AppTag + " "
+    << setfill('0') << year.substr(2)
+    << setw(2) << (1 + months.find(month) / 4)
+    << setw(2) << day << cpu64 << popcnt;
 
   return s.str();
 }
index 2906b0453b3c8508ddeb3ce129a00152d9a5b1cd..c652b371172560d5996ffee229f82a1b47338494 100644 (file)
@@ -116,7 +116,7 @@ template<Color Us>
 Score PawnInfoTable::evaluate_pawns(const Position& pos, Bitboard ourPawns,
                                     Bitboard theirPawns, PawnInfo* pi) {
 
-  const BitCountType Max15 = CpuIs64Bit ? CNT64_MAX15 : CNT32_MAX15;
+  const BitCountType Max15 = Is64Bit ? CNT64_MAX15 : CNT32_MAX15;
   const Color Them = (Us == WHITE ? BLACK : WHITE);
 
   Bitboard b;
index b73eccbac09c89a015de01cfe2afcb873be51152..3934c2912d032ee51bff7920aef66e939c3e76b0 100644 (file)
@@ -124,30 +124,22 @@ inline void __cpuid(int CPUInfo[4], int)
 #define FORCE_INLINE  inline
 #endif
 
-/// cpu_has_popcnt() detects support for popcnt instruction at runtime
-inline bool cpu_has_popcnt() {
 
-  int CPUInfo[4] = {-1};
-  __cpuid(CPUInfo, 0x00000001);
-  return (CPUInfo[2] >> 23) & 1;
-}
-
-/// CpuHasPOPCNT is a global constant initialized at startup that
-/// is set to true if CPU on which application runs supports popcnt
-/// hardware instruction. Unless USE_POPCNT is not defined.
+/// HasPopCnt is a global constant initialized at compile time that is set to
+/// true if CPU on which application runs supports popcnt hardware instruction.
 #if defined(USE_POPCNT)
-const bool CpuHasPOPCNT = cpu_has_popcnt();
+const bool HasPopCnt = true;
 #else
-const bool CpuHasPOPCNT = false;
+const bool HasPopCnt = false;
 #endif
 
 
-/// CpuIs64Bit is a global constant initialized at compile time that
-/// is set to true if CPU on which application runs is a 64 bits.
+/// Is64Bit is a global constant initialized at compile time that is set to
+/// true if CPU on which application runs is a 64 bits.
 #if defined(IS_64BIT)
-const bool CpuIs64Bit = true;
+const bool Is64Bit = true;
 #else
-const bool CpuIs64Bit = false;
+const bool Is64Bit = false;
 #endif
 
 #include <string>