mirror of
https://github.com/transmission/transmission
synced 2025-01-30 10:52:00 +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
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__x86_64__) && defined(__SSE__)
|
||||
#if (defined(__x86_64__) || defined(__i386__)) && defined(__POPCNT__)
|
||||
#define TR_HAVE_ASM_POPCNT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_M_X64) || defined(_M_IX86)
|
||||
#include <nmmintrin.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(TR_HAVE_STD_POPCOUNT)
|
||||
#include <bit>
|
||||
#endif
|
||||
|
@ -65,7 +59,7 @@ struct tr_popcnt
|
|||
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
|
||||
strain the latter puts on the optimized. */
|
||||
static inline unsigned count(T v)
|
||||
|
@ -95,50 +89,6 @@ struct tr_popcnt
|
|||
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)
|
||||
/* raw assembly. This prohibits constexpr so may be worth dropping if there
|
||||
* is need for count() to be constexpr. */
|
||||
|
|
Loading…
Reference in a new issue