convertDoubleTo: add FP16 support

Currently unused. I've tested that GCC 13 and Clang 17 do compile this
and do output reasonable assembly, with and without AVX512FP16 (I also
tested AVX10.1 with GCC 14).

Clang is unable to allocate a "v" (vector) register when T is qfloat16,
so I could only implement the conversion using _Float16. Strictly
speaking, Clang >= 16 always knows about _Float16, but I didn't want to
have a different detection from qtypes.h.

Change-Id: I6818d78a57394e37857bfffd17bae860f8055324
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
bb10
Thiago Macieira 2024-03-08 13:48:31 -08:00
parent c86e1758dd
commit 7d4d6e88bc
1 changed files with 33 additions and 0 deletions

View File

@ -339,6 +339,39 @@ convertDoubleTo(double v, T *value, bool allow_precision_upgrade = true)
# endif
return sse_check_result(*value);
}
# if defined(__F16C__) || defined(__AVX512FP16__)
if constexpr (sizeof(T) == 2 && std::numeric_limits<T>::max_exponent == 16) {
// qfloat16 or std::float16_t, but not std::bfloat16_t or std::bfloat8_t
auto doConvert = [&](auto *out) {
asm ("vldmxcsr %[csr]\n\t"
# ifdef __AVX512FP16__
// AVX512FP16 & AVX10 have an instruction for this
"vcvtsd2sh %[in], %[in], %[out]\n\t"
# else
"vcvtsd2ss %[in], %[in], %[out]\n\t" // sets DEST[MAXVL-1:128] := 0
"vcvtps2ph %[rc], %[out], %[out]\n\t"
# endif
"vstmxcsr %[csr]"
: [csr] "+m" (csr), [out] "=v" (*out)
: [in] "v" (v), [rc] "i" (_MM_FROUND_CUR_DIRECTION)
);
return sse_check_result(out);
};
if constexpr (std::is_same_v<T, qfloat16> && !std::is_void_v<typename T::NativeType>) {
typename T::NativeType tmp;
bool b = doConvert(&tmp);
*value = tmp;
return b;
} else {
# ifndef Q_CC_CLANG
// Clang can only implement this if it has a native FP16 type
return doConvert(value);
# endif
}
}
# endif
#endif // __SSE2__ && inline assembly
if (!qt_is_finite(v) && std::numeric_limits<T>::has_infinity) {