[libc-commits] [libc] [llvm] [libc][math] Do not use float16 basic operations in hypotf16. (PR #155177)
via libc-commits
libc-commits at lists.llvm.org
Sun Aug 24 14:19:23 PDT 2025
https://github.com/lntue updated https://github.com/llvm/llvm-project/pull/155177
>From e7185823fcca561b91b04ebfdbb3dee79b596c50 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Sun, 24 Aug 2025 16:19:49 +0000
Subject: [PATCH 1/2] [libc][math] Do not use float16 basic operations in
hypotf16 as compiler runtimes might not be correct for all rounding modes.
---
libc/src/__support/FPUtil/CMakeLists.txt | 1 +
libc/src/__support/FPUtil/Hypot.h | 14 ++++++++++++--
libc/src/math/generic/hypotf16.cpp | 13 ++++++-------
utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 1 +
4 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 37520eadba005..e8fc539fd32e8 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -231,6 +231,7 @@ add_header_library(
Hypot.h
DEPENDS
.basic_operations
+ .cast
.fenv_impl
.fp_bits
.rounding_mode
diff --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h
index 94da259cd42f0..227ff5e49372e 100644
--- a/libc/src/__support/FPUtil/Hypot.h
+++ b/libc/src/__support/FPUtil/Hypot.h
@@ -12,6 +12,7 @@
#include "BasicOperations.h"
#include "FEnvImpl.h"
#include "FPBits.h"
+#include "cast.h"
#include "rounding_mode.h"
#include "src/__support/CPP/bit.h"
#include "src/__support/CPP/type_traits.h"
@@ -133,8 +134,17 @@ LIBC_INLINE T hypot(T x, T y) {
uint16_t a_exp = a_bits.get_biased_exponent();
uint16_t b_exp = b_bits.get_biased_exponent();
- if ((a_exp - b_exp >= FPBits_t::FRACTION_LEN + 2) || (x == 0) || (y == 0))
- return x_abs.get_val() + y_abs.get_val();
+ if ((a_exp - b_exp >= FPBits_t::FRACTION_LEN + 2) || (x == 0) || (y == 0)) {
+ if constexpr (cpp::is_same_v<T, float16>) {
+ // Compiler runtime for basic operations of float16 might not be correctly
+ // rounded for all rounding modes.
+ float af = fputil::cast<float>(x_abs.get_val());
+ float bf = fputil::cast<float>(y_abs.get_val());
+ return fputil::cast<float16>(af + bf);
+ } else {
+ return x_abs.get_val() + y_abs.get_val();
+ }
+ }
uint64_t out_exp = a_exp;
StorageType a_mant = a_bits.get_mantissa();
diff --git a/libc/src/math/generic/hypotf16.cpp b/libc/src/math/generic/hypotf16.cpp
index d782c2687cdb6..fa90069f9ff0d 100644
--- a/libc/src/math/generic/hypotf16.cpp
+++ b/libc/src/math/generic/hypotf16.cpp
@@ -48,16 +48,15 @@ LLVM_LIBC_FUNCTION(float16, hypotf16, (float16 x, float16 y)) {
return a_bits.get_val();
}
- // TODO: Investigate why replacing the return line below with:
- // return x_bits.get_val() + y_bits.get_val();
- // fails the hypotf16 smoke tests.
+ float af = fputil::cast<float>(a_bits.get_val());
+ float bf = fputil::cast<float>(b_bits.get_val());
+
+ // Compiler runtime basic operations for float16 might not be correctly
+ // rounded for all rounding modes.
if (LIBC_UNLIKELY(a_u - b_u >=
static_cast<uint16_t>((FPBits::FRACTION_LEN + 2)
<< FPBits::FRACTION_LEN)))
- return a_bits.get_val() + b_bits.get_val();
-
- float af = fputil::cast<float>(a_bits.get_val());
- float bf = fputil::cast<float>(b_bits.get_val());
+ return fputil::cast<float16>(af + bf);
// These squares are exact.
float a_sq = af * af;
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index a4a2e39c74fe0..bfda5385f012b 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -1230,6 +1230,7 @@ libc_support_library(
":__support_cpp_bit",
":__support_cpp_type_traits",
":__support_fputil_basic_operations",
+ ":__support_fputil_cast",
":__support_fputil_fenv_impl",
":__support_fputil_fp_bits",
":__support_fputil_rounding_mode",
>From 7d0656e09205cb9de88b8cbecc510ae7aef6dd2a Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Sun, 24 Aug 2025 21:18:37 +0000
Subject: [PATCH 2/2] Omit hypot float16 check when targets do not have
float16.
---
libc/src/__support/FPUtil/Hypot.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h
index 227ff5e49372e..e23f8b52d8220 100644
--- a/libc/src/__support/FPUtil/Hypot.h
+++ b/libc/src/__support/FPUtil/Hypot.h
@@ -135,15 +135,16 @@ LIBC_INLINE T hypot(T x, T y) {
uint16_t b_exp = b_bits.get_biased_exponent();
if ((a_exp - b_exp >= FPBits_t::FRACTION_LEN + 2) || (x == 0) || (y == 0)) {
+#ifdef LIBC_TYPES_HAS_FLOAT16
if constexpr (cpp::is_same_v<T, float16>) {
// Compiler runtime for basic operations of float16 might not be correctly
// rounded for all rounding modes.
float af = fputil::cast<float>(x_abs.get_val());
float bf = fputil::cast<float>(y_abs.get_val());
return fputil::cast<float16>(af + bf);
- } else {
+ } else
+#endif // LIBC_TYPES_HAS_FLOAT16
return x_abs.get_val() + y_abs.get_val();
- }
}
uint64_t out_exp = a_exp;
More information about the libc-commits
mailing list