[libc-commits] [libc] [libc][math] Add floating-point cast independent of compiler runtime (PR #105152)

via libc-commits libc-commits at lists.llvm.org
Tue Aug 20 10:32:45 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: OverMighty (overmighty)

<details>
<summary>Changes</summary>

Fixes build and tests with compiler-rt on x86.

---

Patch is 84.32 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/105152.diff


38 Files Affected:

- (modified) libc/cmake/modules/CheckCompilerFeatures.cmake (+16-3) 
- (added) libc/cmake/modules/compiler_features/check_float16_conversion.cpp (+30) 
- (modified) libc/src/__support/FPUtil/CMakeLists.txt (+22-3) 
- (modified) libc/src/__support/FPUtil/ManipulationFunctions.h (+7-5) 
- (added) libc/src/__support/FPUtil/cast.h (+65) 
- (modified) libc/src/__support/FPUtil/dyadic_float.h (+119-1) 
- (modified) libc/src/__support/FPUtil/except_value_utils.h (+18) 
- (modified) libc/src/__support/FPUtil/generic/CMakeLists.txt (+5-3) 
- (modified) libc/src/__support/FPUtil/generic/FMA.h (+3-2) 
- (modified) libc/src/__support/FPUtil/generic/add_sub.h (+3-2) 
- (modified) libc/src/__support/FPUtil/generic/sqrt.h (+2-1) 
- (modified) libc/src/math/generic/CMakeLists.txt (+18-6) 
- (modified) libc/src/math/generic/ceilf16.cpp (+2-1) 
- (modified) libc/src/math/generic/exp10f16.cpp (+6-5) 
- (modified) libc/src/math/generic/exp2f16.cpp (+2-1) 
- (modified) libc/src/math/generic/expf16.cpp (+3-2) 
- (modified) libc/src/math/generic/expm1f16.cpp (+4-3) 
- (modified) libc/src/math/generic/floorf16.cpp (+2-1) 
- (modified) libc/src/math/generic/rintf16.cpp (+2-1) 
- (modified) libc/src/math/generic/roundevenf16.cpp (+2-1) 
- (modified) libc/src/math/generic/roundf16.cpp (+2-1) 
- (modified) libc/src/math/generic/truncf16.cpp (+2-1) 
- (modified) libc/test/src/math/smoke/AddTest.h (+23-19) 
- (modified) libc/test/src/math/smoke/CMakeLists.txt (+15) 
- (modified) libc/test/src/math/smoke/DivTest.h (+46-36) 
- (modified) libc/test/src/math/smoke/FModTest.h (+32-32) 
- (modified) libc/test/src/math/smoke/FmaTest.h (+23-5) 
- (modified) libc/test/src/math/smoke/ModfTest.h (+1-1) 
- (modified) libc/test/src/math/smoke/MulTest.h (+28-24) 
- (modified) libc/test/src/math/smoke/NextTowardTest.h (+8-6) 
- (modified) libc/test/src/math/smoke/SqrtTest.h (+11-5) 
- (modified) libc/test/src/math/smoke/SubTest.h (+21-19) 
- (modified) libc/test/src/math/smoke/exp10f16_test.cpp (+8-6) 
- (modified) libc/test/src/math/smoke/exp2f16_test.cpp (+8-6) 
- (modified) libc/test/src/math/smoke/expf16_test.cpp (+8-6) 
- (modified) libc/test/src/math/smoke/expm1f16_test.cpp (+24-20) 
- (modified) libc/utils/MPFRWrapper/CMakeLists.txt (+1) 
- (modified) libc/utils/MPFRWrapper/MPFRUtils.cpp (+2-1) 


``````````diff
diff --git a/libc/cmake/modules/CheckCompilerFeatures.cmake b/libc/cmake/modules/CheckCompilerFeatures.cmake
index 63145fe709dda0..862c7ecbd7fdf4 100644
--- a/libc/cmake/modules/CheckCompilerFeatures.cmake
+++ b/libc/cmake/modules/CheckCompilerFeatures.cmake
@@ -10,6 +10,7 @@ set(
     "builtin_round"
     "builtin_roundeven"
     "float16"
+    "float16_conversion"
     "float128"
     "fixed_point"
 )
@@ -61,15 +62,21 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
   set(link_options "")
   if(${feature} STREQUAL "fixed_point")
     list(APPEND compile_options "-ffixed-point")
-  elseif(${feature} MATCHES "^builtin_")
+  elseif(${feature} MATCHES "^builtin_" OR
+         ${feature} STREQUAL "float16_conversion")
     set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT})
     set(link_options -nostdlib)
