[llvm-branch-commits] [libc] [libc] Add Operator Overloads for Float80 (PR #214493)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Aug 24 19:55:09 PDT 2026


https://github.com/Sukumarsawant updated https://github.com/llvm/llvm-project/pull/214493

>From 2c922cc0b6e67c32f30544e165430ce29ffa731b Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 23 Jul 2026 00:10:21 +0530
Subject: [PATCH 01/16] initial temp skeleton

---
 libc/src/__support/FPUtil/float80.h | 90 ++++++++++++++++++++++++-----
 1 file changed, 74 insertions(+), 16 deletions(-)

diff --git a/libc/src/__support/FPUtil/float80.h b/libc/src/__support/FPUtil/float80.h
index 4529fe396a6dc..119f592d6ca41 100644
--- a/libc/src/__support/FPUtil/float80.h
+++ b/libc/src/__support/FPUtil/float80.h
@@ -69,34 +69,92 @@ struct Float80 {
 
   template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
   LIBC_INLINE constexpr explicit operator T() const {
-    constexpr T MIN_T = cpp::numeric_limits<T>::min();
-    constexpr T MAX_T = cpp::numeric_limits<T>::max();
     FPBits<Float80> x_bits(*this);
     // Raise FE_INVALID for inf and NaN
     if (x_bits.is_inf_or_nan()) {
       raise_except_if_required(FE_INVALID);
-      return x_bits.is_neg() ? MIN_T : MAX_T;
     }
-    int exponent = x_bits.get_explicit_exponent();
-    constexpr int EXPONENT_LIMIT = cpp::numeric_limits<T>::digits;
-    if (exponent > EXPONENT_LIMIT) {
-      raise_except_if_required(FE_INVALID);
-      return x_bits.is_neg() ? MIN_T : MAX_T;
-    } else if (exponent == EXPONENT_LIMIT) {
-      if (x_bits.is_pos() || x_bits.get_mantissa() != 0) {
-        raise_except_if_required(FE_INVALID);
-        return x_bits.is_neg() ? MIN_T : MAX_T;
-      }
-    }
-
-    int x_bits_exp = exponent - FPBits<Float80>::FRACTION_LEN;
+    int x_bits_exp =
+        x_bits.get_explicit_exponent() - FPBits<Float80>::FRACTION_LEN;
     // sign * 2^(exp-bias) * mantissa
     DyadicFloat<FPBits<Float80>::STORAGE_LEN> xd(
         x_bits.sign(), x_bits_exp, x_bits.get_explicit_mantissa());
     return static_cast<T>(xd.as_mantissa_type());
   }
+
+  // unary
+  LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR Float80 operator-() const {
+    fputil::FPBits<Float80> result(*this);
+    result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
+    return result.get_val();
+  }
+  // operator overloads
+  LIBC_INLINE constexpr Float80 operator+(const Float80 &other) const {
+    return fputil::generic::add<Float80>(*this, other);
+  }
+
+  LIBC_INLINE constexpr Float80 operator-(const Float80 &other) const {
+    return fputil::generic::sub<Float80>(*this, other);
+  }
+
+  LIBC_INLINE constexpr Float80 operator*(const Float80 &other) const {
+    return fputil::generic::mul<Float80>(*this, other);
+  }
+
+  LIBC_INLINE constexpr Float80 operator/(const Float80 &other) const {
+    return fputil::generic::div<Float80>(*this, other);
+  }
+
+  LIBC_INLINE constexpr Float80 &operator*=(const Float80 &other) {
+    *this = *this * other;
+    return *this;
+  }
+
+  LIBC_INLINE constexpr Float80 &operator+=(const Float80 &other) {
+    *this = *this + other;
+    return *this;
+  }
+
+  LIBC_INLINE constexpr Float80 &operator-=(const Float80 &other) {
+    *this = *this - other;
+    return *this;
+  }
+
+  LIBC_INLINE constexpr Float80 &operator/=(const Float80 &other) {
+    *this = *this / other;
+    return *this;
+  }
+
+  LIBC_INLINE constexpr bool operator==(const Float80 &other) const {
+    return fputil::equals(*this, other);
+  }
+
+  LIBC_INLINE constexpr bool operator!=(const Float80 &other) const {
+    return !fputil::equals(*this, other);
+  }
+
+  LIBC_INLINE constexpr bool operator<(const Float80 &other) const {
+    return fputil::less_than(*this, other);
+  }
+
+  LIBC_INLINE constexpr bool operator<=(const Float80 &other) const {
+    return fputil::less_than_or_equals(*this, other);
+  }
+
+  LIBC_INLINE constexpr bool operator>(const Float80 &other) const {
+    return fputil::greater_than(*this, other);
+  }
+
+  LIBC_INLINE constexpr bool operator>=(const Float80 &other) const {
+    return fputil::greater_than_or_equals(*this, other);
+  }
 };
 
+static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible<
+              LIBC_NAMESPACE::fputil::Float80>::value);
+static_assert(LIBC_NAMESPACE::cpp::is_trivially_copyable<
+              LIBC_NAMESPACE::fputil::Float80>::value);
+
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 

