From 0a6532a39d2e2cfd92ba0a2c4fa8c6ad6c29b581 Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Fri, 30 Dec 2011 11:30:26 +0100 Subject: [PATCH] Retire run-time detection of hardware POPCNT 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 --- src/bitboard.cpp | 6 ++-- src/evaluate.cpp | 74 ++++++++++++++++++++++-------------------------- src/main.cpp | 11 ++----- src/misc.cpp | 13 +++++---- src/pawns.cpp | 2 +- src/types.h | 24 ++++++---------- 6 files changed, 56 insertions(+), 74 deletions(-) diff --git a/src/bitboard.cpp b/src/bitboard.cpp index d9a9daba..8c7bb9eb 100644 --- a/src/bitboard.cpp +++ b/src/bitboard.cpp @@ -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(masks[s]); + shifts[s] = (Is64Bit ? 64 : 32) - count_1s(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. diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 5e278242..b469050a 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -225,28 +225,27 @@ namespace { }; // Function prototypes - template + template Value do_evaluate(const Position& pos, Value& margin); - template + template void init_eval_info(const Position& pos, EvalInfo& ei); - template + template Score evaluate_pieces_of_color(const Position& pos, EvalInfo& ei, Score& mobility); - template + template Score evaluate_king(const Position& pos, EvalInfo& ei, Value margins[]); template Score evaluate_threats(const Position& pos, EvalInfo& ei); - template + template int evaluate_space(const Position& pos, EvalInfo& ei); template Score evaluate_passed_pawns(const Position& pos, EvalInfo& ei); - template 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(pos, margin) - : do_evaluate(pos, margin); -} +Value evaluate(const Position& pos, Value& margin) { return do_evaluate(pos, margin); } namespace { -template +template 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(pos, ei); - init_eval_info(pos, ei); + init_eval_info(pos, ei); + init_eval_info(pos, ei); // Evaluate pieces and mobility - score += evaluate_pieces_of_color(pos, ei, mobilityWhite) - - evaluate_pieces_of_color(pos, ei, mobilityBlack); + score += evaluate_pieces_of_color(pos, ei, mobilityWhite) + - evaluate_pieces_of_color(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(pos, ei, margins) - - evaluate_king(pos, ei, margins); + score += evaluate_king(pos, ei, margins) + - evaluate_king(pos, ei, margins); // Evaluate tactical threats, we need full attack information including king score += evaluate_threats(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(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(pos, ei) - evaluate_space(pos, ei); + int s = evaluate_space(pos, ei) - evaluate_space(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(pos, ei), evaluate_threats(pos, ei)); trace_add(PASSED, evaluate_passed_pawns(pos, ei), evaluate_passed_pawns(pos, ei)); - trace_add(UNSTOPPABLE, evaluate_unstoppable_pawns(pos, ei)); - Score w = make_score(ei.mi->space_weight() * evaluate_space(pos, ei), 0); - Score b = make_score(ei.mi->space_weight() * evaluate_space(pos, ei), 0); + trace_add(UNSTOPPABLE, evaluate_unstoppable_pawns(pos, ei)); + Score w = make_score(ei.mi->space_weight() * evaluate_space(pos, ei), 0); + Score b = make_score(ei.mi->space_weight() * evaluate_space(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 + template 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(pos.king_square(Them)); @@ -474,7 +469,7 @@ namespace { // evaluate_pieces<>() assigns bonuses and penalties to the pieces of a given color - template + template 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 + template 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(pos, ei, mobility, mobilityArea); - score += evaluate_pieces(pos, ei, mobility, mobilityArea); - score += evaluate_pieces(pos, ei, mobility, mobilityArea); - score += evaluate_pieces(pos, ei, mobility, mobilityArea); + score += evaluate_pieces(pos, ei, mobility, mobilityArea); + score += evaluate_pieces(pos, ei, mobility, mobilityArea); + score += evaluate_pieces(pos, ei, mobility, mobilityArea); + score += evaluate_pieces(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 + template 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 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 + template 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(pos, margin); + do_evaluate(pos, margin); totals = TraceStream.str(); TraceStream.str(""); diff --git a/src/main.cpp b/src/main.cpp index 1a830970..9b1b5ecf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,11 +21,10 @@ #include #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); diff --git a/src/misc.cpp b/src/misc.cpp index 5912514c..9189e327 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -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(); } diff --git a/src/pawns.cpp b/src/pawns.cpp index 2906b045..c652b371 100644 --- a/src/pawns.cpp +++ b/src/pawns.cpp @@ -116,7 +116,7 @@ template 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; diff --git a/src/types.h b/src/types.h index b73eccba..3934c291 100644 --- a/src/types.h +++ b/src/types.h @@ -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 -- 2.39.2