Avoid using an if_constexpr macro

It doesn't actually use if constexpr, and compilers are smart enough to
optimize. Some functions can use templates instead.
This commit is contained in:
Chris Robinson 2022-02-22 03:03:44 -08:00
parent 72ddb6351e
commit d06ed618d3
5 changed files with 54 additions and 53 deletions

View File

@ -102,7 +102,7 @@ constexpr SLuint32 GetTypeRepresentation(DevFmtType type) noexcept
constexpr SLuint32 GetByteOrderEndianness() noexcept
{
if_constexpr(al::endian::native == al::endian::little)
if(al::endian::native == al::endian::little)
return SL_BYTEORDER_LITTLEENDIAN;
return SL_BYTEORDER_BIGENDIAN;
}

View File

@ -149,29 +149,23 @@ int WaveBackend::mixerProc()
mDevice->renderSamples(mBuffer.data(), mDevice->UpdateSize, frameStep);
done += mDevice->UpdateSize;
if_constexpr(al::endian::native != al::endian::little)
if(al::endian::native != al::endian::little)
{
const uint bytesize{mDevice->bytesFromFmt()};
if(bytesize == 2)
{
ushort *samples = reinterpret_cast<ushort*>(mBuffer.data());
const size_t len{mBuffer.size() / 2};
for(size_t i{0};i < len;i++)
{
const ushort samp{samples[i]};
samples[i] = static_cast<ushort>((samp>>8) | (samp<<8));
}
const size_t len{mBuffer.size() & ~size_t{1}};
for(size_t i{0};i < len;i+=2)
std::swap(mBuffer[i], mBuffer[i+1]);
}
else if(bytesize == 4)
{
uint *samples = reinterpret_cast<uint*>(mBuffer.data());
const size_t len{mBuffer.size() / 4};
for(size_t i{0};i < len;i++)
const size_t len{mBuffer.size() & ~size_t{3}};
for(size_t i{0};i < len;i+=4)
{
const uint samp{samples[i]};
samples[i] = (samp>>24) | ((samp>>8)&0x0000ff00) |
((samp<<8)&0x00ff0000) | (samp<<24);
std::swap(mBuffer[i ], mBuffer[i+3]);
std::swap(mBuffer[i+1], mBuffer[i+2]);
}
}
}

View File

@ -6,7 +6,6 @@
#include <type_traits>
#if !defined(__GNUC__) && (defined(_WIN32) || defined(_WIN64))
#include <intrin.h>
#include "opthelpers.h"
#endif
namespace al {
@ -111,34 +110,33 @@ int> popcount(T val) noexcept
return static_cast<int>(((v * b00000001) >> ((sizeof(T)-1)*8)) & 0xff);
}
#if defined(_WIN64)
#ifdef _WIN32
template<typename T>
inline std::enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value,
inline std::enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value
&& std::numeric_limits<T>::digits <= 32,
int> countr_zero(T v)
{
unsigned long idx{std::numeric_limits<T>::digits};
if_constexpr(std::numeric_limits<T>::digits <= 32)
_BitScanForward(&idx, static_cast<uint32_t>(v));
else // std::numeric_limits<T>::digits > 32
_BitScanForward64(&idx, v);
_BitScanForward(&idx, static_cast<uint32_t>(v));
return static_cast<int>(idx);
}
#elif defined(_WIN32)
template<typename T>
inline std::enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value,
inline std::enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value
&& 32 < std::numeric_limits<T>::digits && std::numeric_limits<T>::digits <= 64,
int> countr_zero(T v)
{
unsigned long idx{std::numeric_limits<T>::digits};
if_constexpr(std::numeric_limits<T>::digits <= 32)
_BitScanForward(&idx, static_cast<uint32_t>(v));
else if(!_BitScanForward(&idx, static_cast<uint32_t>(v)))
#ifdef _WIN64
_BitScanForward64(&idx, v);
#else
if(!_BitScanForward(&idx, static_cast<uint32_t>(v)))
{
if(_BitScanForward(&idx, static_cast<uint32_t>(v>>32)))
idx += 32;
}
#endif /* _WIN64 */
return static_cast<int>(idx);
}

View File

@ -46,10 +46,4 @@ constexpr bool unlikely(T&& expr) noexcept { return static_cast<bool>(expr); }
#define ASSUME(x) ((void)0)
#endif
#if __cplusplus >= 201703L || defined(__cpp_if_constexpr)
#define if_constexpr if constexpr
#else
#define if_constexpr if
#endif
#endif /* OPTHELPERS_H */

View File

@ -447,32 +447,47 @@ void MirrorLeftHrirs(const al::span<const HrtfStore::Elevation> elevs, HrirArray
}
template<size_t num_bits, typename T>
constexpr std::enable_if_t<std::is_signed<T>::value && num_bits < sizeof(T)*8,
T> fixsign(T value) noexcept
{
constexpr auto signbit = static_cast<T>(1u << (num_bits-1));
return static_cast<T>((value^signbit) - signbit);
}
template<size_t num_bits, typename T>
constexpr std::enable_if_t<!std::is_signed<T>::value || num_bits == sizeof(T)*8,
T> fixsign(T value) noexcept
{ return value; }
template<typename T, size_t num_bits=sizeof(T)*8>
inline T readle(std::istream &data)
inline std::enable_if_t<al::endian::native == al::endian::little,
T> readle(std::istream &data)
{
static_assert((num_bits&7) == 0, "num_bits must be a multiple of 8");
static_assert(num_bits <= sizeof(T)*8, "num_bits is too large for the type");
T ret{};
if_constexpr(al::endian::native == al::endian::little)
{
if(!data.read(reinterpret_cast<char*>(&ret), num_bits/8))
return static_cast<T>(EOF);
}
else
{
al::byte b[sizeof(T)]{};
if(!data.read(reinterpret_cast<char*>(b), num_bits/8))
return static_cast<T>(EOF);
std::reverse_copy(std::begin(b), std::end(b), reinterpret_cast<al::byte*>(&ret));
}
if(!data.read(reinterpret_cast<char*>(&ret), num_bits/8))
return static_cast<T>(EOF);
if_constexpr(std::is_signed<T>::value && num_bits < sizeof(T)*8)
{
constexpr auto signbit = static_cast<T>(1u << (num_bits-1));
return static_cast<T>((ret^signbit) - signbit);
}
return ret;
return fixsign<num_bits>(ret);
}
template<typename T, size_t num_bits=sizeof(T)*8>
inline std::enable_if_t<al::endian::native == al::endian::big,
T> readle(std::istream &data)
{
static_assert((num_bits&7) == 0, "num_bits must be a multiple of 8");
static_assert(num_bits <= sizeof(T)*8, "num_bits is too large for the type");
T ret{};
al::byte b[sizeof(T)]{};
if(!data.read(reinterpret_cast<char*>(b), num_bits/8))
return static_cast<T>(EOF);
std::reverse_copy(std::begin(b), std::end(b), reinterpret_cast<al::byte*>(&ret));
return fixsign<num_bits>(ret);
}
template<>