Use inline functions for popcnt and ctz instead of macros

This commit is contained in:
Chris Robinson 2020-10-13 01:21:44 -07:00
parent 45ff10fb4d
commit 303ca3af72
10 changed files with 73 additions and 83 deletions

View File

@ -177,7 +177,7 @@ bool EnsureEffectSlots(ALCcontext *context, size_t needed)
size_t count{std::accumulate(context->mEffectSlotList.cbegin(), size_t count{std::accumulate(context->mEffectSlotList.cbegin(),
context->mEffectSlotList.cend(), size_t{0}, context->mEffectSlotList.cend(), size_t{0},
[](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(POPCNT64(sublist.FreeMask)); } { return cur + static_cast<ALuint>(PopCount(sublist.FreeMask)); }
)}; )};
while(needed > count) while(needed > count)
@ -207,7 +207,7 @@ ALeffectslot *AllocEffectSlot(ALCcontext *context)
{ return entry.FreeMask != 0; } { return entry.FreeMask != 0; }
); );
auto lidx = static_cast<ALuint>(std::distance(context->mEffectSlotList.begin(), sublist)); auto lidx = static_cast<ALuint>(std::distance(context->mEffectSlotList.begin(), sublist));
auto slidx = static_cast<ALuint>(CTZ64(sublist->FreeMask)); auto slidx = static_cast<ALuint>(CountTrailingZeros(sublist->FreeMask));
ALeffectslot *slot{::new (sublist->EffectSlots + slidx) ALeffectslot{}}; ALeffectslot *slot{::new (sublist->EffectSlots + slidx) ALeffectslot{}};
if(ALenum err{slot->init()}) if(ALenum err{slot->init()})
@ -942,7 +942,7 @@ EffectSlotSubList::~EffectSlotSubList()
uint64_t usemask{~FreeMask}; uint64_t usemask{~FreeMask};
while(usemask) while(usemask)
{ {
ALsizei idx{CTZ64(usemask)}; const ALsizei idx{CountTrailingZeros(usemask)};
al::destroy_at(EffectSlots+idx); al::destroy_at(EffectSlots+idx);
usemask &= ~(1_u64 << idx); usemask &= ~(1_u64 << idx);
} }

View File