>From 3599d8af14b23d40d2f533b25217e62e67c92c28 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 30 Jul 2026 20:30:14 +0530
Subject: [PATCH 02/16] Removed temporarliy for 128bit container only

---
 libc/src/__support/FPUtil/FPBits.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 6127dede03f4a..e251b7f15e9a3 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -127,11 +127,11 @@ template <> struct FPLayout<FPType::IEEE754_Binary128> {
 };
 
 template <> struct FPLayout<FPType::X86_Binary80> {
-#if __SIZEOF_LONG_DOUBLE__ == 12
-  using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
-#else
+// #if __SIZEOF_LONG_DOUBLE__ == 12
+//   using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
+// #else
   using StorageType = UInt128;
-#endif
+// #endif
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
   LIBC_INLINE_VAR static constexpr int EXP_LEN = 15;
   LIBC_INLINE_VAR static constexpr int SIG_LEN = 64;

>From 3cc275d947af195923cbc0d4d48cd784f1aeba19 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 30 Jul 2026 20:36:32 +0530
Subject: [PATCH 03/16] test

---
 libc/src/__support/FPUtil/FPBits.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index e251b7f15e9a3..59d3ca28c7dc4 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -127,11 +127,11 @@ template <> struct FPLayout<FPType::IEEE754_Binary128> {
 };
 
 template <> struct FPLayout<FPType::X86_Binary80> {
-// #if __SIZEOF_LONG_DOUBLE__ == 12
-//   using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
-// #else
+  // #if __SIZEOF_LONG_DOUBLE__ == 12
+  //   using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
+  // #else
   using StorageType = UInt128;
-// #endif
+  // #endif
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
   LIBC_INLINE_VAR static constexpr int EXP_LEN = 15;
   LIBC_INLINE_VAR static constexpr int SIG_LEN = 64;

>From b76b05b8e4ac91bc34d660398b92a5e1013efab3 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 13:10:13 +0530
Subject: [PATCH 04/16] nit

---
 libc/src/__support/FPUtil/FPBits.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 59d3ca28c7dc4..1b5f76b3f1d17 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -127,11 +127,11 @@ template <> struct FPLayout<FPType::IEEE754_Binary128> {
 };
 
 template <> struct FPLayout<FPType::X86_Binary80> {
-  // #if __SIZEOF_LONG_DOUBLE__ == 12
-  //   using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
-  // #else
+  #if __SIZEOF_LONG_DOUBLE__ == 12
+    using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
+  #else
   using StorageType = UInt128;
-  // #endif
+  #endif
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
   LIBC_INLINE_VAR static constexpr int EXP_LEN = 15;
   LIBC_INLINE_VAR static constexpr int SIG_LEN = 64;

>From 37d452acfffe08ad6b6f29bcf4f8d2b1806ffd82 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 13:15:10 +0530
Subject: [PATCH 05/16] formatting

---
 libc/src/__support/FPUtil/FPBits.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 1b5f76b3f1d17..6127dede03f4a 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -127,11 +127,11 @@ template <> struct FPLayout<FPType::IEEE754_Binary128> {
 };
 
 template <> struct FPLayout<FPType::X86_Binary80> {
-  #if __SIZEOF_LONG_DOUBLE__ == 12
-    using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
-  #else
+#if __SIZEOF_LONG_DOUBLE__ == 12
+  using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
+#else
   using StorageType = UInt128;
-  #endif
+#endif
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
   LIBC_INLINE_VAR static constexpr int EXP_LEN = 15;
   LIBC_INLINE_VAR static constexpr int SIG_LEN = 64;

>From fe91cdc224c070c3ff2dbe79f592959c2ffec936 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 15:50:02 +0530
Subject: [PATCH 06/16] feat: add tests

---
 libc/src/__support/FPUtil/float80.h | 85 ++++++-----------------------
 1 file changed, 16 insertions(+), 69 deletions(-)

diff --git a/libc/src/__support/FPUtil/float80.h b/libc/src/__support/FPUtil/float80.h
index 119f592d6ca41..882eec261db15 100644
--- a/libc/src/__support/FPUtil/float80.h
+++ b/libc/src/__support/FPUtil/float80.h
@@ -69,85 +69,32 @@ struct Float80 {
 
   template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
   LIBC_INLINE constexpr explicit operator T() const {
+    constexpr T MIN_T = cpp::numeric_limits<T>::min();
+    constexpr T MAX_T = cpp::numeric_limits<T>::max();
     FPBits<Float80> x_bits(*this);
     // Raise FE_INVALID for inf and NaN
     if (x_bits.is_inf_or_nan()) {
       raise_except_if_required(FE_INVALID);
+      return x_bits.is_neg() ? MIN_T : MAX_T;
     }
-    int x_bits_exp =
-        x_bits.get_explicit_exponent() - FPBits<Float80>::FRACTION_LEN;
+    int exponent = x_bits.get_explicit_exponent();
+    constexpr int EXPONENT_LIMIT = cpp::numeric_limits<T>::digits;
+    if (exponent > EXPONENT_LIMIT) {
+      raise_except_if_required(FE_INVALID);
+      return x_bits.is_neg() ? MIN_T : MAX_T;
+    } else if (exponent == EXPONENT_LIMIT) {
+      if (x_bits.is_pos() || x_bits.get_mantissa() != 0) {
+        raise_except_if_required(FE_INVALID);
+        return x_bits.is_neg() ? MIN_T : MAX_T;
+      }
+    }
+
+    int x_bits_exp = exponent - FPBits<Float80>::FRACTION_LEN;
     // sign * 2^(exp-bias) * mantissa
     DyadicFloat<FPBits<Float80>::STORAGE_LEN> xd(
         x_bits.sign(), x_bits_exp, x_bits.get_explicit_mantissa());
     return static_cast<T>(xd.as_mantissa_type());
   }
-
-  // unary
-  LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR Float80 operator-() const {
-    fputil::FPBits<Float80> result(*this);
-    result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
-    return result.get_val();
-  }
-  // operator overloads
-  LIBC_INLINE constexpr Float80 operator+(const Float80 &other) const {
-    return fputil::generic::add<Float80>(*this, other);
-  }
-
-  LIBC_INLINE constexpr Float80 operator-(const Float80 &other) const {
-    return fputil::generic::sub<Float80>(*this, other);
-  }
-
-  LIBC_INLINE constexpr Float80 operator*(const Float80 &other) const {
-    return fputil::generic::mul<Float80>(*this, other);
-  }
-
-  LIBC_INLINE constexpr Float80 operator/(const Float80 &other) const {
-    return fputil::generic::div<Float80>(*this, other);
-  }
-
-  LIBC_INLINE constexpr Float80 &operator*=(const Float80 &other) {
-    *this = *this * other;
-    return *this;
-  }
-
-  LIBC_INLINE constexpr Float80 &operator+=(const Float80 &other) {
-    *this = *this + other;
-    return *this;
-  }
-
-  LIBC_INLINE constexpr Float80 &operator-=(const Float80 &other) {
-    *this = *this - other;
-    return *this;
-  }
-
-  LIBC_INLINE constexpr Float80 &operator/=(const Float80 &other) {
-    *this = *this / other;
-    return *this;
-  }
-
-  LIBC_INLINE constexpr bool operator==(const Float80 &other) const {
-    return fputil::equals(*this, other);
-  }
-
-  LIBC_INLINE constexpr bool operator!=(const Float80 &other) const {
-    return !fputil::equals(*this, other);
-  }
-
-  LIBC_INLINE constexpr bool operator<(const Float80 &other) const {
-    return fputil::less_than(*this, other);
-  }
-
-  LIBC_INLINE constexpr bool operator<=(const Float80 &other) const {
-    return fputil::less_than_or_equals(*this, other);
-  }
-
-  LIBC_INLINE constexpr bool operator>(const Float80 &other) const {
-    return fputil::greater_than(*this, other);
-  }
-
-  LIBC_INLINE constexpr bool operator>=(const Float80 &other) const {
-    return fputil::greater_than_or_equals(*this, other);
-  }
 };
 
 static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible<

>From 6e81a79c53ebc29f86d0b80503a0aee5ef23b562 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 16:56:36 +0530
Subject: [PATCH 07/16] add explicit bit handling for dyadic_float as per
 FPBits

---
 libc/src/__support/FPUtil/dyadic_float.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index e32906e3cf9cf..855c2d1499216 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -264,6 +264,8 @@ template <size_t Bits> struct DyadicFloat {
       }
 
       out_mantissa = static_cast<StorageType>(mantissa >> extra_fraction_len);
+      if constexpr (get_fp_type<T>() == FPType::X86_Binary80)
+        out_mantissa |= FPBits::EXPLICIT_BIT_MASK;
     }
 
     bool lsb = (out_mantissa & 1) != 0;

>From 23ea3c70c04dde219071404a02820b2ccb858b8a Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 16:58:38 +0530
Subject: [PATCH 08/16] nit

---
 libc/src/__support/FPUtil/dyadic_float.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 855c2d1499216..86a3e409a17d6 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -264,6 +264,7 @@ template <size_t Bits> struct DyadicFloat {
       }
 
       out_mantissa = static_cast<StorageType>(mantissa >> extra_fraction_len);
+      // Takes into consideration the explicit bit for number for types like float 80
       if constexpr (get_fp_type<T>() == FPType::X86_Binary80)
         out_mantissa |= FPBits::EXPLICIT_BIT_MASK;
     }

>From f0815a211ce84b6b74e06954fdbd71b4f8120e35 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 17:03:13 +0530
Subject: [PATCH 09/16] nit

---
 libc/src/__support/FPUtil/dyadic_float.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 86a3e409a17d6..432409e6a8501 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -264,7 +264,8 @@ template <size_t Bits> struct DyadicFloat {
       }
 
       out_mantissa = static_cast<StorageType>(mantissa >> extra_fraction_len);
-      // Takes into consideration the explicit bit for number for types like float 80
+      // Takes into consideration the explicit bit for number for types like
+      // float 80
       if constexpr (get_fp_type<T>() == FPType::X86_Binary80)
         out_mantissa |= FPBits::EXPLICIT_BIT_MASK;
     }

>From 8b7aa2eab7192a2167bcf1e687d7d9d490341eb0 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 17:25:32 +0530
Subject: [PATCH 10/16] test: limit EXTRA_FRAC_LEN to be non-negative

test

test

nit

revert

revert

only add >0 condition

format
---
 libc/src/__support/FPUtil/dyadic_float.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 432409e6a8501..e32906e3cf9cf 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -264,10 +264,6 @@ template <size_t Bits> struct DyadicFloat {
       }
 
       out_mantissa = static_cast<StorageType>(mantissa >> extra_fraction_len);
-      // Takes into consideration the explicit bit for number for types like
-      // float 80
-      if constexpr (get_fp_type<T>() == FPType::X86_Binary80)
-        out_mantissa |= FPBits::EXPLICIT_BIT_MASK;
     }
 
     bool lsb = (out_mantissa & 1) != 0;