-    # The compiler might handle calls to rounding builtins by generating calls
-    # to the respective libc math functions, in which case we cannot use these
+    # The compiler might handle calls to math builtins by generating calls to
+    # the respective libc math functions, in which case we cannot use these
     # builtins in our implementations of these functions. We check that this is
     # not the case by trying to link an executable, since linking would fail due
     # to unresolved references with -nostdlib if calls to libc functions were
     # generated.
+    #
+    # We also had issues with soft-float float16 conversion functions using both
+    # compiler-rt and libgcc, so we also check whether we can convert from and
+    # to float16 without calls to compiler runtime functions by trying to link
+    # an executable with -nostdlib.
     set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
   endif()
 
@@ -97,6 +104,8 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
     list(APPEND AVAILABLE_COMPILER_FEATURES ${feature})
     if(${feature} STREQUAL "float16")
       set(LIBC_TYPES_HAS_FLOAT16 TRUE)
+    elseif(${feature} STREQUAL "float16_conversion")
+      add_compile_definitions(__LIBC_USE_FLOAT16_CONVERSION)
     elseif(${feature} STREQUAL "float128")
       set(LIBC_TYPES_HAS_FLOAT128 TRUE)
     elseif(${feature} STREQUAL "fixed_point")
@@ -115,6 +124,10 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
   endif()
 endforeach()
 
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT})
+set(link_options "")
+
 message(STATUS "Compiler features available: ${AVAILABLE_COMPILER_FEATURES}")
 
 ### Compiler Feature Detection ###
diff --git a/libc/cmake/modules/compiler_features/check_float16_conversion.cpp b/libc/cmake/modules/compiler_features/check_float16_conversion.cpp
new file mode 100644
index 00000000000000..09ac8e9c8bc9d6
--- /dev/null
+++ b/libc/cmake/modules/compiler_features/check_float16_conversion.cpp
@@ -0,0 +1,30 @@
+#include "include/llvm-libc-macros/float16-macros.h"
+#include "include/llvm-libc-types/float128.h"
+
+#ifndef LIBC_TYPES_HAS_FLOAT16
+#error unsupported
+#endif
+
+_Float16 cvt_from_float(float x) { return static_cast<_Float16>(x); }
+
+_Float16 cvt_from_double(double x) { return static_cast<_Float16>(x); }
+
+_Float16 cvt_from_long_double(long double x) {
+  return static_cast<_Float16>(x);
+}
+
+#ifdef LIBC_TYPES_HAS_FLOAT128
+_Float16 cvt_from_float128(float128 x) { return static_cast<_Float16>(x); }
+#endif
+
+float cvt_to_float(_Float16 x) { return x; }
+
+double cvt_to_double(_Float16 x) { return x; }
+
+long double cvt_to_long_double(_Float16 x) { return x; }
+
+#ifdef LIBC_TYPES_HAS_FLOAT128
+float128 cvt_to_float128(_Float16 x) { return x; }
+#endif
+
+extern "C" void _start() {}
diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index ea1e0e8b39d101..90901549946f42 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -97,6 +97,7 @@ add_header_library(
     .rounding_mode
     libc.src.__support.CPP.optional
     libc.src.__support.macros.optimization
+    libc.src.__support.macros.properties.types
 )
 
 
