qfloat16: add AVX512VL qfloat16 conversion tail

Slightly simpler implementation for the tail because of the OpMask
support.

Change-Id: I60fdef243d0c4e04890dfffd16266facd53d78aa
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
bb10
Thiago Macieira 2020-07-29 22:11:46 -07:00
parent 8247c0dac3
commit ac7f73e507
1 changed files with 37 additions and 0 deletions

View File

@ -192,6 +192,19 @@ int qfloat16::fpClassify() const noexcept
*/
#if QT_COMPILER_SUPPORTS(F16C)
#define QT_FUNCTION_TARGET_STRING_AVX512VLBW \
QT_FUNCTION_TARGET_STRING_AVX512VL "," \
QT_FUNCTION_TARGET_STRING_AVX512BW "," \
QT_FUNCTION_TARGET_STRING_F16C "," \
QT_FUNCTION_TARGET_STRING_BMI2 /* BMI2 for BZHI */
static bool hasFastF16Avx256()
{
// 256-bit AVX512 don't have a performance penalty (see qstring.cpp for more info)
constexpr quint64 CpuFeatureAVX512VLBW = CpuFeatureAVX512BW | CpuFeatureAVX512VL;
return qCpuHasFeature(AVX512VLBW);
}
static inline bool hasFastF16()
{
// qsimd.cpp:detectProcessorFeatures() turns off this feature if AVX
@ -199,6 +212,24 @@ static inline bool hasFastF16()
return qCpuHasFeature(F16C);
}
static QT_FUNCTION_TARGET(AVX512VLBW)
void qFloatToFloat16_tail_avx256(quint16 *out, const float *in, qsizetype len) noexcept
{
__mmask16 mask = _bzhi_u32(-1, len);
__m256 f32 = _mm256_maskz_loadu_ps(mask, in );
__m128i f16 = _mm256_maskz_cvtps_ph(mask, f32, _MM_FROUND_TO_NEAREST_INT);
_mm_mask_storeu_epi16(out, mask, f16);
};
static QT_FUNCTION_TARGET(AVX512VLBW)
void qFloatFromFloat16_tail_avx256(float *out, const quint16 *in, qsizetype len) noexcept
{
__mmask16 mask = _bzhi_u32(-1, len);
__m128i f16 = _mm_maskz_loadu_epi16(mask, in);
__m256 f32 = _mm256_cvtph_ps(f16);
_mm256_mask_storeu_ps(out, mask, f32);
};
QT_FUNCTION_TARGET(F16C)
static void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) noexcept
{
@ -222,6 +253,9 @@ static void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) n
return convertOneChunk(len - Step);
}
if (hasFastF16Avx256())
return qFloatToFloat16_tail_avx256(out, in, len);
if (len >= HalfStep) {
auto convertOneChunk = [=](qsizetype offset) QT_FUNCTION_TARGET(F16C) {
__m128 f32 = _mm_loadu_ps(in + offset);
@ -262,6 +296,9 @@ static void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len)
return convertOneChunk(len - Step);
}
if (hasFastF16Avx256())
return qFloatFromFloat16_tail_avx256(out, in, len);
if (len >= HalfStep) {
auto convertOneChunk = [=](qsizetype offset) QT_FUNCTION_TARGET(F16C) {
__m128i f16 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(in + offset));