>From 575ccc5ef1ad924b3cfcfa0a1b0a2c7eac1c4ef7 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 19:11:47 +0530
Subject: [PATCH 11/16] feat: add negation and a test for it

---
 libc/src/__support/FPUtil/float80.h             | 7 +++++++
 libc/test/src/__support/FPUtil/float80_test.cpp | 2 ++
 2 files changed, 9 insertions(+)

diff --git a/libc/src/__support/FPUtil/float80.h b/libc/src/__support/FPUtil/float80.h
index 882eec261db15..572b51aa67fb3 100644
--- a/libc/src/__support/FPUtil/float80.h
+++ b/libc/src/__support/FPUtil/float80.h
@@ -95,6 +95,13 @@ struct Float80 {
         x_bits.sign(), x_bits_exp, x_bits.get_explicit_mantissa());
     return static_cast<T>(xd.as_mantissa_type());
   }
+
+  // unary operators
+  LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR Float80 operator-() const {
+    fputil::FPBits<Float80> result(*this);
+    result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
+    return result.get_val();
+  }
 };
 
 static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible<
diff --git a/libc/test/src/__support/FPUtil/float80_test.cpp b/libc/test/src/__support/FPUtil/float80_test.cpp
index 72c1155f8c6d3..767eccfa9588c 100644
--- a/libc/test/src/__support/FPUtil/float80_test.cpp
+++ b/libc/test/src/__support/FPUtil/float80_test.cpp
@@ -19,7 +19,9 @@ using FPBits = LIBC_NAMESPACE::fputil::FPBits<Float80>;
 TEST(LlvmLibcFloat80Test, IntegerConversion) {
   // Float80 to Integer conversion test
   ASSERT_EQ(static_cast<int>(Float80(0.0f)), 0);
+  ASSERT_EQ(static_cast<int>(Float80(-0.0f)), 0);
   ASSERT_EQ(static_cast<int>(Float80(1.0f)), 1);
+  ASSERT_EQ(static_cast<int>(Float80(-1.0f)), -1);
   ASSERT_EQ(static_cast<long long>(Float80(1000000000.0)),
             static_cast<long long>(1000000000));
   ASSERT_EQ(static_cast<unsigned>(Float80(7.0f)), 7U);

>From bbd46124505e3b6a5eb346b2cd009aefccbc2b6f Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 21:03:12 +0530
Subject: [PATCH 12/16] add tests

---
 libc/src/__support/FPUtil/float80.h           | 21 +++++++++++++++++++
 .../src/__support/FPUtil/float80_test.cpp     | 15 +++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/libc/src/__support/FPUtil/float80.h b/libc/src/__support/FPUtil/float80.h
index 572b51aa67fb3..1a9b2f59fd5a5 100644
--- a/libc/src/__support/FPUtil/float80.h
+++ b/libc/src/__support/FPUtil/float80.h
@@ -101,6 +101,27 @@ struct Float80 {
     fputil::FPBits<Float80> result(*this);
     result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
     return result.get_val();
+
+    // operator overloads
+    LIBC_INLINE constexpr Float80 operator+(const Float80 &other) const {
+      return fputil::generic::add<Float80>(*this, other);
+    }
+
+    LIBC_INLINE constexpr Float80 operator-(const Float80 &other) const {
+      return fputil::generic::sub<Float80>(*this, other);
+    }
+
+    LIBC_INLINE constexpr Float80 operator*(const Float80 &other) const {
+      return fputil::generic::mul<Float80>(*this, other);
+    }
+
+    LIBC_INLINE constexpr Float80 operator/(const Float80 &other) const {
+      return fputil::generic::div<Float80>(*this, other);
+    }
+
+    LIBC_INLINE constexpr bool operator==(const Float128 &other) const {
+      return fputil::equals(*this, other);
+    }
   }
 };
 