@@ -175,9 +176,13 @@ add_header_library(
     .fenv_impl
     .fp_bits
     .multiply_add
+    .rounding_mode
+    libc.hdr.errno_macros
+    libc.hdr.fenv_macros
     libc.src.__support.CPP.type_traits
     libc.src.__support.big_int
     libc.src.__support.macros.optimization
+    libc.src.__support.macros.properties.types
 )
 
 add_header_library(
@@ -217,18 +222,32 @@ add_header_library(
   HDRS
     ManipulationFunctions.h
   DEPENDS
+    .cast
+    .dyadic_float
     .fenv_impl
     .fp_bits
-    .dyadic_float
     .nearest_integer_operations
     .normal_float
     libc.hdr.math_macros
+    libc.src.errno.errno
+    libc.src.__support.common
     libc.src.__support.CPP.bit
     libc.src.__support.CPP.limits
     libc.src.__support.CPP.type_traits
-    libc.src.__support.common
     libc.src.__support.macros.optimization
-    libc.src.errno.errno
+)
+
+add_header_library(
+  cast
+  HDRS
+    cast.h
+  DEPENDS
+    .dyadic_float
+    .fp_bits
+    libc.hdr.fenv_macros
+    libc.src.__support.CPP.algorithm
+    libc.src.__support.CPP.type_traits
+    libc.src.__support.macros.properties.types
 )
 
 add_subdirectory(generic)
diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h
index a14f355789999a..66bfe2aa377f99 100644
--- a/libc/src/__support/FPUtil/ManipulationFunctions.h
+++ b/libc/src/__support/FPUtil/ManipulationFunctions.h
@@ -12,6 +12,7 @@
 #include "FPBits.h"
 #include "NearestIntegerOperations.h"
 #include "NormalFloat.h"
+#include "cast.h"
 #include "dyadic_float.h"
 #include "rounding_mode.h"
 
@@ -192,7 +193,8 @@ ldexp(T x, U exp) {
   // For all other values, NormalFloat to T conversion handles it the right way.
   DyadicFloat<FPBits<T>::STORAGE_LEN> normal(bits.get_val());
   normal.exponent += static_cast<int>(exp);
-  return static_cast<T>(normal);
+  // TODO: Add tests for exceptions.
+  return normal.template as<T, /*ShouldRaiseExceptions=*/true>();
 }
 
 template <typename T, typename U,
@@ -207,17 +209,17 @@ LIBC_INLINE T nextafter(T from, U to) {
 
   FPBits<U> to_bits(to);
   if (to_bits.is_nan())
-    return static_cast<T>(to);
+    return cast<T>(to);
 
   // NOTE: This would work only if `U` has a greater or equal precision than
   // `T`. Otherwise `from` could loose its precision and the following statement
   // could incorrectly evaluate to `true`.
-  if (static_cast<U>(from) == to)
-    return static_cast<T>(to);
+  if (cast<U>(from) == to)
+    return cast<T>(to);
 
   using StorageType = typename FPBits<T>::StorageType;
   if (from != T(0)) {
-    if ((static_cast<U>(from) < to) == (from > T(0))) {
+    if ((cast<U>(from) < to) == (from > T(0))) {
       from_bits = FPBits<T>(StorageType(from_bits.uintval() + 1));
     } else {
       from_bits = FPBits<T>(StorageType(from_bits.uintval() - 1));
diff --git a/libc/src/__support/FPUtil/cast.h b/libc/src/__support/FPUtil/cast.h
new file mode 100644
index 00000000000000..126f3852137b77
--- /dev/null
+++ b/libc/src/__support/FPUtil/cast.h
@@ -0,0 +1,65 @@
+//===-- Conversion between floating-point types -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_CAST_H
+#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_CAST_H
+
+#include "FPBits.h"
+#include "dyadic_float.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/CPP/algorithm.h"
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE::fputil {
+
+template <typename OutType, typename InType>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
+                                           cpp::is_floating_point_v<InType>,
+                                       OutType>
+cast(InType x) {
+#if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
+  if constexpr (cpp::is_same_v<OutType, float16> ||
+                cpp::is_same_v<InType, float16>) {
+    using InFPBits = FPBits<InType>;
+    using InStorageType = typename InFPBits::StorageType;
+    using OutFPBits = FPBits<OutType>;
+    using OutStorageType = typename OutFPBits::StorageType;
+
+    InFPBits x_bits(x);
+
+    if (x_bits.is_nan()) {
+      if (x_bits.is_signaling_nan()) {
+        raise_except_if_required(FE_INVALID);
+        return OutFPBits::quiet_nan().get_val();
+      }
+
+      InStorageType x_mant = x_bits.get_mantissa();
+      if (InFPBits::FRACTION_LEN > OutFPBits::FRACTION_LEN)
+        x_mant >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
+      return OutFPBits::quiet_nan(x_bits.sign(),
+                                  static_cast<OutStorageType>(x_mant))
+          .get_val();
+    }
+
+    if (x_bits.is_inf())
+      return OutFPBits::inf(x_bits.sign()).get_val();
+
+    constexpr size_t MAX_FRACTION_LEN =
+        cpp::max(OutFPBits::FRACTION_LEN, InFPBits::FRACTION_LEN);
+    DyadicFloat<cpp::bit_ceil(MAX_FRACTION_LEN)> xd(x);
+    return xd.template as<OutType, /*ShouldSignalExceptions=*/true>();
+  }
+#endif
+
+  return static_cast<OutType>(x);
+}
+
+} // namespace LIBC_NAMESPACE::fputil
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_CAST_H
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 86346a47b35a34..814d9423a27f87 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -11,11 +11,15 @@
 
 #include "FEnvImpl.h"
 #include "FPBits.h"
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
 #include "multiply_add.h"
+#include "rounding_mode.h"
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/big_int.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/macros/properties/types.h"
 
 #include <stddef.h>
 
@@ -33,7 +37,8 @@ namespace fputil {
 // The outputs of the constructors and most functions will be normalized.
 // To simplify and improve the efficiency, many functions will assume that the
 // inputs are normal.
-template <size_t Bits> struct DyadicFloat {
+template <size_t Bits> class DyadicFloat {
+public:
   using MantissaType = LIBC_NAMESPACE::UInt<Bits>;
 
   Sign sign = Sign::POS;
@@ -104,6 +109,11 @@ template <size_t Bits> struct DyadicFloat {
                                             (FPBits<T>::FRACTION_LEN < Bits),
                                         void>>
   LIBC_INLINE constexpr T as() const {
+#if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
+    if constexpr (cpp::is_same_v<T, float16>)
+      return generic_as<T>();
+#endif
+
     if (LIBC_UNLIKELY(mantissa.is_zero()))
       return FPBits<T>::zero(sign).get_val();
 
@@ -249,6 +259,114 @@ template <size_t Bits> struct DyadicFloat {
 
     return new_mant;
   }
+
+private:
+  template <typename OutType>
+  LIBC_INLINE constexpr cpp::enable_if_t<
+      cpp::is_floating_point_v<OutType> &&
+          sizeof(typename FPBits<OutType>::StorageType) <= sizeof(MantissaType),
+      OutType>
+  generic_as() const {
+    using FPBits = FPBits<float16>;
+    using StorageType = typename FPBits::StorageType;
+
+    constexpr int EXTRA_FRACTION_LEN = Bits - 1 - FPBits::FRACTION_LEN;
+
+    if (mantissa == 0)
+      return FPBits::zero(sign).get_val();
+
+    int unbiased_exp = get_unbiased_exponent();
+
+    if (unbiased_exp + FPBits::EXP_BIAS >= FPBits::MAX_BIASED_EXPONENT) {
+      set_errno_if_required(ERANGE);
+      raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
+
+      switch (quick_get_round()) {
+      case FE_TONEAREST:
+        return FPBits::inf(sign).get_val();
+      case FE_TOWARDZERO:
+        return FPBits::max_normal(sign).get_val();
+      case FE_DOWNWARD:
+        if (sign.is_pos())
+          return FPBits::max_normal(Sign::POS).get_val();
+        return FPBits::inf(Sign::NEG).get_val();
+      case FE_UPWARD:
+        if (sign.is_neg())
+          return FPBits::max_normal(Sign::NEG).get_val();
+        return FPBits::inf(Sign::POS).get_val();
+      default:
+        __builtin_unreachable();
+      }
+    }
+
+    StorageType out_biased_exp = 0;
+    StorageType out_mantissa = 0;
+    bool round = false;
+    bool sticky = false;
+    bool underflow = false;
+
+    if (unbiased_exp < -FPBits::EXP_BIAS - FPBits::FRACTION_LEN) {
+      sticky = true;
+      underflow = true;
+    } else if (unbiased_exp == -FPBits::EXP_BIAS - FPBits::FRACTION_LEN) {
+      round = true;
+      MantissaType sticky_mask = (MantissaType(1) << (Bits - 1)) - 1;
+      sticky = (mantissa & sticky_mask) != 0;
+    } else {
+      int extra_fraction_len = EXTRA_FRACTION_LEN;
+
+      if (unbiased_exp < 1 - FPBits::EXP_BIAS) {
+        underflow = true;
+        extra_fraction_len += 1 - FPBits::EXP_BIAS - unbiased_exp;
+      } else {
+        out_biased_exp =
+            static_cast<StorageType>(unbiased_exp + FPBits::EXP_BIAS);
+      }
+
+      MantissaType round_mask = MantissaType(1) << (extra_fraction_len - 1);
+      round = (mantissa & round_mask) != 0;
+      MantissaType sticky_mask = round_mask - 1;
+      sticky = (mantissa & sticky_mask) != 0;
+
+      out_mantissa = static_cast<StorageType>(mantissa >> extra_fraction_len);
+    }
+
+    bool lsb = (out_mantissa & 1) != 0;
+
+    StorageType result =
+        FPBits::create_value(sign, out_biased_exp, out_mantissa).uintval();
+
+    switch (quick_get_round()) {
+    case FE_TONEAREST:
+      if (round && (lsb || sticky))
+        ++result;
+      break;
+    case FE_DOWNWARD:
+      if (sign.is_neg() && (round || sticky))
+        ++result;
+      break;
+    case FE_UPWARD:
+      if (sign.is_pos() && (round || sticky))
+        ++result;
+      break;
+    default:
+      break;
+    }
+
+    if (round || sticky) {
+      int excepts = FE_INEXACT;
+      if (FPBits(result).is_inf()) {
+        set_errno_if_required(ERANGE);
+        excepts |= FE_OVERFLOW;
+      } else if (underflow) {
+        set_errno_if_required(ERANGE);
+        excepts |= FE_UNDERFLOW;
+      }
+      raise_except_if_required(excepts);
+    }
+
+    return FPBits(result).get_val();
+  }
 };
 
 // Quick add - Add 2 dyadic floats with rounding toward 0 and then normalize the
diff --git a/libc/src/__support/FPUtil/except_value_utils.h b/libc/src/__support/FPUtil/except_value_utils.h
index b9f54aa24e3a22..3b453fecdec76e 100644
--- a/libc/src/__support/FPUtil/except_value_utils.h
+++ b/libc/src/__support/FPUtil/except_value_utils.h
@@ -13,8 +13,11 @@
 #include "FPBits.h"
 #include "rounding_mode.h"
 #include "src/__support/CPP/optional.h"
+#include "src/__support/FPUtil/cast.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/macros/properties/cpu_features.h"
+#include "src/__support/macros/properties/types.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
@@ -113,6 +116,21 @@ template <typename T> LIBC_INLINE T round_result_slightly_up(T value_rn) {
   return tmp;
 }
 
+#if defined(LIBC_TYPES_HAS_FLOAT16) &&                                         \
+    !defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS)
+template <> LIBC_INLINE float16 round_result_slightly_down(float16 value_rn) {
+  volatile float tmp = value_rn;
+  tmp -= FPBits<float16>::min_normal().get_val();
+  return cast<float16>(tmp);
+}
+
+template <> LIBC_INLINE float16 round_result_slightly_up(float16 value_rn) {
+  volatile float tmp = value_rn;
+  tmp += FPBits<float16>::min_normal().get_val();
+  return cast<float16>(tmp);
+}
+#endif
+
 } // namespace fputil
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/FPUtil/generic/CMakeLists.txt b/libc/src/__support/FPUtil/generic/CMakeLists.txt
index 43096aa529fc37..b6f58f3fab571a 100644
--- a/libc/src/__support/FPUtil/generic/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/generic/CMakeLists.txt
@@ -8,6 +8,7 @@ add_header_library(
     libc.src.__support.common
     libc.src.__support.CPP.bit
     libc.src.__support.CPP.type_traits
+    libc.src.__support.FPUtil.cast
     libc.src.__support.FPUtil.dyadic_float
     libc.src.__support.FPUtil.fenv_impl
     libc.src.__support.FPUtil.fp_bits
@@ -21,16 +22,17 @@ add_header_library(
     FMA.h
   DEPENDS
     libc.hdr.fenv_macros
+    libc.src.__support.big_int
     libc.src.__support.common
     libc.src.__support.CPP.bit
     libc.src.__support.CPP.limits
     libc.src.__support.CPP.type_traits
     libc.src.__support.FPUtil.basic_operations
+    libc.src.__support.FPUtil.cast
     libc.src.__support.FPUtil.dyadic_float
     libc.src.__support.FPUtil.fenv_impl
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.rounding_mode
-    libc.src.__support.big_int
     libc.src.__support.macros.optimization
     libc.src.__support.uint128
 )
@@ -60,12 +62,12 @@ add_header_library(
     libc.src.__support.CPP.bit
     libc.src.__support.CPP.type_traits
     libc.src.__support.FPUtil.basic_operations
+    libc.src.__support.FPUtil.cast
+    libc.src.__support.FPUtil.dyadic_float
     libc.src.__support.FPUtil.fenv_impl
     libc.src.__support.FPUtil.fp_bits
-    libc.src.__support.FPUtil.dyadic_float
     libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.macros.attributes
-    libc.src.__support.macros.optimization
 )
 
 add_header_library(
diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h
index e5683c8ff61ea0..bec312e44b1b10 100644
--- a/libc/src/__support/FPUtil/generic/FMA.h
+++ b/libc/src/__support/FPUtil/generic/FMA.h
@@ -14,6 +14,7 @@
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/FPUtil/BasicOperations.h"
 #include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/cast.h"
 #include "src/__support/FPUtil/dyadic_float.h"
 #include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/big_int.h"
@@ -157,7 +158,7 @@ fma(InType x, InType y, InType z) {
   }
 
   if (LIBC_UNLIKELY(x == 0 || y == 0 || z == 0))
-    return static_cast<OutType>(x * y + z);
+    return cast<OutType>(x * y + z);
 
   int x_exp = 0;
   int y_exp = 0;
@@ -198,7 +199,7 @@ fma(InType x, InType y, InType z) {
   if (LIBC_UNLIKELY(x_exp == InFPBits::MAX_BIASED_EXPONENT ||
                     y_exp == InFPBits::MAX_BIASED_EXPONENT ||
                     z_exp == InFPBits::MAX_BIASED_EXPONENT))
-    return static_cast<OutType>(x * y + z);
+    return cast<OutType>(x * y + z);
 
   // Extract mantissa and append hidden leading bits.
   InStorageType x_mant = x_bits.get_explicit_mantissa();
diff --git a/libc/src/__support/FPUtil/generic/add_sub.h b/libc/src/__support/FPUtil/generic/add_sub.h
index 850db3f83209e6..6bc9dcd23bafad 100644
--- a/libc/src/__support/FPUtil/generic/add_sub.h
+++ b/libc/src/__support/FPUtil/generic/add_sub.h
@@ -17,6 +17,7 @@
 #include "src/__support/FPUtil/BasicOperations.h"
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/cast.h"
 #include "src/__support/FPUtil/dyadic_float.h"
 #include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/macros/attributes.h"
@@ -106,14 +107,14 @@ add_or_sub(InType x, InType y) {
       volatile InType tmp = y;
       if constexpr (IsSub)
         tmp = -tmp;
-      return static_cast<OutType>(tmp);
+      return cast<OutType>(tmp);
     }
 
     if (y_bits.is_zero()) {
       volatile InType tmp = y;
       if constexpr (IsSub)
         tmp = -tmp;
-      return static_cast<OutType>(tmp);
+      return cast<OutType>(tmp);
     }
   }
 
diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h
index 4502cc07d32b31..01af4bb7c90092 100644
--- a/libc/src/__support/FPUtil/generic/sqrt.h
+++ b/libc/src/__support/FPUtil/generic/sqrt.h
@@ -14,6 +14,7 @@
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/cast.h"
 #include "src/__support/FPUtil/dyadic_float.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
@@ -96,7 +97,...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/105152


More information about the libc-commits mailing list