[libc-commits] [libc] b03567f - [libc][math] Improved FBits performance and readablity.

Kirill Okhotnikov via libc-commits libc-commits at lists.llvm.org
Fri Jun 10 01:21:55 PDT 2022


Author: Kirill Okhotnikov
Date: 2022-06-10T10:21:44+02:00
New Revision: b03567fe2b74ea777bf134d4c1d7b76746fc7dd9

URL: https://github.com/llvm/llvm-project/commit/b03567fe2b74ea777bf134d4c1d7b76746fc7dd9
DIFF: https://github.com/llvm/llvm-project/commit/b03567fe2b74ea777bf134d4c1d7b76746fc7dd9.diff

LOG: [libc][math] Improved FBits performance and readablity.

Some function added in preparation to fmod commit.

Differential Revision: https://reviews.llvm.org/D127097

Added: 
    

Modified: 
    libc/src/__support/FPUtil/FPBits.h
    libc/src/__support/FPUtil/FloatProperties.h

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 36df9c54c4777..6743fee9b1a48 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -57,6 +57,11 @@ template <typename T> struct FPBits {
 
   UIntType get_mantissa() const { return bits & FloatProp::MANTISSA_MASK; }
 
+  // The function return mantissa with implicit bit set for normal values.
+  constexpr UIntType get_explicit_mantissa() {
+    return (FloatProp::MANTISSA_MASK + 1) | (FloatProp::MANTISSA_MASK & bits);
+  }
+
   void set_unbiased_exponent(UIntType expVal) {
     expVal = (expVal << (FloatProp::MANTISSA_WIDTH)) & FloatProp::EXPONENT_MASK;
     bits &= ~(FloatProp::EXPONENT_MASK);
@@ -69,14 +74,12 @@ template <typename T> struct FPBits {
   }
 
   void set_sign(bool signVal) {
-    bits &= ~(FloatProp::SIGN_MASK);
-    UIntType sign = UIntType(signVal) << (FloatProp::BIT_WIDTH - 1);
-    bits |= sign;
+    bits |= FloatProp::SIGN_MASK;
+    if (!signVal)
+      bits -= FloatProp::SIGN_MASK;
   }
 
-  bool get_sign() const {
-    return ((bits & FloatProp::SIGN_MASK) >> (FloatProp::BIT_WIDTH - 1));
-  }
+  bool get_sign() const { return (bits & FloatProp::SIGN_MASK) != 0; }
 
   static_assert(sizeof(T) == sizeof(UIntType),
                 "Data type and integral representation have 
diff erent sizes.");
@@ -92,7 +95,7 @@ template <typename T> struct FPBits {
   static constexpr UIntType MAX_NORMAL =
       ((UIntType(MAX_EXPONENT) - 1) << MantissaWidth<T>::VALUE) | MAX_SUBNORMAL;
 
-  // We don't want accidental type promotions/conversions so we require exact
+  // We don't want accidental type promotions/conversions, so we require exact
   // type match.
   template <typename XType,
             cpp::EnableIfType<cpp::IsSame<T, XType>::Value, int> = 0>
@@ -118,38 +121,41 @@ template <typename T> struct FPBits {
   }
 
   bool is_zero() const {
-    return get_mantissa() == 0 && get_unbiased_exponent() == 0;
+    // Remove sign bit by shift
+    return (bits << 1) == 0;
   }
 
   bool is_inf() const {
-    return get_mantissa() == 0 && get_unbiased_exponent() == MAX_EXPONENT;
+    return (bits & FloatProp::EXP_MANT_MASK) == FloatProp::EXPONENT_MASK;
   }
 
   bool is_nan() const {
-    return get_unbiased_exponent() == MAX_EXPONENT && get_mantissa() != 0;
+    return (bits & FloatProp::EXP_MANT_MASK) > FloatProp::EXPONENT_MASK;
   }
 
-  bool is_inf_or_nan() const { return get_unbiased_exponent() == MAX_EXPONENT; }
-
-  static FPBits<T> zero() { return FPBits(); }
+  bool is_inf_or_nan() const {
+    return (bits & FloatProp::EXPONENT_MASK) == FloatProp::EXPONENT_MASK;
+  }
 
-  static FPBits<T> neg_zero() {
-    return FPBits(UIntType(1) << (sizeof(UIntType) * 8 - 1));
+  static constexpr FPBits<T> zero(bool sign = false) {
+    return FPBits(sign ? FloatProp::SIGN_MASK : UIntType(0));
   }
 
-  static FPBits<T> inf() {
+  static constexpr FPBits<T> neg_zero() { return zero(true); }
+
+  static constexpr FPBits<T> inf() {
     FPBits<T> bits;
     bits.set_unbiased_exponent(MAX_EXPONENT);
     return bits;
   }
 
-  static FPBits<T> neg_inf() {
+  static constexpr FPBits<T> neg_inf() {
     FPBits<T> bits = inf();
     bits.set_sign(1);
     return bits;
   }
 
-  static T build_nan(UIntType v) {
+  static constexpr T build_nan(UIntType v) {
     FPBits<T> bits = inf();
     bits.set_mantissa(v);
     return T(bits);

diff  --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h
index 8cf0da1267a91..ad52a4066e1e6 100644
--- a/libc/src/__support/FPUtil/FloatProperties.h
+++ b/libc/src/__support/FPUtil/FloatProperties.h
@@ -22,7 +22,7 @@ template <> struct FloatProperties<float> {
   static_assert(sizeof(BitsType) == sizeof(float),
                 "Unexpected size of 'float' type.");
 
-  static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3;
+  static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) * 8;
 
   static constexpr uint32_t MANTISSA_WIDTH = 23;
   static constexpr uint32_t EXPONENT_WIDTH = 8;
@@ -32,6 +32,10 @@ template <> struct FloatProperties<float> {
   static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
   static constexpr uint32_t EXPONENT_BIAS = 127;
 
+  static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK + EXPONENT_MASK;
+  static_assert(EXP_MANT_MASK == ~SIGN_MASK,
+                "Exponent and mantissa masks are not as expected.");
+
   // If a number x is a NAN, then it is a quiet NAN if:
   //   QuietNaNMask & bits(x) != 0
   // Else, it is a signalling NAN.
@@ -43,7 +47,7 @@ template <> struct FloatProperties<double> {
   static_assert(sizeof(BitsType) == sizeof(double),
                 "Unexpected size of 'double' type.");
 
-  static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3;
+  static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) * 8;
 
   static constexpr uint32_t MANTISSA_WIDTH = 52;
   static constexpr uint32_t EXPONENT_WIDTH = 11;
@@ -53,6 +57,10 @@ template <> struct FloatProperties<double> {
   static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
   static constexpr uint32_t EXPONENT_BIAS = 1023;
 
+  static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK + EXPONENT_MASK;
+  static_assert(EXP_MANT_MASK == ~SIGN_MASK,
+                "Exponent and mantissa masks are not as expected.");
+
   // If a number x is a NAN, then it is a quiet NAN if:
   //   QuietNaNMask & bits(x) != 0
   // Else, it is a signalling NAN.
@@ -95,7 +103,7 @@ template <> struct FloatProperties<long double> {
   static_assert(sizeof(BitsType) == sizeof(long double),
                 "Unexpected size of 'long double' type.");
 
-  static constexpr uint32_t BIT_WIDTH = (sizeof(BitsType) << 3) - 48;
+  static constexpr uint32_t BIT_WIDTH = (sizeof(BitsType) * 8) - 48;
 
   static constexpr uint32_t MANTISSA_WIDTH = 63;
   static constexpr uint32_t EXPONENT_WIDTH = 15;


        


More information about the libc-commits mailing list