diff --git a/libc/test/src/__support/FPUtil/float80_test.cpp b/libc/test/src/__support/FPUtil/float80_test.cpp
index 767eccfa9588c..2d1f2d1427f55 100644
--- a/libc/test/src/__support/FPUtil/float80_test.cpp
+++ b/libc/test/src/__support/FPUtil/float80_test.cpp
@@ -16,6 +16,21 @@ using LIBC_NAMESPACE::Sign;
 using LIBC_NAMESPACE::fputil::Float80;
 using FPBits = LIBC_NAMESPACE::fputil::FPBits<Float80>;
 
+TEST(LlvmLibcFloat80Test, temp) { Float80 a(1.0f); }
+
+TEST(LlvmLibcFloat80Test, Operators) {
+  Float80 a(1.0f), b(1.0f), c(2.0f), d(3.0f), pa(1.0f), na(-1.0f);
+
+  // Unary operators
+  ASSERT_TRUE(FPBits(-pa) == FPBits(na));
+
+  // Binary operators
+  ASSERT_TRUE(a + b == c);
+  ASSERT_TRUE(a - b == Float128(0.0));
+  ASSERT_TRUE(c * d == Float128(6.0));
+  ASSERT_TRUE(Float80(6.0f) / d) == Float80(2.0f);
+}
+
 TEST(LlvmLibcFloat80Test, IntegerConversion) {
   // Float80 to Integer conversion test
   ASSERT_EQ(static_cast<int>(Float80(0.0f)), 0);

>From 763a72337c4db643ff193d019abbfe5792e179ed Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 13 Aug 2026 20:25:20 +0530
Subject: [PATCH 13/16] suggestions and add more operators

---
 libc/src/__support/FPUtil/float80.h           | 56 +++++++++++++------
 .../src/__support/FPUtil/float80_test.cpp     | 39 +++++++++++--
 2 files changed, 74 insertions(+), 21 deletions(-)

diff --git a/libc/src/__support/FPUtil/float80.h b/libc/src/__support/FPUtil/float80.h
index 1a9b2f59fd5a5..48ce7912a53f4 100644
--- a/libc/src/__support/FPUtil/float80.h
+++ b/libc/src/__support/FPUtil/float80.h
@@ -14,6 +14,7 @@
 #include "src/__support/FPUtil/cast.h"
 #include "src/__support/FPUtil/comparison_operations.h"
 #include "src/__support/FPUtil/dyadic_float.h"
+#include "src/__support/FPUtil/float128.h"
 #include "src/__support/FPUtil/generic/add_sub.h"
 #include "src/__support/FPUtil/generic/div.h"
 #include "src/__support/FPUtil/generic/mul.h"
@@ -101,27 +102,50 @@ struct Float80 {
     fputil::FPBits<Float80> result(*this);
     result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
     return result.get_val();
+  }
+  LIBC_INLINE constexpr Float80 operator+(const Float80 &other) const {
+    return fputil::generic::add<Float80>(fputil::cast<Float128>(*this),
+                                         fputil::cast<Float128>(other));
+  }
 
-    // operator overloads
-    LIBC_INLINE constexpr Float80 operator+(const Float80 &other) const {
-      return fputil::generic::add<Float80>(*this, other);
-    }
+  LIBC_INLINE constexpr Float80 operator-(const Float80 &other) const {
+    return fputil::generic::sub<Float80>(fputil::cast<Float128>(*this),
+                                         fputil::cast<Float128>(other));
+  }
 
-    LIBC_INLINE constexpr Float80 operator-(const Float80 &other) const {
-      return fputil::generic::sub<Float80>(*this, other);
-    }
+  LIBC_INLINE constexpr Float80 operator*(const Float80 &other) const {
+    return fputil::generic::mul<Float80>(fputil::cast<Float128>(*this),
+                                         fputil::cast<Float128>(other));
+  }
 
-    LIBC_INLINE constexpr Float80 operator*(const Float80 &other) const {
-      return fputil::generic::mul<Float80>(*this, other);
-    }
+  LIBC_INLINE constexpr Float80 operator/(const Float80 &other) const {
+    return fputil::generic::div<Float80>(fputil::cast<Float128>(*this),
+                                         fputil::cast<Float128>(other));
+  }
 
-    LIBC_INLINE constexpr Float80 operator/(const Float80 &other) const {
-      return fputil::generic::div<Float80>(*this, other);
-    }
+  // Comparison operators
+  LIBC_INLINE constexpr bool operator==(const Float80 &other) const {
+    return fputil::equals(*this, other);
+  }
 
-    LIBC_INLINE constexpr bool operator==(const Float128 &other) const {
-      return fputil::equals(*this, other);
-    }
+  LIBC_INLINE constexpr bool operator!=(const Float80 &other) const {
+    return !fputil::equals(*this, other);
+  }
+
+  LIBC_INLINE constexpr bool operator<(const Float80 &other) const {
+    return fputil::less_than(*this, other);
+  }
+
+  LIBC_INLINE constexpr bool operator<=(const Float80 &other) const {
+    return fputil::less_than_or_equals(*this, other);
+  }
+
+  LIBC_INLINE constexpr bool operator>(const Float80 &other) const {
+    return fputil::greater_than(*this, other);
+  }
+
+  LIBC_INLINE constexpr bool operator>=(const Float80 &other) const {
+    return fputil::greater_than_or_equals(*this, other);
   }
 };
 
