[libc-commits] [libc] [libc][math][C23] add software float16 support (PR #184283)

via libc-commits libc-commits at lists.llvm.org
Fri Aug 28 20:48:55 PDT 2026


https://github.com/AnonMiraj updated https://github.com/llvm/llvm-project/pull/184283

>From 462f21f58041a85431e71a102a933980683a62eb Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Tue, 3 Mar 2026 02:42:07 +0200
Subject: [PATCH 1/3] [libc][math][C23] add software float16 support

---
 libc/config/linux/arm/entrypoints.txt         |   5 +
 .../include/llvm-libc-macros/float16-macros.h |  13 +-
 libc/src/__support/FPUtil/BasicOperations.h   |   4 +
 libc/src/__support/FPUtil/CMakeLists.txt      |  18 +++
 libc/src/__support/FPUtil/Float16.h           | 127 ++++++++++++++++++
 libc/src/__support/macros/properties/types.h  |  12 ++
 libc/src/__support/math/CMakeLists.txt        |   1 +
 libc/src/__support/math/fabsf16.h             |   4 +-
 libc/test/src/math/exhaustive/CMakeLists.txt  |  17 +++
 .../src/math/exhaustive/exhaustive_test.h     |   1 +
 .../test/src/math/exhaustive/float16_test.cpp |  67 +++++++++
 libc/test/src/math/smoke/CMakeLists.txt       |   1 +
 libc/test/src/math/smoke/fabsf16_test.cpp     |   2 +-
 libc/utils/MPFRWrapper/CMakeLists.txt         |   2 +
 libc/utils/MPFRWrapper/MPCommon.cpp           |   7 +-
 libc/utils/MPFRWrapper/MPFRUtils.cpp          |   1 +
 16 files changed, 276 insertions(+), 6 deletions(-)
 create mode 100644 libc/src/__support/FPUtil/Float16.h
 create mode 100644 libc/test/src/math/exhaustive/float16_test.cpp

diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 1986d6a5347dc..608b50843b94a 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -506,6 +506,11 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.ufromfpxl
 )
 
+list(APPEND TARGET_LIBM_ENTRYPOINTS
+  # float16 entrypoints
+  libc.src.math.fabsf16
+)
+
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
   libc.src.math.atanbf16
diff --git a/libc/include/llvm-libc-macros/float16-macros.h b/libc/include/llvm-libc-macros/float16-macros.h
index 528c7f016f873..0b40a1b85636c 100644
--- a/libc/include/llvm-libc-macros/float16-macros.h
+++ b/libc/include/llvm-libc-macros/float16-macros.h
@@ -11,11 +11,18 @@
 
 #include "../llvm-libc-types/float128.h"
 
-#if defined(__FLT16_MANT_DIG__) &&                                             \
+#if defined(__arm__) && defined(_M_ARM)
+#define LIBC_USE_SOFT_FLOAT16
+#endif
+
+#ifdef LIBC_USE_SOFT_FLOAT16
+#define LIBC_TYPES_HAS_FLOAT16
+#endif
+
+#if !defined(LIBC_TYPES_HAS_FLOAT16) && defined(__FLT16_MANT_DIG__) &&         \
     (!defined(__GNUC__) || __GNUC__ >= 13 ||                                   \
      (defined(__clang__) && __clang_major__ >= 12)) &&                         \
-    !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) &&              \
-    !defined(_WIN32)
+    !defined(__riscv) && !defined(_WIN32)
 #define LIBC_TYPES_HAS_FLOAT16
 
 // TODO: This would no longer be required if HdrGen let us guard function
diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h
index 5b81b921296a0..747d089f3da73 100644
--- a/libc/src/__support/FPUtil/BasicOperations.h
+++ b/libc/src/__support/FPUtil/BasicOperations.h
@@ -53,6 +53,7 @@ max(T x, T y) {
 }
 
 #ifdef LIBC_TYPES_HAS_FLOAT16
