[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