From 7f16c4544b884f94f72c34522ddc95de0121a43b Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Thu, 5 Mar 2026 21:35:18 -0500 Subject: [PATCH] Make HALIDE_CPP_COMPILER_HAS_FLOAT16 overrideable and numeric Define HALIDE_CPP_COMPILER_HAS_FLOAT16 as 0 or 1 so callers can override detection and use it in #if guards consistently. Exclude __wasm__ from the Clang _Float16 detection path to avoid enabling _Float16 on wasm targets that advertise fp16 features but do not support the source-language type. Fixes #8986 --- src/Expr.h | 2 +- src/Float16.h | 4 ++-- src/Type.h | 2 +- src/runtime/HalideRuntime.h | 14 ++++++++++---- test/correctness/float16_t.cpp | 4 ++-- test/correctness/image_io.cpp | 2 +- tools/halide_image_io.h | 28 ++++++++++++++-------------- 7 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/Expr.h b/src/Expr.h index b9832c104de8..419a42e51f16 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -298,7 +298,7 @@ struct Expr : public Internal::IRHandle { Expr(bfloat16_t x) : IRHandle(Internal::FloatImm::make(BFloat(16), (double)x)) { } -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 explicit Expr(_Float16 x) : IRHandle(Internal::FloatImm::make(Float(16), (double)x)) { } diff --git a/src/Float16.h b/src/Float16.h index 936c7abf666a..e84741d7867d 100644 --- a/src/Float16.h +++ b/src/Float16.h @@ -40,7 +40,7 @@ struct float16_t { * positive zero.*/ float16_t() = default; -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 /** Construct a float16_t from compiler's built-in _Float16 type. */ explicit float16_t(_Float16 value) { memcpy(&data, &value, sizeof(_Float16)); @@ -57,7 +57,7 @@ struct float16_t { /** Cast to int */ explicit operator int() const; -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 /** Cast to compiler's built-in _Float16 type. */ explicit operator _Float16() const { _Float16 result; diff --git a/src/Type.h b/src/Type.h index 99545245a619..8a023429e5e6 100644 --- a/src/Type.h +++ b/src/Type.h @@ -166,7 +166,7 @@ HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(Halide::float16_t); HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(Halide::bfloat16_t); HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(halide_task_t); HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(halide_loop_task_t); -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(_Float16); #endif HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(float); diff --git a/src/runtime/HalideRuntime.h b/src/runtime/HalideRuntime.h index 898b9aa243df..46c5a89cfbb4 100644 --- a/src/runtime/HalideRuntime.h +++ b/src/runtime/HalideRuntime.h @@ -98,6 +98,9 @@ extern "C" { #define HALIDE_RUNTIME_ASAN_DETECTED #endif +#if !defined(HALIDE_CPP_COMPILER_HAS_FLOAT16) +#define HALIDE_CPP_COMPILER_HAS_FLOAT16 0 + #if !defined(HALIDE_RUNTIME_ASAN_DETECTED) // clang had _Float16 added as a reserved name in clang 8, but @@ -105,10 +108,11 @@ extern "C" { // Ideally there would be a better way to detect if the type // is supported, even in a compiler independent fashion, but // coming up with one has proven elusive. -#if defined(__clang__) && (__clang_major__ >= 15) && !defined(__EMSCRIPTEN__) && !defined(__i386__) +#if defined(__clang__) && (__clang_major__ >= 15) && !defined(__EMSCRIPTEN__) && !defined(__i386__) && !defined(__wasm__) #if defined(__is_identifier) #if !__is_identifier(_Float16) -#define HALIDE_CPP_COMPILER_HAS_FLOAT16 +#undef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#define HALIDE_CPP_COMPILER_HAS_FLOAT16 1 #endif #endif #endif @@ -121,11 +125,13 @@ extern "C" { (defined(__i386__) && (__GNUC__ >= 14) && defined(__SSE2__)) || \ (defined(__arm__) && (__GNUC__ >= 13) && __ARM_FP16_FORMAT_IEEE) || \ (defined(__aarch64__) && (__GNUC__ >= 13)) -#define HALIDE_CPP_COMPILER_HAS_FLOAT16 +#undef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#define HALIDE_CPP_COMPILER_HAS_FLOAT16 1 #endif #endif #endif // !HALIDE_RUNTIME_ASAN_DETECTED +#endif // !defined(HALIDE_CPP_COMPILER_HAS_FLOAT16) #endif // !COMPILING_HALIDE_RUNTIME @@ -2152,7 +2158,7 @@ HALIDE_ALWAYS_INLINE constexpr halide_type_t halide_type_of() { return halide_type_t(halide_type_handle, 64); } -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 template<> HALIDE_ALWAYS_INLINE constexpr halide_type_t halide_type_of<_Float16>() { return halide_type_t(halide_type_float, 16); diff --git a/test/correctness/float16_t.cpp b/test/correctness/float16_t.cpp index 8694c8c969f5..c73e30512011 100644 --- a/test/correctness/float16_t.cpp +++ b/test/correctness/float16_t.cpp @@ -322,7 +322,7 @@ int run_test() { std::abs(halfway_plus_eps - (double)to_even)); assert(float(halfway_plus_eps) == halfway); -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 assert(_Float16(halfway_plus_eps) == _Float16(float(to_odd))); #endif assert(float16_t(halfway_plus_eps) == to_odd); @@ -484,7 +484,7 @@ int main(int argc, char **argv) { } printf("Testing _Float16...\n"); -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 if (run_test<_Float16>() != 0) { fprintf(stderr, "_Float16 test failed!\n"); return 1; diff --git a/test/correctness/image_io.cpp b/test/correctness/image_io.cpp index 4921aa6f8a02..e24bccb9091b 100644 --- a/test/correctness/image_io.cpp +++ b/test/correctness/image_io.cpp @@ -278,7 +278,7 @@ int main(int argc, char **argv) { do_test(); do_test(); do_test(); -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 do_test<_Float16>(); #endif do_test(); diff --git a/tools/halide_image_io.h b/tools/halide_image_io.h index 3d84f22b04e4..2d078f1cc703 100644 --- a/tools/halide_image_io.h +++ b/tools/halide_image_io.h @@ -116,7 +116,7 @@ template<> inline bool convert(const int64_t &in) { return in != 0; } -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 template<> inline bool convert(const _Float16 &in) { return (float)in != 0; @@ -171,7 +171,7 @@ template<> inline uint8_t convert(const int64_t &in) { return convert(in); } -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 template<> inline uint8_t convert(const _Float16 &in) { return (uint8_t)std::lround((float)in * 255.0f); @@ -223,7 +223,7 @@ template<> inline uint16_t convert(const int64_t &in) { return convert(in); } -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 template<> inline uint16_t convert(const _Float16 &in) { return (uint16_t)std::lround((float)in * 65535.0f); @@ -275,7 +275,7 @@ template<> inline uint32_t convert(const int64_t &in) { return convert(in); } -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 template<> inline uint32_t convert(const _Float16 &in) { return (uint32_t)std::llround((float)in * 4294967295.0); @@ -327,7 +327,7 @@ template<> inline uint64_t convert(const int64_t &in) { return convert(in); } -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 template<> inline uint64_t convert(const _Float16 &in) { return convert((uint32_t)std::llround((float)in * 4294967295.0)); @@ -379,7 +379,7 @@ template<> inline int8_t convert(const int64_t &in) { return convert(in); } -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 template<> inline int8_t convert(const _Float16 &in) { return convert((float)in); @@ -431,7 +431,7 @@ template<> inline int16_t convert(const int64_t &in) { return convert(in); } -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 template<> inline int16_t convert(const _Float16 &in) { return convert((float)in); @@ -483,7 +483,7 @@ template<> inline int32_t convert(const int64_t &in) { return convert(in); } -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 template<> inline int32_t convert(const _Float16 &in) { return convert((float)in); @@ -535,7 +535,7 @@ template<> inline int64_t convert(const int64_t &in) { return convert(in); } -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 template<> inline int64_t convert(const _Float16 &in) { return convert((float)in); @@ -550,7 +550,7 @@ inline int64_t convert(const double &in) { return convert(in); } -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 // Convert to f16 template<> inline _Float16 convert(const bool &in) { @@ -639,7 +639,7 @@ template<> inline float convert(const int64_t &in) { return convert(in); } -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 template<> inline float convert(const _Float16 &in) { return (float)in; @@ -691,7 +691,7 @@ template<> inline double convert(const int64_t &in) { return convert(in); } -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 template<> inline double convert(const _Float16 &in) { return (double)in; @@ -2496,7 +2496,7 @@ struct ImageTypeConversion { const halide_type_t src_type = src.type(); switch (src_type.element_of().as_u32()) { -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 case halide_type_t(halide_type_float, 16).as_u32(): return convert_image(src.template as<_Float16, AnyDims>()); #endif @@ -2545,7 +2545,7 @@ struct ImageTypeConversion { // Call the appropriate static-to-static conversion routine // based on the desired dst type. switch (dst_type.element_of().as_u32()) { -#ifdef HALIDE_CPP_COMPILER_HAS_FLOAT16 +#if HALIDE_CPP_COMPILER_HAS_FLOAT16 case halide_type_t(halide_type_float, 16).as_u32(): return convert_image<_Float16>(src); #endif