diff --git a/libc/test/src/__support/FPUtil/float80_test.cpp b/libc/test/src/__support/FPUtil/float80_test.cpp
index 2d1f2d1427f55..d76219b6b61ab 100644
--- a/libc/test/src/__support/FPUtil/float80_test.cpp
+++ b/libc/test/src/__support/FPUtil/float80_test.cpp
@@ -16,19 +16,48 @@ using LIBC_NAMESPACE::Sign;
 using LIBC_NAMESPACE::fputil::Float80;
 using FPBits = LIBC_NAMESPACE::fputil::FPBits<Float80>;
 
+// will be removed
 TEST(LlvmLibcFloat80Test, temp) { Float80 a(1.0f); }
 
 TEST(LlvmLibcFloat80Test, Operators) {
   Float80 a(1.0f), b(1.0f), c(2.0f), d(3.0f), pa(1.0f), na(-1.0f);
 
+  // comparison operators
+  ASSERT_TRUE(a == b);
+  ASSERT_TRUE(a == Float80(1.0));
+  ASSERT_TRUE(a != c);
+  ASSERT_TRUE(b != c);
+  ASSERT_TRUE(c > b);
+  ASSERT_TRUE(a >= b);
+  ASSERT_TRUE(b <= c);
+  ASSERT_TRUE(a < c);
+
   // Unary operators
-  ASSERT_TRUE(FPBits(-pa) == FPBits(na));
+  ASSERT_TRUE(-pa == na);
+  ASSERT_TRUE(-(-pa) == pa);
 
   // Binary operators
-  ASSERT_TRUE(a + b == c);
-  ASSERT_TRUE(a - b == Float128(0.0));
-  ASSERT_TRUE(c * d == Float128(6.0));
-  ASSERT_TRUE(Float80(6.0f) / d) == Float80(2.0f);
+  ASSERT_TRUE((a + b) == c);
+  ASSERT_TRUE((a - b) == Float80(0.0f));
+  ASSERT_TRUE((c * d) == Float80(6.0f));
+  ASSERT_TRUE((Float80(6.0f) / d) == Float80(2.0f));
+}
+
+TEST(LlvmLibcFloat80Test, SpecialValues) {
+  Float80 inf = FPBits::inf(Sign::POS).get_val();
+  Float80 neg_inf = FPBits::inf(Sign::NEG).get_val();
+  Float80 nan = FPBits::quiet_nan().get_val();
+
+  // checking operators with special values
+  ASSERT_TRUE(Float80(0.0f) == Float80(-0.0f)); // +0.0 == -0.0 is true
+  ASSERT_TRUE(Float80(0.0f) == Float80(0.0f));
+  ASSERT_TRUE(inf == inf);
+  ASSERT_TRUE(-inf == neg_inf);
+  ASSERT_TRUE((inf + Float80(1.0f)) == inf);
+  ASSERT_TRUE(inf + inf == inf);
+  ASSERT_TRUE(nan != nan);
+  ASSERT_TRUE(!(nan == nan));
+  ASSERT_TRUE(nan != Float80(0.0f));
 }
 
 TEST(LlvmLibcFloat80Test, IntegerConversion) {

>From a9c9cff937c2d14653bf1a2d110830ea6dd1f279 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Fri, 21 Aug 2026 01:47:22 +0530
Subject: [PATCH 14/16] nit

---
 libc/test/src/__support/FPUtil/float80_test.cpp | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/libc/test/src/__support/FPUtil/float80_test.cpp b/libc/test/src/__support/FPUtil/float80_test.cpp
index d76219b6b61ab..c59be71240b9d 100644
--- a/libc/test/src/__support/FPUtil/float80_test.cpp
+++ b/libc/test/src/__support/FPUtil/float80_test.cpp
@@ -16,9 +16,6 @@ using LIBC_NAMESPACE::Sign;
 using LIBC_NAMESPACE::fputil::Float80;
 using FPBits = LIBC_NAMESPACE::fputil::FPBits<Float80>;
 
-// will be removed
-TEST(LlvmLibcFloat80Test, temp) { Float80 a(1.0f); }
-
 TEST(LlvmLibcFloat80Test, Operators) {
   Float80 a(1.0f), b(1.0f), c(2.0f), d(3.0f), pa(1.0f), na(-1.0f);
 

>From 01df9d328a304d773d8fac09ee70990cb0465213 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Fri, 21 Aug 2026 01:51:46 +0530
Subject: [PATCH 15/16] apply suggestion

---
 libc/src/__support/FPUtil/CMakeLists.txt | 1 +
 libc/src/__support/FPUtil/float80.h      | 8 ++------
 2 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 96fbb6d80a669..19934a6f00783 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -323,6 +323,7 @@ add_header_library(
     .dyadic_float
     libc.hdr.stdint_proxy
     libc.src.__support.CPP.type_traits
+    libc.src.__support.FPUtil.float80
     libc.src.__support.FPUtil.generic.add_sub
     libc.src.__support.FPUtil.generic.div
     libc.src.__support.FPUtil.generic.mul
diff --git a/libc/src/__support/FPUtil/float80.h b/libc/src/__support/FPUtil/float80.h
index 48ce7912a53f4..25c7ba9251a96 100644
--- a/libc/src/__support/FPUtil/float80.h
+++ b/libc/src/__support/FPUtil/float80.h
@@ -97,12 +97,13 @@ struct Float80 {
     return static_cast<T>(xd.as_mantissa_type());
   }
 
-  // unary operators
+  // unary operator
   LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR Float80 operator-() const {
     fputil::FPBits<Float80> result(*this);
     result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
     return result.get_val();
   }
+
   LIBC_INLINE constexpr Float80 operator+(const Float80 &other) const {
     return fputil::generic::add<Float80>(fputil::cast<Float128>(*this),
                                          fputil::cast<Float128>(other));
@@ -149,11 +150,6 @@ struct Float80 {
   }
 };
 
-static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible<
-              LIBC_NAMESPACE::fputil::Float80>::value);
-static_assert(LIBC_NAMESPACE::cpp::is_trivially_copyable<
-              LIBC_NAMESPACE::fputil::Float80>::value);
-
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 

>From 20b3ea12bb41eb5bbf2047dad6da3421456b6477 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 22 Aug 2026 19:51:59 +0530
Subject: [PATCH 16/16] fix self dependency

---
 libc/src/__support/FPUtil/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 19934a6f00783..a32244e478532 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -321,9 +321,9 @@ add_header_library(
     .cast
     .comparison_operations
     .dyadic_float
+    .float128
     libc.hdr.stdint_proxy
     libc.src.__support.CPP.type_traits
-    libc.src.__support.FPUtil.float80
     libc.src.__support.FPUtil.generic.add_sub
     libc.src.__support.FPUtil.generic.div
     libc.src.__support.FPUtil.generic.mul



More information about the llvm-branch-commits mailing list