@ -286,8 +286,7 @@ bool EnsureBuffers(ALCdevice *device, size_t needed)
{ {
size_t count{std::accumulate(device->BufferList.cbegin(), device->BufferList.cend(), size_t{0}, size_t count{std::accumulate(device->BufferList.cbegin(), device->BufferList.cend(), size_t{0},
[](size_t cur, const BufferSubList &sublist) noexcept -> size_t [](size_t cur, const BufferSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(POPCNT64(sublist.FreeMask)); } { return cur + static_cast<ALuint>(PopCount(sublist.FreeMask)); })};
)};
while(needed > count) while(needed > count)
{ {
@ -316,7 +315,7 @@ ALbuffer *AllocBuffer(ALCdevice *device)
); );
auto lidx = static_cast<ALuint>(std::distance(device->BufferList.begin(), sublist)); auto lidx = static_cast<ALuint>(std::distance(device->BufferList.begin(), sublist));
auto slidx = static_cast<ALuint>(CTZ64(sublist->FreeMask)); auto slidx = static_cast<ALuint>(CountTrailingZeros(sublist->FreeMask));
ALbuffer *buffer{::new (sublist->Buffers + slidx) ALbuffer{}}; ALbuffer *buffer{::new (sublist->Buffers + slidx) ALbuffer{}};
@ -1582,7 +1581,7 @@ BufferSubList::~BufferSubList()
uint64_t usemask{~FreeMask}; uint64_t usemask{~FreeMask};
while(usemask) while(usemask)
{ {
ALsizei idx{CTZ64(usemask)}; const ALsizei idx{CountTrailingZeros(usemask)};
al::destroy_at(Buffers+idx); al::destroy_at(Buffers+idx);
usemask &= ~(1_u64 << idx); usemask &= ~(1_u64 << idx);
} }

View File

@ -145,8 +145,7 @@ bool EnsureEffects(ALCdevice *device, size_t needed)
{ {
size_t count{std::accumulate(device->EffectList.cbegin(), device->EffectList.cend(), size_t{0}, size_t count{std::accumulate(device->EffectList.cbegin(), device->EffectList.cend(), size_t{0},
[](size_t cur, const EffectSubList &sublist) noexcept -> size_t [](size_t cur, const EffectSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(POPCNT64(sublist.FreeMask)); } { return cur + static_cast<ALuint>(PopCount(sublist.FreeMask)); })};
)};
while(needed > count) while(needed > count)
{ {
@ -174,7 +173,7 @@ ALeffect *AllocEffect(ALCdevice *device)
{ return entry.FreeMask != 0; } { return entry.FreeMask != 0; }
); );
auto lidx = static_cast<ALuint>(std::distance(device->EffectList.begin(), sublist)); auto lidx = static_cast<ALuint>(std::distance(device->EffectList.begin(), sublist));
auto slidx = static_cast<ALuint>(CTZ64(sublist->FreeMask)); auto slidx = static_cast<ALuint>(CountTrailingZeros(sublist->FreeMask));
ALeffect *effect{::new (sublist->Effects + slidx) ALeffect{}}; ALeffect *effect{::new (sublist->Effects + slidx) ALeffect{}};
InitEffectParams(effect, AL_EFFECT_NULL); InitEffectParams(effect, AL_EFFECT_NULL);
@ -534,7 +533,7 @@ EffectSubList::~EffectSubList()
uint64_t usemask{~FreeMask}; uint64_t usemask{~FreeMask};
while(usemask) while(usemask)
{ {
ALsizei idx = CTZ64(usemask); const ALsizei idx{CountTrailingZeros(usemask)};
al::destroy_at(Effects+idx); al::destroy_at(Effects+idx);
usemask &= ~(1_u64 << idx); usemask &= ~(1_u64 << idx);
} }

View File

@ -321,8 +321,7 @@ bool EnsureFilters(ALCdevice *device, size_t needed)
{ {
size_t count{std::accumulate(device->FilterList.cbegin(), device->FilterList.cend(), size_t{0}, size_t count{std::accumulate(device->FilterList.cbegin(), device->FilterList.cend(), size_t{0},
[](size_t cur, const FilterSubList &sublist) noexcept -> size_t [](size_t cur, const FilterSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(POPCNT64(sublist.FreeMask)); } { return cur + static_cast<ALuint>(PopCount(sublist.FreeMask)); })};
)};
while(needed > count) while(needed > count)
{ {
@ -351,7 +350,7 @@ ALfilter *AllocFilter(ALCdevice *device)
{ return entry.FreeMask != 0; } { return entry.FreeMask != 0; }
); );
auto lidx = static_cast<ALuint>(std::distance(device->FilterList.begin(), sublist)); auto lidx = static_cast<ALuint>(std::distance(device->FilterList.begin(), sublist));
auto slidx = static_cast<ALuint>(CTZ64(sublist->FreeMask)); auto slidx = static_cast<ALuint>(CountTrailingZeros(sublist->FreeMask));
ALfilter *filter{::new(sublist->Filters + slidx) ALfilter{}}; ALfilter *filter{::new(sublist->Filters + slidx) ALfilter{}};
InitFilterParams(filter, AL_FILTER_NULL); InitFilterParams(filter, AL_FILTER_NULL);
@ -702,7 +701,7 @@ FilterSubList::~FilterSubList()
uint64_t usemask{~FreeMask}; uint64_t usemask{~FreeMask};
while(usemask) while(usemask)
{ {
ALsizei idx = CTZ64(usemask); const ALsizei idx{CountTrailingZeros(usemask)};
al::destroy_at(Filters+idx); al::destroy_at(Filters+idx);
usemask &= ~(1_u64 << idx); usemask &= ~(1_u64 << idx);
} }

View File

@ -683,8 +683,7 @@ bool EnsureSources(ALCcontext *context, size_t needed)
size_t count{std::accumulate(context->mSourceList.cbegin(), context->mSourceList.cend(), size_t count{std::accumulate(context->mSourceList.cbegin(), context->mSourceList.cend(),
size_t{0}, size_t{0},
[](size_t cur, const SourceSubList &sublist) noexcept -> size_t [](size_t cur, const SourceSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(POPCNT64(sublist.FreeMask)); } { return cur + static_cast<ALuint>(PopCount(sublist.FreeMask)); })};
)};
while(needed > count) while(needed > count)
{ {
@ -712,7 +711,7 @@ ALsource *AllocSource(ALCcontext *context)
{ return entry.FreeMask != 0; } { return entry.FreeMask != 0; }
); );
auto lidx = static_cast<ALuint>(std::distance(context->mSourceList.begin(), sublist)); auto lidx = static_cast<ALuint>(std::distance(context->mSourceList.begin(), sublist));
auto slidx = static_cast<ALuint>(CTZ64(sublist->FreeMask)); auto slidx = static_cast<ALuint>(CountTrailingZeros(sublist->FreeMask));
ALsource *source{::new(sublist->Sources + slidx) ALsource{}}; ALsource *source{::new(sublist->Sources + slidx) ALsource{}};
@ -3410,7 +3409,7 @@ SourceSubList::~SourceSubList()
uint64_t usemask{~FreeMask}; uint64_t usemask{~FreeMask};
while(usemask) while(usemask)
{ {
ALsizei idx{CTZ64(usemask)}; const ALsizei idx{CountTrailingZeros(usemask)};
al::destroy_at(Sources+idx); al::destroy_at(Sources+idx);
usemask &= ~(1_u64 << idx); usemask &= ~(1_u64 << idx);
} }

View File

@ -2117,7 +2117,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
uint64_t usemask{~sublist.FreeMask}; uint64_t usemask{~sublist.FreeMask};
while(usemask) while(usemask)
{ {
ALsizei idx{CTZ64(usemask)}; const ALsizei idx{CountTrailingZeros(usemask)};
ALeffectslot *slot{sublist.EffectSlots + idx}; ALeffectslot *slot{sublist.EffectSlots + idx};
usemask &= ~(1_u64 << idx); usemask &= ~(1_u64 << idx);
@ -2140,7 +2140,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
uint64_t usemask{~sublist.FreeMask}; uint64_t usemask{~sublist.FreeMask};
while(usemask) while(usemask)
{ {
ALsizei idx{CTZ64(usemask)}; const ALsizei idx{CountTrailingZeros(usemask)};
ALsource *source{sublist.Sources + idx}; ALsource *source{sublist.Sources + idx};
usemask &= ~(1_u64 << idx); usemask &= ~(1_u64 << idx);
@ -2282,22 +2282,19 @@ ALCdevice::~ALCdevice()
size_t count{std::accumulate(BufferList.cbegin(), BufferList.cend(), size_t{0u}, size_t count{std::accumulate(BufferList.cbegin(), BufferList.cend(), size_t{0u},
[](size_t cur, const BufferSubList &sublist) noexcept -> size_t [](size_t cur, const BufferSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); } { return cur + static_cast<ALuint>(PopCount(~sublist.FreeMask)); })};
)};
if(count > 0) if(count > 0)
WARN("%zu Buffer%s not deleted\n", count, (count==1)?"":"s"); WARN("%zu Buffer%s not deleted\n", count, (count==1)?"":"s");
count = std::accumulate(EffectList.cbegin(), EffectList.cend(), size_t{0u}, count = std::accumulate(EffectList.cbegin(), EffectList.cend(), size_t{0u},
[](size_t cur, const EffectSubList &sublist) noexcept -> size_t [](size_t cur, const EffectSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); } { return cur + static_cast<ALuint>(PopCount(~sublist.FreeMask)); });
);
if(count > 0) if(count > 0)
WARN("%zu Effect%s not deleted\n", count, (count==1)?"":"s"); WARN("%zu Effect%s not deleted\n", count, (count==1)?"":"s");
count = std::accumulate(FilterList.cbegin(), FilterList.cend(), size_t{0u}, count = std::accumulate(FilterList.cbegin(), FilterList.cend(), size_t{0u},
[](size_t cur, const FilterSubList &sublist) noexcept -> size_t [](size_t cur, const FilterSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); } { return cur + static_cast<ALuint>(PopCount(~sublist.FreeMask)); });
);
if(count > 0) if(count > 0)
WARN("%zu Filter%s not deleted\n", count, (count==1)?"":"s"); WARN("%zu Filter%s not deleted\n", count, (count==1)?"":"s");
@ -2350,8 +2347,7 @@ ALCcontext::~ALCcontext()
count = std::accumulate(mSourceList.cbegin(), mSourceList.cend(), size_t{0u}, count = std::accumulate(mSourceList.cbegin(), mSourceList.cend(), size_t{0u},
[](size_t cur, const SourceSubList &sublist) noexcept -> size_t [](size_t cur, const SourceSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); } { return cur + static_cast<ALuint>(PopCount(~sublist.FreeMask)); });
);
if(count > 0) if(count > 0)
WARN("%zu Source%s not deleted\n", count, (count==1)?"":"s"); WARN("%zu Source%s not deleted\n", count, (count==1)?"":"s");
mSourceList.clear(); mSourceList.clear();
@ -2377,8 +2373,7 @@ ALCcontext::~ALCcontext()
count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), size_t{0u}, count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), size_t{0u},
[](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); } { return cur + static_cast<ALuint>(PopCount(~sublist.FreeMask)); });
);
if(count > 0) if(count > 0)
WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count, (count==1)?"":"s"); WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count, (count==1)?"":"s");
mEffectSlotList.clear(); mEffectSlotList.clear();

