diff --git a/config.lib b/config.lib index a33e450b02..98cdced7c0 100644 --- a/config.lib +++ b/config.lib @@ -1812,6 +1812,22 @@ EOL fi fi + log 2 "executing $cc_host $CFLAGS $LDFLAGS $STATIC_FLAGS -o tmp.config.bitmath-builtins -x c++ -" + "$cc_host" $CFLAGS $LDFLAGS $STATIC_FLAGS -o tmp.config.bitmath-builtins -x c++ - 2> /dev/null << EOL + int main() { + return __builtin_popcountll(__builtin_popcountl(__builtin_popcount(__builtin_ctz(1)))); + } +EOL + ret=$? + rm -f tmp.config.bitmath-builtins + log 2 " exit code $ret" + if [ $ret -ne 0 ]; then + log 1 "checking bitmath builtins... no" + else + log 1 "checking bitmath builtins... found" + CFLAGS="$CFLAGS -DWITH_BITMATH_BUILTINS" + fi + if [ "$os" != "CYGWIN" ] && [ "$os" != "HAIKU" ] && [ "$os" != "MORPHOS" ] && [ "$os" != "OSX" ] && [ "$os" != "DOS" ] && [ "$os" != "WINCE" ] && [ "$os" != "PSP" ] && [ "$os" != "OS2" ]; then log 2 "executing $cc_host $CFLAGS $LDFLAGS $STATIC_FLAGS -o tmp.config.demangle -x c++ - -lstdc++" "$cc_host" $CFLAGS $LDFLAGS $STATIC_FLAGS -o tmp.config.demangle -x c++ - -lstdc++ 2> /dev/null << EOL diff --git a/src/core/bitmath_func.cpp b/src/core/bitmath_func.cpp index 7763227315..65188c9fd8 100644 --- a/src/core/bitmath_func.cpp +++ b/src/core/bitmath_func.cpp @@ -14,6 +14,8 @@ #include "../safeguards.h" +#ifndef WITH_BITMATH_BUILTINS + const uint8 _ffb_64[64] = { 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, @@ -53,6 +55,8 @@ uint8 FindFirstBit(uint32 x) return pos; } +#endif + /** * Search the last set bit in a 64 bit variable. * diff --git a/src/core/bitmath_func.hpp b/src/core/bitmath_func.hpp index 31e679b005..6e39121563 100644 --- a/src/core/bitmath_func.hpp +++ b/src/core/bitmath_func.hpp @@ -185,6 +185,18 @@ static inline T ToggleBit(T &x, const uint8 y) return x = (T)(x ^ ((T)1U << y)); } +#ifdef WITH_BITMATH_BUILTINS + +#define FIND_FIRST_BIT(x) FindFirstBit(x) + +inline uint8 FindFirstBit(uint32 x) +{ + if (x == 0) return 0; + + return __builtin_ctz(x); +} + +#else /** Lookup table to check which bit is set in a 6 bit variable */ extern const uint8 _ffb_64[64]; @@ -201,6 +213,12 @@ extern const uint8 _ffb_64[64]; */ #define FIND_FIRST_BIT(x) _ffb_64[(x)] +uint8 FindFirstBit(uint32 x); + +#endif + +uint8 FindLastBit(uint64 x); + /** * Finds the position of the first non-zero bit in an integer. * @@ -224,9 +242,6 @@ static inline uint8 FindFirstBit2x64(const int value) } } -uint8 FindFirstBit(uint32 x); -uint8 FindLastBit(uint64 x); - /** * Clear the first bit in an integer. * @@ -252,6 +267,15 @@ static inline T KillFirstBit(T value) template static inline uint CountBits(T value) { +#ifdef WITH_BITMATH_BUILTINS + if (sizeof(T) == sizeof(unsigned int)) { + return __builtin_popcount(value); + } else if (sizeof(T) == sizeof(unsigned long)) { + return __builtin_popcountl(value); + } else { + return __builtin_popcountll(value); + } +#else uint num; /* This loop is only called once for every bit set by clearing the lowest @@ -264,6 +288,7 @@ static inline uint CountBits(T value) } return num; +#endif } /**