[libc] [llvm] [libc] Add `next_toward_inf` fo `FPBits` (PR #80654)

Guillaume Chatelet via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 5 02:12:51 PST 2024


https://github.com/gchatelet updated https://github.com/llvm/llvm-project/pull/80654

>From 734466d9e83cb1ef92ee5da6e45646cd1b6cd8d9 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Mon, 5 Feb 2024 09:47:12 +0000
Subject: [PATCH 1/2] [libc] Add `next_toward_inf` fo `FPBits`

It is needed to provide correct rounding when building FPRep from greater precision representations.
---
 libc/src/__support/FPUtil/FPBits.h            | 34 +++++++++++++++++++
 .../test/src/__support/FPUtil/fpbits_test.cpp | 22 ++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 7bfdfc1691a2d..271fc7c2c968d 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -266,6 +266,16 @@ template <FPType fp_type> struct FPStorage : public FPLayout<fp_type> {
     LIBC_INLINE constexpr operator Exponent() const {
       return Exponent(UP::value - EXP_BIAS);
     }
+
+    LIBC_INLINE constexpr BiasedExponent &operator++() {
+      ++UP::value;
+      return *this;
+    }
+
+    LIBC_INLINE constexpr BiasedExponent &operator--() {
+      --UP::value;
+      return *this;
+    }
   };
 
   // An opaque type to store a floating point significand.
@@ -435,6 +445,13 @@ struct FPRepSem : public FPStorage<fp_type> {
   LIBC_INLINE constexpr bool is_normal() const {
     return is_finite() && !is_subnormal();
   }
+
+  // Modifiers
+  LIBC_INLINE constexpr void next_toward_inf() {
+    if (is_finite())
+      ++UP::bits;
+  }
+
   // Returns the mantissa with the implicit bit set iff the current
   // value is a valid normal number.
   LIBC_INLINE constexpr StorageType get_explicit_mantissa() const {
@@ -551,6 +568,22 @@ struct FPRepSem<FPType::X86_Binary80, RetT>
       return false;
     return get_implicit_bit();
   }
+  
+  // Modifiers
+  LIBC_INLINE constexpr void next_toward_inf() {
+    if (is_finite()) {
+      if (exp_sig_bits() == max_normal().uintval()) {
+        bits = inf(sign()).uintval();
+      } else if (exp_sig_bits() == max_subnormal().uintval()) {
+        bits = min_normal(sign()).uintval();
+      } else if (sig_bits() == SIG_MASK) {
+        bits = encode(sign(), ++biased_exponent(), Significand::ZERO());
+      } else {
+        ++bits;
+      }
+    }
+  }
+
   LIBC_INLINE constexpr StorageType get_explicit_mantissa() const {
     return sig_bits();
   }
@@ -633,6 +666,7 @@ struct FPRepImpl : public FPRepSem<fp_type, RetT> {
   using UP::max_subnormal;
   using UP::min_normal;
   using UP::min_subnormal;
+  using UP::next_toward_inf;
   using UP::one;
   using UP::quiet_nan;
   using UP::signaling_nan;
diff --git a/libc/test/src/__support/FPUtil/fpbits_test.cpp b/libc/test/src/__support/FPUtil/fpbits_test.cpp
index 65823511e82f5..c0dedc08780cf 100644
--- a/libc/test/src/__support/FPUtil/fpbits_test.cpp
+++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp
@@ -306,6 +306,28 @@ TYPED_TEST(LlvmLibcFPBitsTest, Properties, FPTypes) {
   }
 }
 
+#define ASSERT_SAME_REP(A, B) ASSERT_EQ(A.uintval(), B.uintval());
+
+TYPED_TEST(LlvmLibcFPBitsTest, NextTowardInf, FPTypes) {
+  struct {
+    FP before, after;
+  } TEST_CASES[] = {
+      {FP::ZERO, FP::MIN_SUBNORMAL},          //
+      {FP::MAX_SUBNORMAL, FP::MIN_NORMAL},    //
+      {FP::MAX_NORMAL, FP::INF},              //
+      {FP::INF, FP::INF},                     //
+      {FP::QUIET_NAN, FP::QUIET_NAN},         //
+      {FP::SIGNALING_NAN, FP::SIGNALING_NAN}, //
+  };
+  for (Sign sign : all_signs) {
+    for (auto tc : TEST_CASES) {
+      T val = make<T>(sign, tc.before);
+      val.next_toward_inf();
+      ASSERT_SAME_REP(val, make<T>(sign, tc.after));
+    }
+  }
+}
+
 TEST(LlvmLibcFPBitsTest, FloatType) {
   using FloatBits = FPBits<float>;
 

>From 6a32ff54d9c25ba79651bf33a6adbbcac44fef77 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Mon, 5 Feb 2024 10:12:37 +0000
Subject: [PATCH 2/2] Add assert / fix formatting

---
 libc/src/__support/FPUtil/CMakeLists.txt          | 1 +
 libc/src/__support/FPUtil/FPBits.h                | 5 ++++-
 utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 1 +
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 50cc904f0cfad..47c102a47426c 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -31,6 +31,7 @@ add_header_library(
     libc.src.__support.common
     libc.src.__support.CPP.bit
     libc.src.__support.CPP.type_traits
+    libc.src.__support.libc_assert
     libc.src.__support.macros.attributes
     libc.src.__support.macros.properties.float
     libc.src.__support.math_extras
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 271fc7c2c968d..e33c8402b6296 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -13,6 +13,7 @@
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/UInt128.h"
 #include "src/__support/common.h"
+#include "src/__support/libc_assert.h"       // LIBC_ASSERT
 #include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR
 #include "src/__support/macros/properties/float.h" // LIBC_COMPILER_HAS_FLOAT128
 #include "src/__support/math_extras.h"             // mask_trailing_ones
@@ -268,11 +269,13 @@ template <FPType fp_type> struct FPStorage : public FPLayout<fp_type> {
     }
 
     LIBC_INLINE constexpr BiasedExponent &operator++() {
+      LIBC_ASSERT(*this != BiasedExponent(Exponent::INF()));
       ++UP::value;
       return *this;
     }
 
     LIBC_INLINE constexpr BiasedExponent &operator--() {
+      LIBC_ASSERT(*this != BiasedExponent(Exponent::SUBNORMAL()));
       --UP::value;
       return *this;
     }
@@ -568,7 +571,7 @@ struct FPRepSem<FPType::X86_Binary80, RetT>
       return false;
     return get_implicit_bit();
   }
-  
+
   // Modifiers
   LIBC_INLINE constexpr void next_toward_inf() {
     if (is_finite()) {
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index f1fe823354ed7..adce590bcf2ae 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -666,6 +666,7 @@ libc_support_library(
         ":__support_common",
         ":__support_cpp_bit",
         ":__support_cpp_type_traits",
+        ":__support_libc_assert",
         ":__support_macros_attributes",
         ":__support_macros_properties_float",
         ":__support_math_extras",



More information about the llvm-commits mailing list