View File

@ -183,7 +183,7 @@ void BackendBase::setChannelOrderFromWFXMask(ALuint chanmask)
ALuint idx{0}; ALuint idx{0};
while(chanmask) while(chanmask)
{ {
const int bit{CTZ32(chanmask)}; const int bit{CountTrailingZeros(chanmask)};
const ALuint mask{1u << bit}; const ALuint mask{1u << bit};
chanmask &= ~mask; chanmask &= ~mask;

View File

@ -1641,7 +1641,7 @@ HRESULT WasapiCapture::resetProxy()
if((InputType.dwChannelMask&SPEAKER_LOW_FREQUENCY)) if((InputType.dwChannelMask&SPEAKER_LOW_FREQUENCY))
{ {
constexpr auto lfemask = MaskFromTopBits(SPEAKER_LOW_FREQUENCY); constexpr auto lfemask = MaskFromTopBits(SPEAKER_LOW_FREQUENCY);
const int lfeidx{POPCNT32(InputType.dwChannelMask&lfemask) - 1}; const int lfeidx{PopCount(uint32_t{InputType.dwChannelMask&lfemask}) - 1};
chanmask &= ~(1u << lfeidx); chanmask &= ~(1u << lfeidx);
} }

View File

@ -340,7 +340,7 @@ void ChannelConverter::convert(const void *src, float *dst, ALuint frames) const
{ {
if(mDstChans == DevFmtMono) if(mDstChans == DevFmtMono)
{ {
const float scale{std::sqrt(1.0f / static_cast<float>(POPCNT32(mChanMask)))}; const float scale{std::sqrt(1.0f / static_cast<float>(PopCount(mChanMask)))};
switch(mSrcType) switch(mSrcType)
{ {
#define HANDLE_FMT(T) case T: Multi2Mono<T>(mChanMask, mSrcStep, scale, dst, src, frames); break #define HANDLE_FMT(T) case T: Multi2Mono<T>(mChanMask, mSrcStep, scale, dst, src, frames); break

View File

@ -90,34 +90,33 @@ inline size_t RoundUp(size_t value, size_t r) noexcept
} }
/* Define CTZ macros (count trailing zeros), and POPCNT macros (population /* Define CountTrailingZeros (count trailing zero bits, starting from the lsb)
* count/count 1 bits), for 32- and 64-bit integers. The CTZ macros' results * and PopCount (population count/count 1 bits) methods, for 32- and 64-bit
* are *UNDEFINED* if the value is 0. * integers. The CountTrailingZeros results are *UNDEFINED* if the value is 0.
*/ */
template<typename T>
inline int PopCount(T val) = delete;
template<typename T>
inline int CountTrailingZeros(T val) = delete;
#ifdef __GNUC__ #ifdef __GNUC__
namespace detail_ { /* Define variations for unsigned (long (long)) int, since we don't know what
* uint32/64_t are typedef'd to.
template<typename T> */
constexpr inline auto popcnt64(T val) = delete;
template<> template<>
constexpr inline auto popcnt64(unsigned long long val) { return __builtin_popcountll(val); } inline int PopCount(unsigned long long val) { return __builtin_popcountll(val); }
template<> template<>
constexpr inline auto popcnt64(unsigned long val) { return __builtin_popcountl(val); } inline int PopCount(unsigned long val) { return __builtin_popcountl(val); }
template<typename T>
constexpr inline auto ctz64(T val) = delete;
template<> template<>
constexpr inline auto ctz64(unsigned long long val) { return __builtin_ctzll(val); } inline int PopCount(unsigned int val) { return __builtin_popcount(val); }
template<> template<>
constexpr inline auto ctz64(unsigned long val) { return __builtin_ctzl(val); } inline int CountTrailingZeros(unsigned long long val) { return __builtin_ctzll(val); }
template<>
} // namespace detail_ inline int CountTrailingZeros(unsigned long val) { return __builtin_ctzl(val); }
template<>
#define POPCNT32 __builtin_popcount inline int CountTrailingZeros(unsigned int val) { return __builtin_ctz(val); }
#define CTZ32 __builtin_ctz
#define POPCNT64 detail_::popcnt64<uint64_t>
#define CTZ64 detail_::ctz64<uint64_t>
#else #else
@ -128,69 +127,69 @@ constexpr inline auto ctz64(unsigned long val) { return __builtin_ctzl(val); }
* as the ntz2 variant. These likely aren't the most efficient methods, but * as the ntz2 variant. These likely aren't the most efficient methods, but
* they're good enough if the GCC built-ins aren't available. * they're good enough if the GCC built-ins aren't available.
*/ */
inline int fallback_popcnt32(uint32_t v) template<>
inline int PopCount(uint32_t v)
{ {
v = v - ((v >> 1) & 0x55555555u); v = v - ((v >> 1) & 0x55555555u);
v = (v & 0x33333333u) + ((v >> 2) & 0x33333333u); v = (v & 0x33333333u) + ((v >> 2) & 0x33333333u);
v = (v + (v >> 4)) & 0x0f0f0f0fu; v = (v + (v >> 4)) & 0x0f0f0f0fu;
return (int)((v * 0x01010101u) >> 24); return static_cast<int>((v * 0x01010101u) >> 24);
} }
#define POPCNT32 fallback_popcnt32 template<>
inline int fallback_popcnt64(uint64_t v) inline int PopCount(uint64_t v)
{ {
v = v - ((v >> 1) & 0x5555555555555555_u64); v = v - ((v >> 1) & 0x5555555555555555_u64);
v = (v & 0x3333333333333333_u64) + ((v >> 2) & 0x3333333333333333_u64); v = (v & 0x3333333333333333_u64) + ((v >> 2) & 0x3333333333333333_u64);
v = (v + (v >> 4)) & 0x0f0f0f0f0f0f0f0f_u64; v = (v + (v >> 4)) & 0x0f0f0f0f0f0f0f0f_u64;
return (int)((v * 0x0101010101010101_u64) >> 56); return static_cast<int>((v * 0x0101010101010101_u64) >> 56);
} }
#define POPCNT64 fallback_popcnt64
#if defined(_WIN64) #if defined(_WIN64)
inline int msvc64_ctz32(uint32_t v) template<>
inline int CountTrailingZeros(uint32_t v)
{ {
unsigned long idx = 32; unsigned long idx = 32;
_BitScanForward(&idx, v); _BitScanForward(&idx, v);
return (int)idx; return static_cast<int>(idx);
} }
#define CTZ32 msvc64_ctz32 template<>
inline int msvc64_ctz64(uint64_t v) inline int CountTrailingZeros(uint64_t v)
{ {
unsigned long idx = 64; unsigned long idx = 64;
_BitScanForward64(&idx, v); _BitScanForward64(&idx, v);
return (int)idx; return static_cast<int>(idx);
} }
#define CTZ64 msvc64_ctz64
#elif defined(_WIN32) #elif defined(_WIN32)
inline int msvc_ctz32(uint32_t v) template<>
inline int CountTrailingZeros(uint32_t v)
{ {
unsigned long idx = 32; unsigned long idx = 32;
_BitScanForward(&idx, v); _BitScanForward(&idx, v);
return (int)idx; return static_cast<int>(idx);
} }
#define CTZ32 msvc_ctz32 template<>
inline int msvc_ctz64(uint64_t v) inline int CountTrailingZeros(uint64_t v)
{ {
unsigned long idx = 64; unsigned long idx = 64;
if(!_BitScanForward(&idx, (uint32_t)(v&0xffffffff))) if(!_BitScanForward(&idx, static_cast<uint32_t>(v&0xffffffff)))
{ {
if(_BitScanForward(&idx, (uint32_t)(v>>32))) if(_BitScanForward(&idx, static_cast<uint32_t>(v>>32)))
idx += 32; idx += 32;
} }
return (int)idx; return static_cast<int>(idx);
} }
#define CTZ64 msvc_ctz64
#else #else
inline int fallback_ctz32(uint32_t value) template<>
{ return POPCNT32(~value & (value - 1)); } inline int CountTrailingZeros(uint32_t value)
#define CTZ32 fallback_ctz32 { return PopCount(~value & (value - 1)); }
inline int fallback_ctz64(uint64_t value) template<>
{ return POPCNT64(~value & (value - 1)); } inline int CountTrailingZeros(uint64_t value)
#define CTZ64 fallback_ctz64 { return PopCount(~value & (value - 1)); }
#endif #endif
#endif #endif
@ -240,7 +239,7 @@ inline int float2int(float f) noexcept
#elif (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 0) \ #elif (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 0) \
|| ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) \ || ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) \
&& !defined(__SSE_MATH__)) && !defined(__SSE_MATH__))
int sign, shift, mant; int sign, shift, mant;
union { union {
float f; float f;
@ -276,7 +275,7 @@ inline int double2int(double d) noexcept
#elif (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP < 2) \ #elif (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP < 2) \
|| ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) \ || ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) \
&& !defined(__SSE2_MATH__)) && !defined(__SSE2_MATH__))
int sign, shift; int sign, shift;
int64_t mant; int64_t mant;
union { union {