mirror of
https://github.com/transmission/transmission
synced 2025-01-30 19:03:04 +00:00
The `popcnt` feature checks weren't actually checking the ISA feature or cpuid. This caused an illegal instruction exception on x86 hardware that doesn't support `popcnt` when compiled with MSVC. Since MSVC doesn't support any x86 ISA defines, the only way to check for `popcnt` is with cpuid. Since this is a tiny inline function, dynamic dispatch is likley not worth it so just removing the MSVC for `popcnt`. MSVC will now fallback to the generic implementation.
This commit is contained in:
parent
605c6bd031
commit
1e5546280e
1 changed files with 2 additions and 52 deletions
|
@ -27,17 +27,11 @@
|
||||||
#define TR_HAVE_BUILTIN_POPCOUNT
|
#define TR_HAVE_BUILTIN_POPCOUNT
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if defined(__x86_64__) && defined(__SSE__)
|
#if (defined(__x86_64__) || defined(__i386__)) && defined(__POPCNT__)
|
||||||
#define TR_HAVE_ASM_POPCNT
|
#define TR_HAVE_ASM_POPCNT
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#if defined(_M_X64) || defined(_M_IX86)
|
|
||||||
#include <nmmintrin.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(TR_HAVE_STD_POPCOUNT)
|
#if defined(TR_HAVE_STD_POPCOUNT)
|
||||||
#include <bit>
|
#include <bit>
|
||||||
#endif
|
#endif
|
||||||
|
@ -65,7 +59,7 @@ struct tr_popcnt
|
||||||
return static_cast<unsigned>(std::popcount(unsigned_v));
|
return static_cast<unsigned>(std::popcount(unsigned_v));
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(TR_HAVE_BUILTIN_POPCOUNT) && defined(TR_HAVE_ASM_POPCNT)
|
#elif defined(TR_HAVE_BUILTIN_POPCOUNT)
|
||||||
/* Use __builtin as opposed to straight assembly to avoid any
|
/* Use __builtin as opposed to straight assembly to avoid any
|
||||||
strain the latter puts on the optimized. */
|
strain the latter puts on the optimized. */
|
||||||
static inline unsigned count(T v)
|
static inline unsigned count(T v)
|
||||||
|
@ -95,50 +89,6 @@ struct tr_popcnt
|
||||||
return __builtin_popcount(unsigned_v);
|
return __builtin_popcount(unsigned_v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(_MSC_VER) && defined(_M_X64)
|
|
||||||
/* 64-bit x86 intrinsics. */
|
|
||||||
static inline unsigned count(T v)
|
|
||||||
{
|
|
||||||
if constexpr (sizeof(T) == sizeof(uint64_t))
|
|
||||||
{
|
|
||||||
return _mm_popcnt_u64(v);
|
|
||||||
}
|
|
||||||
else if constexpr (sizeof(T) == sizeof(uint32_t))
|
|
||||||
{
|
|
||||||
return _mm_popcnt_u32(v);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static_assert(sizeof(T) < sizeof(uint32_t));
|
|
||||||
/* Need to avoid sign extension. */
|
|
||||||
unsigned_T unsigned_v = static_cast<unsigned_T>(v);
|
|
||||||
return _mm_popcnt_u32(unsigned_v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#elif defined(_MSC_VER) && defined(_M_IX86)
|
|
||||||
/* 32-bit x86 intrinsics. */
|
|
||||||
static inline unsigned count(T v)
|
|
||||||
{
|
|
||||||
if constexpr (sizeof(T) == sizeof(uint64_t))
|
|
||||||
{
|
|
||||||
/* Avoid signed shift. */
|
|
||||||
unsigned_T unsigned_v = static_cast<unsigned_T>(v);
|
|
||||||
|
|
||||||
return _mm_popcnt_u32(static_cast<uint32_t>(unsigned_v)) + _mm_popcnt_u32(static_cast<uint32_t>(unsigned_v >> 32));
|
|
||||||
}
|
|
||||||
else if constexpr (sizeof(T) == sizeof(uint32_t))
|
|
||||||
{
|
|
||||||
return _mm_popcnt_u32(v);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static_assert(sizeof(T) < sizeof(uint32_t));
|
|
||||||
/* Need to avoid sign extension. */
|
|
||||||
unsigned_T unsigned_v = static_cast<unsigned_T>(v);
|
|
||||||
return _mm_popcnt_u32(unsigned_v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#elif defined(TR_HAVE_ASM_POPCNT)
|
#elif defined(TR_HAVE_ASM_POPCNT)
|
||||||
/* raw assembly. This prohibits constexpr so may be worth dropping if there
|
/* raw assembly. This prohibits constexpr so may be worth dropping if there
|
||||||
* is need for count() to be constexpr. */
|
* is need for count() to be constexpr. */
|
||||||
|
|
Loading…
Reference in a new issue