+#if !defined(LIBC_USE_SOFT_FLOAT16)
 #if defined(__LIBC_USE_BUILTIN_FMAXF16_FMINF16)
 template <> LIBC_INLINE constexpr float16 max(float16 x, float16 y) {
   if (cpp::is_constant_evaluated())
@@ -69,6 +70,7 @@ template <> LIBC_INLINE constexpr float16 max(float16 x, float16 y) {
   return ((xi > yi) != (xi < 0 && yi < 0)) ? x : y;
 }
 #endif
+#endif // !LIBC_USE_SOFT_FLOAT16
 #endif // LIBC_TYPES_HAS_FLOAT16
 
 #if defined(__LIBC_USE_BUILTIN_FMAX_FMIN) && !defined(LIBC_TARGET_ARCH_IS_X86)
@@ -106,6 +108,7 @@ min(T x, T y) {
 }
 
 #ifdef LIBC_TYPES_HAS_FLOAT16
+#if !defined(LIBC_USE_SOFT_FLOAT16)
 #if defined(__LIBC_USE_BUILTIN_FMAXF16_FMINF16)
 template <> LIBC_INLINE constexpr float16 min(float16 x, float16 y) {
   if (cpp::is_constant_evaluated())
@@ -122,6 +125,7 @@ template <> LIBC_INLINE constexpr float16 min(float16 x, float16 y) {
   return ((xi < yi) != (xi < 0 && yi < 0)) ? x : y;
 }
 #endif
+#endif // !LIBC_USE_SOFT_FLOAT16
 #endif // LIBC_TYPES_HAS_FLOAT16
 
 #if defined(__LIBC_USE_BUILTIN_FMAX_FMIN) && !defined(LIBC_TARGET_ARCH_IS_X86)
diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 4673ef794c80b..2f86adc9b745e 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -43,6 +43,24 @@ add_header_library(
     libc.src.__support.uint128
 )
 
+add_header_library(
+  Float16
+  HDRS
+    Float16.h
+  DEPENDS
+    .cast
+    .comparison_operations
+    .dyadic_float
+    libc.hdr.stdint_proxy
+    libc.src.__support.CPP.bit
+    libc.src.__support.CPP.type_traits
+    libc.src.__support.FPUtil.generic.add_sub
+    libc.src.__support.FPUtil.generic.div
+    libc.src.__support.FPUtil.generic.mul
+    libc.src.__support.macros.config
+    libc.src.__support.macros.properties.types
+)
+
 add_header_library(
   fpbits_str
   HDRS
diff --git a/libc/src/__support/FPUtil/Float16.h b/libc/src/__support/FPUtil/Float16.h
new file mode 100644
index 0000000000000..5387e6a7c1c7a
--- /dev/null
+++ b/libc/src/__support/FPUtil/Float16.h
@@ -0,0 +1,127 @@
+//===-- Definition of float16 data type. ------------------------*- 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_FLOAT16_H
+#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT16_H
+
+#include "src/__support/macros/properties/types.h"
+
+#ifdef LIBC_USE_SOFT_FLOAT16
+
+#include "hdr/stdint_proxy.h"
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/comparison_operations.h"
+#include "src/__support/FPUtil/dyadic_float.h"
+#include "src/__support/FPUtil/generic/add_sub.h"
+#include "src/__support/FPUtil/generic/div.h"
+#include "src/__support/FPUtil/generic/mul.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace fputil {
+
+struct Float16 {
+  uint16_t bits;
+
+  LIBC_INLINE Float16() = default;
+
+  template <typename T>
+  LIBC_INLINE constexpr explicit Float16(T value)
+      : bits(static_cast<uint16_t>(0U)) {
+    if constexpr (cpp::is_floating_point_v<T>) {
+      bits = fputil::cast<Float16>(value).bits;
+    } else if constexpr (cpp::is_integral_v<T>) {
+      Sign sign = Sign::POS;
+
+      if constexpr (cpp::is_signed_v<T>) {
+        if (value < 0) {
+          sign = Sign::NEG;
+          value = -value;
+        }
+      }
+
+      fputil::DyadicFloat<cpp::numeric_limits<cpp::make_unsigned_t<T>>::digits>
+          xd(sign, 0, value);
+      bits = xd.template as<Float16, /*ShouldSignalExceptions=*/true>().bits;
+
+    } else if constexpr (cpp::is_convertible_v<T, Float16>) {
+      bits = value.operator Float16().bits;
+    }
+  }
+
+  template <cpp::enable_if_t<fputil::get_fp_type<float>() ==
+                                 fputil::FPType::IEEE754_Binary32,
+                             int> = 0>
+  LIBC_INLINE constexpr operator float() const {
+    return fputil::cast<float>(*this);
+  }
+
+  template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
+  LIBC_INLINE constexpr explicit operator T() const {
+    return static_cast<T>(static_cast<float>(*this));
+  }
+
+  LIBC_INLINE bool operator==(Float16 other) const {
+    return fputil::equals(*this, other);
+  }
+
+  LIBC_INLINE bool operator!=(Float16 other) const {
+    return !fputil::equals(*this, other);
+  }
+
+  LIBC_INLINE bool operator<(Float16 other) const {
+    return fputil::less_than(*this, other);
+  }
+
+  LIBC_INLINE bool operator<=(Float16 other) const {
+    return fputil::less_than_or_equals(*this, other);
+  }
+
+  LIBC_INLINE bool operator>(Float16 other) const {
+    return fputil::greater_than(*this, other);
+  }
+
+  LIBC_INLINE bool operator>=(Float16 other) const {
+    return fputil::greater_than_or_equals(*this, other);
+  }
+
+  LIBC_INLINE constexpr Float16 operator-() const {
+    fputil::FPBits<float16> result(*this);
+    result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
+    return result.get_val();
+  }
+
+  LIBC_INLINE Float16 operator+(Float16 other) const {
+    return fputil::generic::add<Float16>(*this, other);
+  }
+
+  LIBC_INLINE Float16 operator-(Float16 other) const {
+    return fputil::generic::sub<Float16>(*this, other);
+  }
+
+  LIBC_INLINE Float16 operator*(Float16 other) const {
+    return fputil::generic::mul<float16>(*this, other);
+  }
+
+  LIBC_INLINE Float16 operator/(Float16 other) const {
+    return fputil::generic::div<float16>(*this, other);
+  }
+
+  LIBC_INLINE Float16 &operator*=(const Float16 &other) {
+    *this = *this * other;
+    return *this;
+  }
+}; // struct Float16
+
+} // namespace fputil
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_USE_SOFT_FLOAT16
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT16_H
diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h
index 505fa6d7957f8..68907507b9ffc 100644
--- a/libc/src/__support/macros/properties/types.h
+++ b/libc/src/__support/macros/properties/types.h
@@ -50,8 +50,20 @@
 // LIBC_TYPES_HAS_FLOAT16 is provided by
 // "include/llvm-libc-macros/float16-macros.h"
 #ifdef LIBC_TYPES_HAS_FLOAT16
+
+#ifdef LIBC_USE_SOFT_FLOAT16
+namespace LIBC_NAMESPACE_DECL {
+namespace fputil {
+struct Float16;
+} // namespace fputil
+} // namespace LIBC_NAMESPACE_DECL
+
+using float16 = LIBC_NAMESPACE::fputil::Float16;
+#else
 // Type alias for internal use.
 using float16 = _Float16;
+#endif
+
 #endif // LIBC_TYPES_HAS_FLOAT16
 
 // -- float128 support --------------------------------------------------------
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 9f4624682eafe..baed5ad3ffea9 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -3236,6 +3236,7 @@ add_header_library(
     fabsf16.h
   DEPENDS
     libc.include.llvm-libc-macros.float16_macros
+    libc.src.__support.FPUtil.Float16
     libc.src.__support.FPUtil.basic_operations
     libc.src.__support.macros.config
   FLAGS
diff --git a/libc/src/__support/math/fabsf16.h b/libc/src/__support/math/fabsf16.h
index 26634361adc73..ca568c680b7c2 100644
--- a/libc/src/__support/math/fabsf16.h
+++ b/libc/src/__support/math/fabsf16.h
@@ -14,6 +14,7 @@
 #ifdef LIBC_TYPES_HAS_FLOAT16
 
 #include "src/__support/FPUtil/BasicOperations.h"
+#include "src/__support/FPUtil/Float16.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/properties/architectures.h"
 #include "src/__support/macros/properties/compiler.h"
@@ -27,7 +28,8 @@ LIBC_INLINE constexpr float16 fabsf16(float16 x) {
   // For x86, GCC generates better code from the generic implementation.
   // https://godbolt.org/z/K9orM4hTa
 #if defined(__LIBC_MISC_MATH_BASIC_OPS_OPT) &&                                 \
-    !(defined(LIBC_TARGET_ARCH_IS_X86) && defined(LIBC_COMPILER_IS_GCC))
+    !(defined(LIBC_TARGET_ARCH_IS_X86) && defined(LIBC_COMPILER_IS_GCC)) &&    \
+    !defined(LIBC_USE_SOFT_FLOAT16)
   return __builtin_fabsf16(x);
 #else
   return fputil::abs(x);
diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index 2d1301d3a1e66..97355fbbf0278 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -713,6 +713,23 @@ add_fp_unittest(
     -lpthread
 )
 
+add_fp_unittest(
+  float16_test
+  NO_RUN_POSTBUILD
+  NEED_MPFR
+  SUITE
+    libc_math_exhaustive_tests
+  SRCS
+    float16_test.cpp
+  DEPENDS
+    .exhaustive_test
+    libc.src.__support.FPUtil.Float16
+    libc.src.__support.FPUtil.cast
+    libc.src.__support.FPUtil.fp_bits
+  LINK_LIBRARIES
+    -lpthread
+)
+
 add_fp_unittest(
   bfloat16_test
   NO_RUN_POSTBUILD
diff --git a/libc/test/src/math/exhaustive/exhaustive_test.h b/libc/test/src/math/exhaustive/exhaustive_test.h
index 322d774d46a68..04d43214e00a2 100644
--- a/libc/test/src/math/exhaustive/exhaustive_test.h
+++ b/libc/test/src/math/exhaustive/exhaustive_test.h
@@ -8,6 +8,7 @@
 
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/Float16.h"
 #include "src/__support/macros/properties/types.h"
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
diff --git a/libc/test/src/math/exhaustive/float16_test.cpp b/libc/test/src/math/exhaustive/float16_test.cpp
new file mode 100644
index 0000000000000..3d1ba1ab805a6
--- /dev/null
+++ b/libc/test/src/math/exhaustive/float16_test.cpp
@@ -0,0 +1,67 @@
+//===-- Exhaustive tests for float -> float16 conversion ------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "exhaustive_test.h"
+#include "src/__support/FPUtil/cast.h"
+#include "utils/MPFRWrapper/MPCommon.h"
+
+using namespace LIBC_NAMESPACE::fputil;
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+template <typename InType>
+struct Float16ConversionChecker : public virtual LIBC_NAMESPACE::testing::Test {
+  using FloatType = InType;
+  using FPBits = LIBC_NAMESPACE::fputil::FPBits<FloatType>;
+  using StorageType = typename FPBits::StorageType;
+
+  // Check in a range, return the number of failures.
+  uint64_t check(StorageType start, StorageType stop,
+                 mpfr::RoundingMode rounding) {
+    mpfr::ForceRoundingMode r(rounding);
+    if (!r.success)
+      return (stop > start);
+    StorageType bits = start;
+    uint64_t failed = 0;
+    do {
+      FPBits x_bits(bits);
+      FloatType x = x_bits.get_val();
+
+      const float16 libc_result = cast<float16>(x);
+      const float16 mpfr_result = mpfr::MPFRNumber(x).as<float16>();
+
+      const bool correct =
+          LIBC_NAMESPACE::testing::getMatcher<
+              LIBC_NAMESPACE::testing::TestCond::EQ>(mpfr_result)
+              .match(libc_result);
+
+      failed += (!correct);
+    } while (bits++ < stop);
+    return failed;
+  }
+};
+
+template <typename FloatType>
+using LlvmLibcFloat16ExhaustiveTest =
+    LlvmLibcExhaustiveMathTest<Float16ConversionChecker<FloatType>>;
+using LlvmLibcFloat16FromFloatTest = LlvmLibcFloat16ExhaustiveTest<float>;
+
+// Positive Range: [0, Inf];
+constexpr uint32_t POS_START = 0x0000'0000U;
+constexpr uint32_t POS_STOP = 0x7f80'0000U;
+
+// Negative Range: [-Inf, 0];
+constexpr uint32_t NEG_START = 0xb000'0000U;
+constexpr uint32_t NEG_STOP = 0xff80'0000U;
+
+TEST_F(LlvmLibcFloat16FromFloatTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
+}
+
+TEST_F(LlvmLibcFloat16FromFloatTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
+}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 81f76fa7681fd..8e670ad2a2851 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -229,6 +229,7 @@ add_fp_unittest(
     FAbsTest.h
   DEPENDS
     libc.src.math.fabsf16
+    libc.src.__support.FPUtil.Float16
 )
 
 add_fp_unittest(
diff --git a/libc/test/src/math/smoke/fabsf16_test.cpp b/libc/test/src/math/smoke/fabsf16_test.cpp
index c43bd5090f90b..d4d6dd1d2593a 100644
--- a/libc/test/src/math/smoke/fabsf16_test.cpp
+++ b/libc/test/src/math/smoke/fabsf16_test.cpp
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "FAbsTest.h"
-
+#include "src/__support/FPUtil/Float16.h"
 #include "src/math/fabsf16.h"
 
 LIST_FABS_TESTS(float16, LIBC_NAMESPACE::fabsf16)
diff --git a/libc/utils/MPFRWrapper/CMakeLists.txt b/libc/utils/MPFRWrapper/CMakeLists.txt
index 73151c61a7fcc..a1546992ce21c 100644
--- a/libc/utils/MPFRWrapper/CMakeLists.txt
+++ b/libc/utils/MPFRWrapper/CMakeLists.txt
@@ -14,6 +14,7 @@ if(LIBC_TESTS_CAN_USE_MPFR OR LIBC_TESTS_CAN_USE_MPC)
     libc.src.__support.CPP.string
     libc.src.__support.CPP.string_view
     libc.src.__support.CPP.type_traits
+    libc.src.__support.FPUtil.Float16
     libc.src.__support.FPUtil.bfloat16
     libc.src.__support.FPUtil.cast
     libc.src.__support.FPUtil.fp_bits
@@ -43,6 +44,7 @@ if(LIBC_TESTS_CAN_USE_MPFR)
     libc.hdr.stdint_proxy
     libc.src.__support.CPP.array
     libc.src.__support.CPP.stringstream
+    libc.src.__support.FPUtil.Float16
     libc.src.__support.FPUtil.bfloat16
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.fpbits_str
diff --git a/libc/utils/MPFRWrapper/MPCommon.cpp b/libc/utils/MPFRWrapper/MPCommon.cpp
index 2422bcf45222f..4847f03d1cbfa 100644
--- a/libc/utils/MPFRWrapper/MPCommon.cpp
+++ b/libc/utils/MPFRWrapper/MPCommon.cpp
@@ -10,6 +10,11 @@
 
 #include "src/__support/CPP/string_view.h"
 #include "src/__support/FPUtil/bfloat16.h"
+
+#ifdef LIBC_USE_SOFT_FLOAT16
+#include "src/__support/FPUtil/Float16.h"
+#endif
+
 #include "src/__support/FPUtil/cast.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/properties/types.h"
@@ -632,7 +637,7 @@ template <> long double MPFRNumber::as<long double>() const {
   return mpfr_get_ld(value, mpfr_rounding);
 }
 
-#ifdef LIBC_TYPES_HAS_FLOAT16
+#if defined(LIBC_TYPES_HAS_FLOAT16) || defined(LIBC_USE_SOFT_FLOAT16)
 template <> float16 MPFRNumber::as<float16>() const {
   // TODO: Either prove that this cast won't cause double-rounding errors, or
   // find a better way to get a float16.
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index d585baa2e0d2c..b928edeebba4b 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -11,6 +11,7 @@
 
 #include "src/__support/CPP/array.h"
 #include "src/__support/CPP/stringstream.h"
+#include "src/__support/FPUtil/Float16.h"
 #include "src/__support/FPUtil/bfloat16.h"
 #include "src/__support/FPUtil/fpbits_str.h"
 #include "src/__support/macros/config.h"

>From ad2e245150fb5234cd42f4f95cc6b800b29504e6 Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Wed, 5 Aug 2026 03:40:11 +0300
Subject: [PATCH 2/3] address reviews

---
 .../include/llvm-libc-macros/float16-macros.h |   2 +-
 .../CPP/type_traits/is_floating_point.h       |   3 +-
 libc/src/__support/FPUtil/BasicOperations.h   |  12 +-
 libc/src/__support/FPUtil/CMakeLists.txt      |  37 +++---
 libc/src/__support/FPUtil/FPBits.h            |   2 +
 libc/src/__support/FPUtil/cast.h              |  22 +++-
 libc/src/__support/FPUtil/dyadic_float.h      |   3 +-
 .../__support/FPUtil/{Float16.h => float16.h} |  55 +++++---
 libc/src/__support/macros/properties/types.h  |   6 +-
 libc/src/__support/math/CMakeLists.txt        |   2 +-
 libc/src/__support/math/fabsf16.h             |   2 +-
 libc/test/src/__support/FPUtil/CMakeLists.txt |  11 ++
 .../src/__support/FPUtil/float16_test.cpp     | 124 ++++++++++++++++++
 libc/test/src/math/exhaustive/CMakeLists.txt  |   2 +-
 .../src/math/exhaustive/exhaustive_test.h     |   2 +-
 libc/test/src/math/smoke/CMakeLists.txt       |   2 +-
 libc/test/src/math/smoke/fabsf16_test.cpp     |   2 +-
 libc/utils/MPFRWrapper/CMakeLists.txt         |   4 +-
 libc/utils/MPFRWrapper/MPCommon.cpp           |  14 +-
 libc/utils/MPFRWrapper/MPCommon.h             |   9 ++
 libc/utils/MPFRWrapper/MPFRUtils.cpp          |   2 +-
 21 files changed, 243 insertions(+), 75 deletions(-)
 rename libc/src/__support/FPUtil/{Float16.h => float16.h} (68%)
 create mode 100644 libc/test/src/__support/FPUtil/float16_test.cpp

diff --git a/libc/include/llvm-libc-macros/float16-macros.h b/libc/include/llvm-libc-macros/float16-macros.h
index 0b40a1b85636c..5a1a9cdd311f8 100644
--- a/libc/include/llvm-libc-macros/float16-macros.h
+++ b/libc/include/llvm-libc-macros/float16-macros.h
@@ -11,7 +11,7 @@
 
 #include "../llvm-libc-types/float128.h"
 
-#if defined(__arm__) && defined(_M_ARM)
+#if (defined(__arm__) && defined(_M_ARM)) || defined(__riscv)
 #define LIBC_USE_SOFT_FLOAT16
 #endif
 
diff --git a/libc/src/__support/CPP/type_traits/is_floating_point.h b/libc/src/__support/CPP/type_traits/is_floating_point.h
index 283c4fcefb6fe..dae4e47a5534c 100644
--- a/libc/src/__support/CPP/type_traits/is_floating_point.h
+++ b/libc/src/__support/CPP/type_traits/is_floating_point.h
@@ -42,7 +42,8 @@ template <typename T> struct is_floating_point {
 #endif
                               ,
                               bfloat16
-
+                              ,
+                              fputil::Float16
                               ,
                               fputil::Float128>();
 };
diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h
index 747d089f3da73..4c64d6dabbd29 100644
--- a/libc/src/__support/FPUtil/BasicOperations.h
+++ b/libc/src/__support/FPUtil/BasicOperations.h
@@ -52,8 +52,7 @@ max(T x, T y) {
   return constexpr_max(x, y);
 }
 
-#ifdef LIBC_TYPES_HAS_FLOAT16
-#if !defined(LIBC_USE_SOFT_FLOAT16)
+#if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(LIBC_USE_SOFT_FLOAT16)
 #if defined(__LIBC_USE_BUILTIN_FMAXF16_FMINF16)
 template <> LIBC_INLINE constexpr float16 max(float16 x, float16 y) {
   if (cpp::is_constant_evaluated())
@@ -70,8 +69,7 @@ template <> LIBC_INLINE constexpr float16 max(float16 x, float16 y) {
   return ((xi > yi) != (xi < 0 && yi < 0)) ? x : y;
 }
 #endif
-#endif // !LIBC_USE_SOFT_FLOAT16
-#endif // LIBC_TYPES_HAS_FLOAT16
+#endif // defined(LIBC_TYPES_HAS_FLOAT16) && !defined(LIBC_USE_SOFT_FLOAT16)
 
 #if defined(__LIBC_USE_BUILTIN_FMAX_FMIN) && !defined(LIBC_TARGET_ARCH_IS_X86)
 template <> LIBC_INLINE constexpr float max(float x, float y) {
@@ -107,8 +105,7 @@ min(T x, T y) {
   return constexpr_min(x, y);
 }
 
-#ifdef LIBC_TYPES_HAS_FLOAT16
-#if !defined(LIBC_USE_SOFT_FLOAT16)
+#if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(LIBC_USE_SOFT_FLOAT16)
 #if defined(__LIBC_USE_BUILTIN_FMAXF16_FMINF16)
 template <> LIBC_INLINE constexpr float16 min(float16 x, float16 y) {
   if (cpp::is_constant_evaluated())
@@ -125,8 +122,7 @@ template <> LIBC_INLINE constexpr float16 min(float16 x, float16 y) {
   return ((xi < yi) != (xi < 0 && yi < 0)) ? x : y;
 }
 #endif
-#endif // !LIBC_USE_SOFT_FLOAT16
-#endif // LIBC_TYPES_HAS_FLOAT16
+#endif // defined(LIBC_TYPES_HAS_FLOAT16) && !defined(LIBC_USE_SOFT_FLOAT16)
 
 #if defined(__LIBC_USE_BUILTIN_FMAX_FMIN) && !defined(LIBC_TARGET_ARCH_IS_X86)
 template <> LIBC_INLINE constexpr float min(float x, float y) {
diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 2f86adc9b745e..299299fb166ca 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -43,24 +43,6 @@ add_header_library(
     libc.src.__support.uint128
 )
 
-add_header_library(
-  Float16
-  HDRS
-    Float16.h
-  DEPENDS
-    .cast
-    .comparison_operations
-    .dyadic_float
-    libc.hdr.stdint_proxy
-    libc.src.__support.CPP.bit
-    libc.src.__support.CPP.type_traits
-    libc.src.__support.FPUtil.generic.add_sub
-    libc.src.__support.FPUtil.generic.div
-    libc.src.__support.FPUtil.generic.mul
-    libc.src.__support.macros.config
-    libc.src.__support.macros.properties.types
-)
-
 add_header_library(
   fpbits_str
   HDRS
@@ -294,6 +276,25 @@ add_header_library(
     libc.src.__support.macros.properties.types
 )
 
+add_header_library(
+  float16
+  HDRS
+    float16.h
+  DEPENDS
+    .cast
+    .comparison_operations
+    .dyadic_float
+    libc.hdr.stdint_proxy
+    libc.src.__support.CPP.bit
+    libc.src.__support.CPP.type_traits
+    libc.src.__support.FPUtil.generic.add_sub
+    libc.src.__support.FPUtil.generic.div
+    libc.src.__support.FPUtil.generic.mul
+    libc.src.__support.macros.attributes
+    libc.src.__support.macros.config
+    libc.src.__support.macros.properties.types
+)
+
 add_header_library(
   bfloat16
   HDRS
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 83219b7573f46..4567144b6a3b2 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -815,6 +815,8 @@ template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
     return FPType::BFloat16;
   else if constexpr (cpp::is_same_v<UnqualT, Float128>)
     return FPType::IEEE754_Binary128;
+  else if constexpr (cpp::is_same_v<UnqualT, Float16>)
+    return FPType::IEEE754_Binary16;
   else
     static_assert(cpp::always_false<UnqualT>, "Unsupported type");
 }
diff --git a/libc/src/__support/FPUtil/cast.h b/libc/src/__support/FPUtil/cast.h
index 4fc5ea0893ebe..f7607b7c67008 100644
--- a/libc/src/__support/FPUtil/cast.h
+++ b/libc/src/__support/FPUtil/cast.h
@@ -33,7 +33,9 @@ cast(InType x) {
     if constexpr (cpp::is_same_v<OutType, bfloat16> ||
                   cpp::is_same_v<InType, bfloat16> ||
                   cpp::is_same_v<OutType, Float128> ||
-                  cpp::is_same_v<InType, Float128>
+                  cpp::is_same_v<InType, Float128> ||
+                  cpp::is_same_v<OutType, Float16> ||
+                  cpp::is_same_v<InType, Float16>
 #if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
                   || cpp::is_same_v<OutType, float16> ||
                   cpp::is_same_v<InType, float16>
@@ -52,12 +54,18 @@ cast(InType x) {
           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();
+        OutStorageType out_mant = 0;
+        if constexpr (InFPBits::FRACTION_LEN > OutFPBits::FRACTION_LEN) {
+          InStorageType in_mant = x_bits.get_mantissa();
+          in_mant >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
+          out_mant = static_cast<OutStorageType>(in_mant);
+        } else if constexpr (InFPBits::FRACTION_LEN < OutFPBits::FRACTION_LEN) {
+          out_mant = static_cast<OutStorageType>(x_bits.get_mantissa());
+          out_mant <<= OutFPBits::FRACTION_LEN - InFPBits::FRACTION_LEN;
+        } else {
+          out_mant = static_cast<OutStorageType>(x_bits.get_mantissa());
+        }
+        return OutFPBits::quiet_nan(x_bits.sign(), out_mant).get_val();
       }
 
       if (x_bits.is_inf())
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 80892701e689a..f55535327e789 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -438,7 +438,8 @@ template <size_t Bits> struct DyadicFloat {
                                             (FPBits<T>::FRACTION_LEN < Bits),
                                         void>>
   LIBC_INLINE LIBC_CONSTEXPR_DEFAULT T as() const {
-    if constexpr (cpp::is_same_v<T, bfloat16> || cpp::is_same_v<T, Float128>
+    if constexpr (cpp::is_same_v<T, bfloat16> || cpp::is_same_v<T, Float128> ||
+                  cpp::is_same_v<T, Float16>
 #if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
                   || cpp::is_same_v<T, float16>
 #endif
diff --git a/libc/src/__support/FPUtil/Float16.h b/libc/src/__support/FPUtil/float16.h
similarity index 68%
rename from libc/src/__support/FPUtil/Float16.h
rename to libc/src/__support/FPUtil/float16.h
index 5387e6a7c1c7a..d1c0981bc240e 100644
--- a/libc/src/__support/FPUtil/Float16.h
+++ b/libc/src/__support/FPUtil/float16.h
@@ -9,10 +9,6 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT16_H
 #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT16_H
 
-#include "src/__support/macros/properties/types.h"
-
-#ifdef LIBC_USE_SOFT_FLOAT16
-
 #include "hdr/stdint_proxy.h"
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/FPUtil/cast.h"
@@ -21,7 +17,9 @@
 #include "src/__support/FPUtil/generic/add_sub.h"
 #include "src/__support/FPUtil/generic/div.h"
 #include "src/__support/FPUtil/generic/mul.h"
+#include "src/__support/macros/attributes.h"
 #include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
 
 namespace LIBC_NAMESPACE_DECL {
 namespace fputil {
@@ -52,6 +50,8 @@ struct Float16 {
 
     } else if constexpr (cpp::is_convertible_v<T, Float16>) {
       bits = value.operator Float16().bits;
+    } else {
+      bits = fputil::cast<Float16>(static_cast<float>(value)).bits;
     }
   }
 
@@ -67,61 +67,74 @@ struct Float16 {
     return static_cast<T>(static_cast<float>(*this));
   }
 
-  LIBC_INLINE bool operator==(Float16 other) const {
+  LIBC_INLINE constexpr bool operator==(Float16 other) const {
     return fputil::equals(*this, other);
   }
 
-  LIBC_INLINE bool operator!=(Float16 other) const {
+  LIBC_INLINE constexpr bool operator!=(Float16 other) const {
     return !fputil::equals(*this, other);
   }
 
-  LIBC_INLINE bool operator<(Float16 other) const {
+  LIBC_INLINE constexpr bool operator<(Float16 other) const {
     return fputil::less_than(*this, other);
   }
 
-  LIBC_INLINE bool operator<=(Float16 other) const {
+  LIBC_INLINE constexpr bool operator<=(Float16 other) const {
     return fputil::less_than_or_equals(*this, other);
   }
 
-  LIBC_INLINE bool operator>(Float16 other) const {
+  LIBC_INLINE constexpr bool operator>(Float16 other) const {
     return fputil::greater_than(*this, other);
   }
 
-  LIBC_INLINE bool operator>=(Float16 other) const {
+  LIBC_INLINE constexpr bool operator>=(Float16 other) const {
     return fputil::greater_than_or_equals(*this, other);
   }
 
-  LIBC_INLINE constexpr Float16 operator-() const {
-    fputil::FPBits<float16> result(*this);
+  LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR Float16 operator-() const {
+    fputil::FPBits<Float16> result(*this);
     result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
     return result.get_val();
   }
 
-  LIBC_INLINE Float16 operator+(Float16 other) const {
+  LIBC_INLINE constexpr Float16 operator+(Float16 other) const {
     return fputil::generic::add<Float16>(*this, other);
   }
 
-  LIBC_INLINE Float16 operator-(Float16 other) const {
+  LIBC_INLINE constexpr Float16 operator-(Float16 other) const {
     return fputil::generic::sub<Float16>(*this, other);
   }
 
-  LIBC_INLINE Float16 operator*(Float16 other) const {
-    return fputil::generic::mul<float16>(*this, other);
+  LIBC_INLINE constexpr Float16 operator*(Float16 other) const {
+    return fputil::generic::mul<Float16>(*this, other);
+  }
+
+  LIBC_INLINE constexpr Float16 operator/(Float16 other) const {
+    return fputil::generic::div<Float16>(*this, other);
+  }
+
+  LIBC_INLINE constexpr Float16 &operator+=(Float16 other) {
+    *this = *this + other;
+    return *this;
   }
 
-  LIBC_INLINE Float16 operator/(Float16 other) const {
-    return fputil::generic::div<float16>(*this, other);
+  LIBC_INLINE constexpr Float16 &operator-=(Float16 other) {
+    *this = *this - other;
+    return *this;
   }
 
-  LIBC_INLINE Float16 &operator*=(const Float16 &other) {
+  LIBC_INLINE constexpr Float16 &operator*=(Float16 other) {
     *this = *this * other;
     return *this;
   }
+
+  LIBC_INLINE constexpr Float16 &operator/=(Float16 other) {
+    *this = *this / other;
+    return *this;
+  }
 }; // struct Float16
 
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 
-#endif // LIBC_USE_SOFT_FLOAT16
-
 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT16_H
diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h
index 68907507b9ffc..b1dddaf58093f 100644
--- a/libc/src/__support/macros/properties/types.h
+++ b/libc/src/__support/macros/properties/types.h
@@ -49,15 +49,15 @@
 // -- float16 support ---------------------------------------------------------
 // LIBC_TYPES_HAS_FLOAT16 is provided by
 // "include/llvm-libc-macros/float16-macros.h"
-#ifdef LIBC_TYPES_HAS_FLOAT16
-
-#ifdef LIBC_USE_SOFT_FLOAT16
 namespace LIBC_NAMESPACE_DECL {
 namespace fputil {
 struct Float16;
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#ifdef LIBC_USE_SOFT_FLOAT16
 using float16 = LIBC_NAMESPACE::fputil::Float16;
 #else
 // Type alias for internal use.
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index baed5ad3ffea9..765664abe2168 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -3236,7 +3236,7 @@ add_header_library(
     fabsf16.h
   DEPENDS
     libc.include.llvm-libc-macros.float16_macros
-    libc.src.__support.FPUtil.Float16
+    libc.src.__support.FPUtil.float16
     libc.src.__support.FPUtil.basic_operations
     libc.src.__support.macros.config
   FLAGS
diff --git a/libc/src/__support/math/fabsf16.h b/libc/src/__support/math/fabsf16.h
index ca568c680b7c2..65b786fd77331 100644
--- a/libc/src/__support/math/fabsf16.h
+++ b/libc/src/__support/math/fabsf16.h
@@ -14,7 +14,7 @@
 #ifdef LIBC_TYPES_HAS_FLOAT16
 
 #include "src/__support/FPUtil/BasicOperations.h"
-#include "src/__support/FPUtil/Float16.h"
+#include "src/__support/FPUtil/float16.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/properties/architectures.h"
 #include "src/__support/macros/properties/compiler.h"
diff --git a/libc/test/src/__support/FPUtil/CMakeLists.txt b/libc/test/src/__support/FPUtil/CMakeLists.txt
index 87fd10aaacd90..1a85391234206 100644
--- a/libc/test/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/test/src/__support/FPUtil/CMakeLists.txt
@@ -58,6 +58,17 @@ if(LLVM_LIBC_FULL_BUILD)
   return()
 endif()
 
+add_fp_unittest(
+  float16_test
+  NEED_MPFR
+  SUITE
+    libc-fputil-tests
+  SRCS
+    float16_test.cpp
+  DEPENDS
+    libc.src.__support.FPUtil.float16
+)
+
 add_fp_unittest(
   bfloat16_test
   NEED_MPFR
diff --git a/libc/test/src/__support/FPUtil/float16_test.cpp b/libc/test/src/__support/FPUtil/float16_test.cpp
new file mode 100644
index 0000000000000..203e22c580692
--- /dev/null
+++ b/libc/test/src/__support/FPUtil/float16_test.cpp
@@ -0,0 +1,124 @@
+//===-- Unit tests for float16 type ---------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/FPUtil/float16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPCommon.h"
+
+using Float16 = LIBC_NAMESPACE::fputil::Float16;
+using LlvmLibcFloat16ConversionTest =
+    LIBC_NAMESPACE::testing::FPTest<Float16>;
+
+// range: [0, inf]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7c00U;
+
+// range: [-0, -inf]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xfc00U;
+
+using MPFRNumber = LIBC_NAMESPACE::testing::mpfr::MPFRNumber;
+
+TEST_F(LlvmLibcFloat16ConversionTest, ToFloatPositiveRange) {
+  for (uint16_t bits = POS_START; bits <= POS_STOP; bits++) {
+    Float16 f16_num{bits};
+    MPFRNumber mpfr_num{f16_num};
+
+    // float16 to float
+    float mpfr_float = mpfr_num.as<float>();
+    EXPECT_FP_EQ_ALL_ROUNDING(mpfr_float, static_cast<float>(f16_num));
+
+    // float to float16
+    Float16 f16_from_float{mpfr_float};
+    MPFRNumber mpfr_num_2{mpfr_float};
+    Float16 mpfr_f16 = mpfr_num_2.as<Float16>();
+    EXPECT_FP_EQ_ALL_ROUNDING(mpfr_f16, f16_from_float);
+  }
+}
+
+TEST_F(LlvmLibcFloat16ConversionTest, ToFloatNegativeRange) {
+  for (uint16_t bits = NEG_START; bits <= NEG_STOP; bits++) {
+    Float16 f16_num{bits};
+    MPFRNumber mpfr_num{f16_num};
+
+    // float16 to float
+    float mpfr_float = mpfr_num.as<float>();
+    EXPECT_FP_EQ_ALL_ROUNDING(mpfr_float, static_cast<float>(f16_num));
+
+    // float to float16
+    Float16 f16_from_float{mpfr_float};
+    MPFRNumber mpfr_num_2{mpfr_float};
+    Float16 mpfr_f16 = mpfr_num_2.as<Float16>();
+    EXPECT_FP_EQ_ALL_ROUNDING(mpfr_f16, f16_from_float);
+  }
+}
+
+TEST_F(LlvmLibcFloat16ConversionTest, FromInteger) {
+  constexpr int RANGE = 1'234;
+  for (int i = -RANGE; i <= RANGE; i++) {
+    Float16 mpfr_f16 = MPFRNumber(i).as<Float16>();
+    Float16 libc_f16{i};
+    EXPECT_FP_EQ_ALL_ROUNDING(mpfr_f16, libc_f16);
+  }
+}
+
+TEST_F(LlvmLibcFloat16ConversionTest, CompoundAssignmentOperators) {
+  constexpr Float16 VAL[] = {zero,           neg_zero,        inf,
+                             neg_inf,        min_normal,      max_normal,
+                             Float16(1.0f),  Float16(-1.0f),  Float16(2.0f),
+                             Float16(3.0f)};
+  // *=
+  for (const Float16 &x : VAL) {
+    for (const Float16 &y : VAL) {
+      Float16 a = x, b = y;
+      MPFRNumber mpfr_a{a}, mpfr_b{b};
+      MPFRNumber mpfr_c = mpfr_a.mul(mpfr_b);
+      Float16 mpfr_f16 = mpfr_c.as<Float16>();
+      a *= b;
+      Float16 libc_f16 = a;
+      EXPECT_FP_EQ_ALL_ROUNDING(mpfr_f16, libc_f16);
+    }
+  }
+  // /=
+  for (const Float16 &x : VAL) {
+    for (const Float16 &y : VAL) {
+      Float16 a = x, b = y;
+      MPFRNumber mpfr_a{a}, mpfr_b{b};
+      MPFRNumber mpfr_c = mpfr_a.div(mpfr_b);
+      Float16 mpfr_f16 = mpfr_c.as<Float16>();
+      a /= b;
+      Float16 libc_f16 = a;
+      EXPECT_FP_EQ_ALL_ROUNDING(mpfr_f16, libc_f16);
+    }
+  }
+  // +=
+  for (const Float16 &x : VAL) {
+    for (const Float16 &y : VAL) {
+      Float16 a = x, b = y;
+      MPFRNumber mpfr_a{a}, mpfr_b{b};
+      MPFRNumber mpfr_c = mpfr_a.add(mpfr_b);
+      Float16 mpfr_f16 = mpfr_c.as<Float16>();
+      a += b;
+      Float16 libc_f16 = a;
+      EXPECT_FP_EQ_ALL_ROUNDING(mpfr_f16, libc_f16);
+    }
+  }
+  // -=
+  for (const Float16 &x : VAL) {
+    for (const Float16 &y : VAL) {
+      Float16 a = x, b = y;
+      MPFRNumber mpfr_a{a}, mpfr_b{b};
+      MPFRNumber mpfr_c = mpfr_a.sub(mpfr_b);
+      Float16 mpfr_f16 = mpfr_c.as<Float16>();
+      a -= b;
+      Float16 libc_f16 = a;
+      EXPECT_FP_EQ_ALL_ROUNDING(mpfr_f16, libc_f16);
+    }
+  }
+}
diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index 97355fbbf0278..dbe8f7bbe2829 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -723,7 +723,7 @@ add_fp_unittest(
     float16_test.cpp
   DEPENDS
     .exhaustive_test
-    libc.src.__support.FPUtil.Float16
+    libc.src.__support.FPUtil.float16
     libc.src.__support.FPUtil.cast
     libc.src.__support.FPUtil.fp_bits
   LINK_LIBRARIES
diff --git a/libc/test/src/math/exhaustive/exhaustive_test.h b/libc/test/src/math/exhaustive/exhaustive_test.h
index 04d43214e00a2..fd6452a976eb1 100644
--- a/libc/test/src/math/exhaustive/exhaustive_test.h
+++ b/libc/test/src/math/exhaustive/exhaustive_test.h
@@ -8,7 +8,7 @@
 
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/Float16.h"
+#include "src/__support/FPUtil/float16.h"
 #include "src/__support/macros/properties/types.h"
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 8e670ad2a2851..1c60fb5191683 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -229,7 +229,7 @@ add_fp_unittest(
     FAbsTest.h
   DEPENDS
     libc.src.math.fabsf16
-    libc.src.__support.FPUtil.Float16
+    libc.src.__support.FPUtil.float16
 )
 
 add_fp_unittest(
diff --git a/libc/test/src/math/smoke/fabsf16_test.cpp b/libc/test/src/math/smoke/fabsf16_test.cpp
index d4d6dd1d2593a..c7bab4b305f99 100644
--- a/libc/test/src/math/smoke/fabsf16_test.cpp
+++ b/libc/test/src/math/smoke/fabsf16_test.cpp
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "FAbsTest.h"
-#include "src/__support/FPUtil/Float16.h"
+#include "src/__support/FPUtil/float16.h"
 #include "src/math/fabsf16.h"
 
 LIST_FABS_TESTS(float16, LIBC_NAMESPACE::fabsf16)
diff --git a/libc/utils/MPFRWrapper/CMakeLists.txt b/libc/utils/MPFRWrapper/CMakeLists.txt
index a1546992ce21c..f90e1007da529 100644
--- a/libc/utils/MPFRWrapper/CMakeLists.txt
+++ b/libc/utils/MPFRWrapper/CMakeLists.txt
@@ -14,7 +14,7 @@ if(LIBC_TESTS_CAN_USE_MPFR OR LIBC_TESTS_CAN_USE_MPC)
     libc.src.__support.CPP.string
     libc.src.__support.CPP.string_view
     libc.src.__support.CPP.type_traits
-    libc.src.__support.FPUtil.Float16
+    libc.src.__support.FPUtil.float16
     libc.src.__support.FPUtil.bfloat16
     libc.src.__support.FPUtil.cast
     libc.src.__support.FPUtil.fp_bits
@@ -44,7 +44,7 @@ if(LIBC_TESTS_CAN_USE_MPFR)
     libc.hdr.stdint_proxy
     libc.src.__support.CPP.array
     libc.src.__support.CPP.stringstream
-    libc.src.__support.FPUtil.Float16
+    libc.src.__support.FPUtil.float16
     libc.src.__support.FPUtil.bfloat16
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.fpbits_str
diff --git a/libc/utils/MPFRWrapper/MPCommon.cpp b/libc/utils/MPFRWrapper/MPCommon.cpp
index 4847f03d1cbfa..0393ce6421ca7 100644
--- a/libc/utils/MPFRWrapper/MPCommon.cpp
+++ b/libc/utils/MPFRWrapper/MPCommon.cpp
@@ -10,11 +10,7 @@
 
 #include "src/__support/CPP/string_view.h"
 #include "src/__support/FPUtil/bfloat16.h"
-
-#ifdef LIBC_USE_SOFT_FLOAT16
-#include "src/__support/FPUtil/Float16.h"
-#endif
-
+#include "src/__support/FPUtil/float16.h"
 #include "src/__support/FPUtil/cast.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/properties/types.h"
@@ -637,7 +633,7 @@ template <> long double MPFRNumber::as<long double>() const {
   return mpfr_get_ld(value, mpfr_rounding);
 }
 
-#if defined(LIBC_TYPES_HAS_FLOAT16) || defined(LIBC_USE_SOFT_FLOAT16)
+#ifdef LIBC_TYPES_HAS_FLOAT16
 template <> float16 MPFRNumber::as<float16>() const {
   // TODO: Either prove that this cast won't cause double-rounding errors, or
   // find a better way to get a float16.
@@ -645,6 +641,12 @@ template <> float16 MPFRNumber::as<float16>() const {
 }
 #endif
 
+#if !defined(LIBC_USE_SOFT_FLOAT16)
+template <> fputil::Float16 MPFRNumber::as<fputil::Float16>() const {
+  return fputil::cast<fputil::Float16>(mpfr_get_d(value, mpfr_rounding));
+}
+#endif
+
 #ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
 template <> float128 MPFRNumber::as<float128>() const {
   return mpfr_get_float128(value, mpfr_rounding);
diff --git a/libc/utils/MPFRWrapper/MPCommon.h b/libc/utils/MPFRWrapper/MPCommon.h
index 38fd15fcc956c..32a6a3ee47fca 100644
--- a/libc/utils/MPFRWrapper/MPCommon.h
+++ b/libc/utils/MPFRWrapper/MPCommon.h
@@ -65,6 +65,12 @@ template <> struct ExtraPrecision<float128> {
 };
 #endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
 
+#if !defined(LIBC_USE_SOFT_FLOAT16)
+template <> struct ExtraPrecision<LIBC_NAMESPACE::fputil::Float16> {
+  static constexpr unsigned int VALUE = 128;
+};
+#endif
+
 template <> struct ExtraPrecision<bfloat16> {
   static constexpr unsigned int VALUE = 64;
 };
@@ -115,6 +121,9 @@ class MPFRNumber {
             cpp::enable_if_t<cpp::is_same_v<float, XType>
 #ifdef LIBC_TYPES_HAS_FLOAT16
                                  || cpp::is_same_v<float16, XType>
+#endif
+#if !defined(LIBC_USE_SOFT_FLOAT16)
+                                 || cpp::is_same_v<LIBC_NAMESPACE::fputil::Float16, XType>
 #endif
                                  || cpp::is_same_v<bfloat16, XType>,
                              int> = 0>
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index b928edeebba4b..5c9471af1c5a5 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -11,7 +11,7 @@
 
 #include "src/__support/CPP/array.h"
 #include "src/__support/CPP/stringstream.h"
-#include "src/__support/FPUtil/Float16.h"
+#include "src/__support/FPUtil/float16.h"
 #include "src/__support/FPUtil/bfloat16.h"
 #include "src/__support/FPUtil/fpbits_str.h"
 #include "src/__support/macros/config.h"

>From 43dcaed51c2a68c799a5e22a618a37a2935e1cb0 Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Sat, 29 Aug 2026 05:52:21 +0300
Subject: [PATCH 3/3] Make soft float16 emulation the default behavior

---
 libc/config/baremetal/aarch64/entrypoints.txt             | 2 +-
 libc/config/baremetal/arm/entrypoints.txt                 | 2 +-
 libc/config/baremetal/riscv/entrypoints.txt               | 2 +-
 libc/config/darwin/aarch64/entrypoints.txt                | 2 +-
 libc/config/freebsd/x86_64/entrypoints.txt                | 2 +-
 libc/config/linux/aarch64/entrypoints.txt                 | 2 +-
 libc/config/linux/arm/entrypoints.txt                     | 1 +
 libc/config/linux/riscv/entrypoints.txt                   | 2 +-
 libc/config/linux/x86_64/entrypoints.txt                  | 2 +-
 libc/config/windows/entrypoints.txt                       | 1 +
 libc/include/llvm-libc-macros/float16-macros.h            | 8 ++++----
 libc/src/__support/FPUtil/float16.h                       | 4 ++++
 libc/src/__support/math/fabsf16.h                         | 7 +------
 libc/test/src/__support/FPUtil/CMakeLists.txt             | 2 ++
 .../src/__support/FPUtil/comparison_operations_test.cpp   | 1 +
 libc/test/src/__support/FPUtil/dyadic_float_test.cpp      | 1 +
 16 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 93808e4c471fc..72a33d15bd9c3 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -398,6 +398,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.expm1f
     libc.src.math.fabs
     libc.src.math.fabsf
+    libc.src.math.fabsf16
     libc.src.math.fabsl
     libc.src.math.fadd
     libc.src.math.faddl
@@ -637,7 +638,6 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.f16sub
     libc.src.math.f16subf
     libc.src.math.f16subl
-    libc.src.math.fabsf16
     libc.src.math.fdimf16
     libc.src.math.floorf16
     libc.src.math.fmaf16
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 71ecbe438bf7b..566a0e40582f1 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -410,6 +410,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.expm1f
     libc.src.math.fabs
     libc.src.math.fabsf
+    libc.src.math.fabsf16
     libc.src.math.fabsl
     libc.src.math.fadd
     libc.src.math.faddl
@@ -649,7 +650,6 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.f16sub
     libc.src.math.f16subf
     libc.src.math.f16subl
-    libc.src.math.fabsf16
     libc.src.math.fdimf16
     libc.src.math.floorf16
     libc.src.math.fmaf16
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index b38f60ab9d5f5..50172348ca048 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -406,6 +406,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.expm1f
     libc.src.math.fabs
     libc.src.math.fabsf
+    libc.src.math.fabsf16
     libc.src.math.fabsl
     libc.src.math.fadd
     libc.src.math.faddl
@@ -645,7 +646,6 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.f16sub
     libc.src.math.f16subf
     libc.src.math.f16subl
-    libc.src.math.fabsf16
     libc.src.math.fdimf16
     libc.src.math.floorf16
     libc.src.math.fmaf16
diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt
index 15adad72ab459..cf25a76391ae7 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -217,6 +217,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.expm1f
     libc.src.math.fabs
     libc.src.math.fabsf
+    libc.src.math.fabsf16
     libc.src.math.fabsl
     libc.src.math.fadd
     libc.src.math.faddl
@@ -457,7 +458,6 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.f16sub
     libc.src.math.f16subf
     libc.src.math.f16subl
-    libc.src.math.fabsf16
     libc.src.math.fdimf16
     libc.src.math.floorf16
     libc.src.math.fmaf16
diff --git a/libc/config/freebsd/x86_64/entrypoints.txt b/libc/config/freebsd/x86_64/entrypoints.txt
index df6c0f907725b..140a0829cea3a 100644
--- a/libc/config/freebsd/x86_64/entrypoints.txt
+++ b/libc/config/freebsd/x86_64/entrypoints.txt
@@ -153,6 +153,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.expm1f
     libc.src.math.fabs
     libc.src.math.fabsf
+    libc.src.math.fabsf16
     libc.src.math.fabsl
     libc.src.math.fadd
     libc.src.math.faddl
@@ -407,7 +408,6 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.f16sub
     libc.src.math.f16subf
     libc.src.math.f16subl
-    libc.src.math.fabsf16
     libc.src.math.fdimf16
     libc.src.math.floorf16
     libc.src.math.fmaf16
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 1ccb6cf202cf7..7efc7f799c425 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -545,6 +545,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.expm1f
     libc.src.math.fabs
     libc.src.math.fabsf
+    libc.src.math.fabsf16
     libc.src.math.fabsl
     libc.src.math.fadd
     libc.src.math.faddl
@@ -774,7 +775,6 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.f16sub
     libc.src.math.f16subf
     # libc.src.math.f16subl
-    libc.src.math.fabsf16
     libc.src.math.fdimf16
     libc.src.math.fdiv
     libc.src.math.fdivl
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 608b50843b94a..a7a4a34736890 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -332,6 +332,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.expm1f
     libc.src.math.fabs
     libc.src.math.fabsf
+    libc.src.math.fabsf16
     libc.src.math.fabsl
     libc.src.math.fadd
     libc.src.math.faddl
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 5083417b453be..6702012d2fd28 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -616,6 +616,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.expm1f
     libc.src.math.fabs
     libc.src.math.fabsf
+    libc.src.math.fabsf16
     libc.src.math.fabsl
     libc.src.math.fadd
     libc.src.math.faddl
@@ -863,7 +864,6 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.f16sub
     libc.src.math.f16subf
     libc.src.math.f16subl
-    libc.src.math.fabsf16
     libc.src.math.fdimf16
     libc.src.math.floorf16
     libc.src.math.fmaf16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index bf809e268f585..350239779d00a 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -621,6 +621,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.expm1f
     libc.src.math.fabs
     libc.src.math.fabsf
+    libc.src.math.fabsf16
     libc.src.math.fabsl
     libc.src.math.fadd
     libc.src.math.faddl
@@ -868,7 +869,6 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.f16sub
     libc.src.math.f16subf
     libc.src.math.f16subl
-    libc.src.math.fabsf16
     libc.src.math.fdimf16
     libc.src.math.floorf16
     libc.src.math.fmaf16
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 5333bc4042070..5b40867b54b81 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -185,6 +185,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.expm1f
     libc.src.math.fabs
     libc.src.math.fabsf
+    libc.src.math.fabsf16
     libc.src.math.fabsl
     libc.src.math.fadd
     libc.src.math.faddl
diff --git a/libc/include/llvm-libc-macros/float16-macros.h b/libc/include/llvm-libc-macros/float16-macros.h
index 5a1a9cdd311f8..0a537388cc31a 100644
--- a/libc/include/llvm-libc-macros/float16-macros.h
+++ b/libc/include/llvm-libc-macros/float16-macros.h
@@ -11,7 +11,7 @@
 
 #include "../llvm-libc-types/float128.h"
 
-#if (defined(__arm__) && defined(_M_ARM)) || defined(__riscv)
+#ifndef LIBC_DONT_USE_SOFT_FLOAT16
 #define LIBC_USE_SOFT_FLOAT16
 #endif
 
@@ -24,12 +24,12 @@
      (defined(__clang__) && __clang_major__ >= 12)) &&                         \
     !defined(__riscv) && !defined(_WIN32)
 #define LIBC_TYPES_HAS_FLOAT16
+#endif
 
 // TODO: This would no longer be required if HdrGen let us guard function
 // declarations with multiple macros.
-#ifdef LIBC_TYPES_HAS_FLOAT128
+#if defined(LIBC_TYPES_HAS_FLOAT16) && defined(LIBC_TYPES_HAS_FLOAT128)
 #define LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128
-#endif // LIBC_TYPES_HAS_FLOAT128
-#endif
+#endif // LIBC_TYPES_HAS_FLOAT16 && LIBC_TYPES_HAS_FLOAT128
 
 #endif // LLVM_LIBC_MACROS_FLOAT16_MACROS_H
diff --git a/libc/src/__support/FPUtil/float16.h b/libc/src/__support/FPUtil/float16.h
index d1c0981bc240e..21349d682c826 100644
--- a/libc/src/__support/FPUtil/float16.h
+++ b/libc/src/__support/FPUtil/float16.h
@@ -29,6 +29,10 @@ struct Float16 {
 
   LIBC_INLINE Float16() = default;
 
+  template <size_t Bits>
+  LIBC_INLINE constexpr explicit Float16(const DyadicFloat<Bits> &df)
+      : bits(df.template as<Float16, /*ShouldSignalExceptions=*/false>().bits) {}
+
   template <typename T>
   LIBC_INLINE constexpr explicit Float16(T value)
       : bits(static_cast<uint16_t>(0U)) {
diff --git a/libc/src/__support/math/fabsf16.h b/libc/src/__support/math/fabsf16.h
index 65b786fd77331..afbc662c5a40c 100644
--- a/libc/src/__support/math/fabsf16.h
+++ b/libc/src/__support/math/fabsf16.h
@@ -9,15 +9,12 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_MATH_FABSF16_H
 #define LLVM_LIBC_SRC___SUPPORT_MATH_FABSF16_H
 
-#include "include/llvm-libc-macros/float16-macros.h"
-
-#ifdef LIBC_TYPES_HAS_FLOAT16
-
 #include "src/__support/FPUtil/BasicOperations.h"
 #include "src/__support/FPUtil/float16.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/properties/architectures.h"
 #include "src/__support/macros/properties/compiler.h"
+#include "src/__support/macros/properties/types.h"
 
 namespace LIBC_NAMESPACE_DECL {
 namespace math {
@@ -39,6 +36,4 @@ LIBC_INLINE constexpr float16 fabsf16(float16 x) {
 } // namespace math
 } // namespace LIBC_NAMESPACE_DECL
 
-#endif // LIBC_TYPES_HAS_FLOAT16
-
 #endif // LLVM_LIBC_SRC___SUPPORT_MATH_FABSF16_H
diff --git a/libc/test/src/__support/FPUtil/CMakeLists.txt b/libc/test/src/__support/FPUtil/CMakeLists.txt
index 1a85391234206..bb5b849ceeef7 100644
--- a/libc/test/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/test/src/__support/FPUtil/CMakeLists.txt
@@ -9,6 +9,7 @@ add_fp_unittest(
     dyadic_float_test.cpp
   DEPENDS
     libc.src.__support.FPUtil.dyadic_float
+    libc.src.__support.FPUtil.float16
     libc.src.__support.macros.properties.types
   COMPILE_OPTIONS
     # Prevent constant folding with a default rounding mode.
@@ -89,5 +90,6 @@ add_fp_unittest(
   DEPENDS
     libc.src.__support.FPUtil.bfloat16
     libc.src.__support.FPUtil.comparison_operations
+    libc.src.__support.FPUtil.float16
     libc.src.__support.macros.properties.types
 )
diff --git a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
index 681b686c2acf0..0580ea848968e 100644
--- a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
+++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
@@ -8,6 +8,7 @@
 
 #include "src/__support/FPUtil/bfloat16.h"
 #include "src/__support/FPUtil/comparison_operations.h"
+#include "src/__support/FPUtil/float16.h"
 #include "src/__support/macros/properties/types.h"
 #include "test/UnitTest/FEnvSafeTest.h"
 #include "test/UnitTest/FPMatcher.h"
diff --git a/libc/test/src/__support/FPUtil/dyadic_float_test.cpp b/libc/test/src/__support/FPUtil/dyadic_float_test.cpp
index 720b426033dff..2dc670d814c5a 100644
--- a/libc/test/src/__support/FPUtil/dyadic_float_test.cpp
+++ b/libc/test/src/__support/FPUtil/dyadic_float_test.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/__support/FPUtil/dyadic_float.h"
+#include "src/__support/FPUtil/float16.h"
 #include "src/__support/big_int.h"
 #include "src/__support/macros/properties/types.h"
 #include "test/UnitTest/FPMatcher.h"



More information about the libc-commits mailing list