[libc-commits] [libc] 1f51038 - [libc][stdfix] Implement `countlsfx` functions in libc. (#126597)

via libc-commits libc-commits at lists.llvm.org
Wed Feb 12 11:12:48 PST 2025


Author: Krishna Pandey
Date: 2025-02-12T14:12:44-05:00
New Revision: 1f51038036b4bc216eddcc620dcb9eca5df2bfef

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

LOG: [libc][stdfix] Implement `countlsfx` functions in libc. (#126597)

fixes #113357

---------

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>

Added: 
    libc/src/stdfix/countlshk.cpp
    libc/src/stdfix/countlshk.h
    libc/src/stdfix/countlshr.cpp
    libc/src/stdfix/countlshr.h
    libc/src/stdfix/countlsk.cpp
    libc/src/stdfix/countlsk.h
    libc/src/stdfix/countlslk.cpp
    libc/src/stdfix/countlslk.h
    libc/src/stdfix/countlslr.cpp
    libc/src/stdfix/countlslr.h
    libc/src/stdfix/countlsr.cpp
    libc/src/stdfix/countlsr.h
    libc/src/stdfix/countlsuhk.cpp
    libc/src/stdfix/countlsuhk.h
    libc/src/stdfix/countlsuhr.cpp
    libc/src/stdfix/countlsuhr.h
    libc/src/stdfix/countlsuk.cpp
    libc/src/stdfix/countlsuk.h
    libc/src/stdfix/countlsulk.cpp
    libc/src/stdfix/countlsulk.h
    libc/src/stdfix/countlsulr.cpp
    libc/src/stdfix/countlsulr.h
    libc/src/stdfix/countlsur.cpp
    libc/src/stdfix/countlsur.h
    libc/test/src/stdfix/CountlsTest.h
    libc/test/src/stdfix/countlshk_test.cpp
    libc/test/src/stdfix/countlshr_test.cpp
    libc/test/src/stdfix/countlsk_test.cpp
    libc/test/src/stdfix/countlslk_test.cpp
    libc/test/src/stdfix/countlslr_test.cpp
    libc/test/src/stdfix/countlsr_test.cpp
    libc/test/src/stdfix/countlsuhk_test.cpp
    libc/test/src/stdfix/countlsuhr_test.cpp
    libc/test/src/stdfix/countlsuk_test.cpp
    libc/test/src/stdfix/countlsulk_test.cpp
    libc/test/src/stdfix/countlsulr_test.cpp
    libc/test/src/stdfix/countlsur_test.cpp

Modified: 
    libc/config/baremetal/arm/entrypoints.txt
    libc/config/baremetal/riscv/entrypoints.txt
    libc/config/linux/riscv/entrypoints.txt
    libc/config/linux/x86_64/entrypoints.txt
    libc/docs/headers/math/stdfix.rst
    libc/include/stdfix.yaml
    libc/src/__support/fixed_point/CMakeLists.txt
    libc/src/__support/fixed_point/fx_bits.h
    libc/src/__support/fixed_point/fx_rep.h
    libc/src/stdfix/CMakeLists.txt
    libc/test/src/stdfix/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 694cd7b1993ca..351f727389e3a 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -469,6 +469,18 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
     libc.src.stdfix.ukbits
     libc.src.stdfix.lkbits
     libc.src.stdfix.ulkbits
+    libc.src.stdfix.countlshr
+    libc.src.stdfix.countlsr
+    libc.src.stdfix.countlslr
+    libc.src.stdfix.countlshk
+    libc.src.stdfix.countlsk
+    libc.src.stdfix.countlslk
+    libc.src.stdfix.countlsuhr
+    libc.src.stdfix.countlsur
+    libc.src.stdfix.countlsulr
+    libc.src.stdfix.countlsuhk
+    libc.src.stdfix.countlsuk
+    libc.src.stdfix.countlsulk
   )
 endif()
 

diff  --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 667ab40dca999..39c70a22a21e0 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -464,6 +464,18 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
     libc.src.stdfix.ukbits
     libc.src.stdfix.lkbits
     libc.src.stdfix.ulkbits
+    libc.src.stdfix.countlshr
+    libc.src.stdfix.countlsr
+    libc.src.stdfix.countlslr
+    libc.src.stdfix.countlshk
+    libc.src.stdfix.countlsk
+    libc.src.stdfix.countlslk
+    libc.src.stdfix.countlsuhr
+    libc.src.stdfix.countlsur
+    libc.src.stdfix.countlsulr
+    libc.src.stdfix.countlsuhk
+    libc.src.stdfix.countlsuk
+    libc.src.stdfix.countlsulk
   )
 endif()
 

diff  --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 6e67ea559d57b..a9ba0c257755b 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -749,6 +749,18 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
     # TODO: https://github.com/llvm/llvm-project/issues/115778
     libc.src.stdfix.lkbits
     libc.src.stdfix.ulkbits
+    libc.src.stdfix.countlshr
+    libc.src.stdfix.countlsr
+    libc.src.stdfix.countlslr
+    libc.src.stdfix.countlshk
+    libc.src.stdfix.countlsk
+    libc.src.stdfix.countlslk
+    libc.src.stdfix.countlsuhr
+    libc.src.stdfix.countlsur
+    libc.src.stdfix.countlsulr
+    libc.src.stdfix.countlsuhk
+    libc.src.stdfix.countlsuk
+    libc.src.stdfix.countlsulk
   )
 endif()
 

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 0a942516db6c3..76e593296a4ea 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -875,6 +875,18 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
     libc.src.stdfix.ukbits
     libc.src.stdfix.lkbits
     libc.src.stdfix.ulkbits
+    libc.src.stdfix.countlshr
+    libc.src.stdfix.countlsr
+    libc.src.stdfix.countlslr
+    libc.src.stdfix.countlshk
+    libc.src.stdfix.countlsk
+    libc.src.stdfix.countlslk
+    libc.src.stdfix.countlsuhr
+    libc.src.stdfix.countlsur
+    libc.src.stdfix.countlsulr
+    libc.src.stdfix.countlsuhk
+    libc.src.stdfix.countlsuk
+    libc.src.stdfix.countlsulk
   )
 endif()
 

diff  --git a/libc/docs/headers/math/stdfix.rst b/libc/docs/headers/math/stdfix.rst
index 58052f000995c..4507f2b608bf1 100644
--- a/libc/docs/headers/math/stdfix.rst
+++ b/libc/docs/headers/math/stdfix.rst
@@ -73,7 +73,7 @@ The following functions are included in the ISO/IEC TR 18037:2008 standard.
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
 | \*bits        |                |             |               |            |                |             |                |             |               |            |                |             |
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
-| countls       |                |             |               |            |                |             |                |             |               |            |                |             |
+| countls       | |check|        | |check|     | |check|       | |check|    | |check|        | |check|     | |check|        | |check|     | |check|       | |check|    | |check|        | |check|     |
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
 | divi          |                |             |               |            |                |             |                |             |               |            |                |             |
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+

diff  --git a/libc/include/stdfix.yaml b/libc/include/stdfix.yaml
index 9663ac0c7df4d..0abf2f3a9b3b6 100644
--- a/libc/include/stdfix.yaml
+++ b/libc/include/stdfix.yaml
@@ -306,3 +306,87 @@ functions:
     arguments:
       - type: unsigned int
     guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: countlshr
+    standards:
+      - stdc_ext
+    return_type: int
+    arguments:
+      - type: short fract
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: countlsr
+    standards:
+      - stdc_ext
+    return_type: int
+    arguments:
+      - type: fract
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: countlslr
+    standards:
+      - stdc_ext
+    return_type: int
+    arguments:
+      - type: long fract
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: countlshk
+    standards:
+      - stdc_ext
+    return_type: int
+    arguments:
+      - type: short accum
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: countlsk
+    standards:
+      - stdc_ext
+    return_type: int
+    arguments:
+      - type: accum
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: countlslk
+    standards:
+      - stdc_ext
+    return_type: int
+    arguments:
+      - type: long accum
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: countlsuhr
+    standards:
+      - stdc_ext
+    return_type: int
+    arguments:
+      - type: unsigned short fract
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: countlsur
+    standards:
+      - stdc_ext
+    return_type: int
+    arguments:
+      - type: unsigned fract
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: countlsulr
+    standards:
+      - stdc_ext
+    return_type: int
+    arguments:
+      - type: unsigned long fract
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: countlsuhk
+    standards:
+      - stdc_ext
+    return_type: int
+    arguments:
+      - type: unsigned short accum
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: countlsuk
+    standards:
+      - stdc_ext
+    return_type: int
+    arguments:
+      - type: unsigned accum
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: countlsulk
+    standards:
+      - stdc_ext
+    return_type: int
+    arguments:
+      - type: unsigned long accum
+    guard: LIBC_COMPILER_HAS_FIXED_POINT

diff  --git a/libc/src/__support/fixed_point/CMakeLists.txt b/libc/src/__support/fixed_point/CMakeLists.txt
index 3b744081765e4..b415e2c00c488 100644
--- a/libc/src/__support/fixed_point/CMakeLists.txt
+++ b/libc/src/__support/fixed_point/CMakeLists.txt
@@ -19,6 +19,7 @@ add_header_library(
     libc.src.__support.macros.optimization
     libc.src.__support.CPP.type_traits
     libc.src.__support.CPP.bit
+    libc.src.__support.CPP.limits
     libc.src.__support.math_extras
 )
 

diff  --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index 225ea417760a0..7509419da0c43 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -11,9 +11,10 @@
 
 #include "include/llvm-libc-macros/stdfix-macros.h"
 #include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/limits.h" // numeric_limits
 #include "src/__support/CPP/type_traits.h"
-#include "src/__support/macros/attributes.h" // LIBC_INLINE
-#include "src/__support/macros/config.h"
+#include "src/__support/macros/attributes.h"   // LIBC_INLINE
+#include "src/__support/macros/config.h"       // LIBC_NAMESPACE_DECL
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 #include "src/__support/math_extras.h"
 
@@ -50,6 +51,12 @@ template <typename T> struct FXBits {
   static constexpr StorageType SIGN_MASK =
       (fx_rep::SIGN_LEN == 0 ? 0 : StorageType(1) << SIGN_OFFSET);
 
+  // mask for <integral | fraction>
+  static constexpr StorageType VALUE_MASK = INTEGRAL_MASK | FRACTION_MASK;
+
+  // mask for <sign | integral | fraction>
+  static constexpr StorageType TOTAL_MASK = SIGN_MASK | VALUE_MASK;
+
 public:
   LIBC_INLINE constexpr FXBits() = default;
 
@@ -74,6 +81,12 @@ template <typename T> struct FXBits {
     return (value & INTEGRAL_MASK) >> INTEGRAL_OFFSET;
   }
 
+  // returns complete bitstring representation the fixed point number
+  // the bitstring is of the form: padding | sign | integral | fraction
+  LIBC_INLINE constexpr StorageType get_bits() {
+    return (value & TOTAL_MASK) >> FRACTION_OFFSET;
+  }
+
   // TODO: replace bool with Sign
   LIBC_INLINE constexpr bool get_sign() {
     return static_cast<bool>((value & SIGN_MASK) >> SIGN_OFFSET);
@@ -163,6 +176,24 @@ template <typename T> LIBC_INLINE constexpr T round(T x, int n) {
   return bit_and((x + round_bit), rounding_mask);
 }
 
+// count leading sign bits
+// TODO: support fixed_point_padding
+template <typename T>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, int>
+countls(T f) {
+  using FXRep = FXRep<T>;
+  using BitType = typename FXRep::StorageType;
+  using FXBits = FXBits<T>;
+
+  if constexpr (FXRep::SIGN_LEN > 0) {
+    if (f < 0)
+      f = bit_not(f);
+  }
+
+  BitType value_bits = FXBits(f).get_bits();
+  return cpp::countl_zero(value_bits) - FXRep::SIGN_LEN;
+}
+
 } // namespace fixed_point
 } // namespace LIBC_NAMESPACE_DECL
 

diff  --git a/libc/src/__support/fixed_point/fx_rep.h b/libc/src/__support/fixed_point/fx_rep.h
index 186938947694e..7227fffa683a8 100644
--- a/libc/src/__support/fixed_point/fx_rep.h
+++ b/libc/src/__support/fixed_point/fx_rep.h
@@ -43,8 +43,8 @@ template <> struct FXRep<short fract> {
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
   LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SFRACT_FBIT;
-  LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
-      SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN;
 
   LIBC_INLINE static constexpr Type MIN() { return SFRACT_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return SFRACT_MAX; }
@@ -63,8 +63,8 @@ template <> struct FXRep<unsigned short fract> {
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
   LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USFRACT_FBIT;
-  LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
-      SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN;
 
   LIBC_INLINE static constexpr Type MIN() { return USFRACT_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return USFRACT_MAX; }
@@ -83,8 +83,8 @@ template <> struct FXRep<fract> {
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
   LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = FRACT_FBIT;
-  LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
-      SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN;
 
   LIBC_INLINE static constexpr Type MIN() { return FRACT_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return FRACT_MAX; }
@@ -103,8 +103,8 @@ template <> struct FXRep<unsigned fract> {
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
   LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = UFRACT_FBIT;
-  LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
-      SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN;
 
   LIBC_INLINE static constexpr Type MIN() { return UFRACT_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return UFRACT_MAX; }
@@ -123,8 +123,8 @@ template <> struct FXRep<long fract> {
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
   LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = LFRACT_FBIT;
-  LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
-      SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN;
 
   LIBC_INLINE static constexpr Type MIN() { return LFRACT_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return LFRACT_MAX; }
@@ -143,8 +143,8 @@ template <> struct FXRep<unsigned long fract> {
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
   LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ULFRACT_FBIT;
-  LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
-      SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN;
 
   LIBC_INLINE static constexpr Type MIN() { return ULFRACT_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return ULFRACT_MAX; }
@@ -163,8 +163,8 @@ template <> struct FXRep<short accum> {
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
   LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = SACCUM_IBIT;
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SACCUM_FBIT;
-  LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
-      SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN;
 
   LIBC_INLINE static constexpr Type MIN() { return SACCUM_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return SACCUM_MAX; }
@@ -183,8 +183,8 @@ template <> struct FXRep<unsigned short accum> {
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
   LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = USACCUM_IBIT;
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USACCUM_FBIT;
-  LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
-      SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN;
 
   LIBC_INLINE static constexpr Type MIN() { return USACCUM_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return USACCUM_MAX; }
@@ -203,8 +203,8 @@ template <> struct FXRep<accum> {
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
   LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = ACCUM_IBIT;
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ACCUM_FBIT;
-  LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
-      SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN;
 
   LIBC_INLINE static constexpr Type MIN() { return ACCUM_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return ACCUM_MAX; }
@@ -223,8 +223,8 @@ template <> struct FXRep<unsigned accum> {
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
   LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = UACCUM_IBIT;
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = UACCUM_FBIT;
-  LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
-      SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN;
 
   LIBC_INLINE static constexpr Type MIN() { return UACCUM_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return UACCUM_MAX; }
@@ -243,8 +243,8 @@ template <> struct FXRep<long accum> {
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
   LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = LACCUM_IBIT;
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = LACCUM_FBIT;
-  LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
-      SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN;
 
   LIBC_INLINE static constexpr Type MIN() { return LACCUM_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return LACCUM_MAX; }
@@ -263,8 +263,8 @@ template <> struct FXRep<unsigned long accum> {
   LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
   LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = ULACCUM_IBIT;
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ULACCUM_FBIT;
-  LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
-      SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
+  LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN;
 
   LIBC_INLINE static constexpr Type MIN() { return ULACCUM_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return ULACCUM_MAX; }

diff  --git a/libc/src/stdfix/CMakeLists.txt b/libc/src/stdfix/CMakeLists.txt
index 37292d85367fe..6fb06b8d7e9ae 100644
--- a/libc/src/stdfix/CMakeLists.txt
+++ b/libc/src/stdfix/CMakeLists.txt
@@ -47,6 +47,18 @@ foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
       libc.src.__support.CPP.bit
       libc.src.__support.fixed_point.fx_bits
   )
+
+  add_entrypoint_object(
+    countls${suffix}
+    HDRS
+      countls${suffix}.h
+    SRCS
+      countls${suffix}.cpp
+    COMPILE_OPTIONS
+      ${libc_opt_high_flag}
+    DEPENDS
+      libc.src.__support.fixed_point.fx_bits
+  )
 endforeach()
 
 add_entrypoint_object(

diff  --git a/libc/src/stdfix/countlshk.cpp b/libc/src/stdfix/countlshk.cpp
new file mode 100644
index 0000000000000..f94728beff1cb
--- /dev/null
+++ b/libc/src/stdfix/countlshk.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation for countlshk function  ----------------------------===//
+//
+// 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 "countlshk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlshk, (short accum f)) {
+  return fixed_point::countls(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/stdfix/countlshk.h b/libc/src/stdfix/countlshk.h
new file mode 100644
index 0000000000000..ab334244e166a
--- /dev/null
+++ b/libc/src/stdfix/countlshk.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for countlshk function ------------*- 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_STDFIX_COUNTLSHK_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSHK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlshk(short accum f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSHK_H

diff  --git a/libc/src/stdfix/countlshr.cpp b/libc/src/stdfix/countlshr.cpp
new file mode 100644
index 0000000000000..d77d3e9a3c22a
--- /dev/null
+++ b/libc/src/stdfix/countlshr.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation for countlshr function  ----------------------------===//
+//
+// 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 "countlshr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlshr, (short fract f)) {
+  return fixed_point::countls(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/stdfix/countlshr.h b/libc/src/stdfix/countlshr.h
new file mode 100644
index 0000000000000..579b7b680406e
--- /dev/null
+++ b/libc/src/stdfix/countlshr.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for countlshr function ------------*- 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_STDFIX_COUNTLSHR_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSHR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlshr(short fract f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSHR_H

diff  --git a/libc/src/stdfix/countlsk.cpp b/libc/src/stdfix/countlsk.cpp
new file mode 100644
index 0000000000000..b6f56adee16a6
--- /dev/null
+++ b/libc/src/stdfix/countlsk.cpp
@@ -0,0 +1,18 @@
+//===-- Implementation for countlsk function  -----------------------------===//
+//
+// 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 "countlsk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsk, (accum f)) { return fixed_point::countls(f); }
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/stdfix/countlsk.h b/libc/src/stdfix/countlsk.h
new file mode 100644
index 0000000000000..d0c893bc078d5
--- /dev/null
+++ b/libc/src/stdfix/countlsk.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for countlsk function -------------*- 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_STDFIX_COUNTLSK_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsk(accum f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSK_H

diff  --git a/libc/src/stdfix/countlslk.cpp b/libc/src/stdfix/countlslk.cpp
new file mode 100644
index 0000000000000..9bf30ff34c6ee
--- /dev/null
+++ b/libc/src/stdfix/countlslk.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation for countlslk function  ----------------------------===//
+//
+// 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 "countlslk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlslk, (long accum f)) {
+  return fixed_point::countls(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/stdfix/countlslk.h b/libc/src/stdfix/countlslk.h
new file mode 100644
index 0000000000000..60fa469797b7a
--- /dev/null
+++ b/libc/src/stdfix/countlslk.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for countlslk function ------------*- 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_STDFIX_COUNTLSLK_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSLK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlslk(long accum f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSLK_H

diff  --git a/libc/src/stdfix/countlslr.cpp b/libc/src/stdfix/countlslr.cpp
new file mode 100644
index 0000000000000..774023c734a37
--- /dev/null
+++ b/libc/src/stdfix/countlslr.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation for countlslr function  ----------------------------===//
+//
+// 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 "countlslr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlslr, (long fract f)) {
+  return fixed_point::countls(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/stdfix/countlslr.h b/libc/src/stdfix/countlslr.h
new file mode 100644
index 0000000000000..c909551e77a1a
--- /dev/null
+++ b/libc/src/stdfix/countlslr.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for countlslr function ------------*- 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_STDFIX_COUNTLSLR_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSLR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlslr(long fract f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSLR_H

diff  --git a/libc/src/stdfix/countlsr.cpp b/libc/src/stdfix/countlsr.cpp
new file mode 100644
index 0000000000000..14563127ad5e9
--- /dev/null
+++ b/libc/src/stdfix/countlsr.cpp
@@ -0,0 +1,18 @@
+//===-- Implementation for countlsr function  -----------------------------===//
+//
+// 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 "countlsr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsr, (fract f)) { return fixed_point::countls(f); }
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/stdfix/countlsr.h b/libc/src/stdfix/countlsr.h
new file mode 100644
index 0000000000000..75dcf4aff0ca3
--- /dev/null
+++ b/libc/src/stdfix/countlsr.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for countlsr function -------------*- 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_STDFIX_COUNTLSR_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsr(fract f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSR_H

diff  --git a/libc/src/stdfix/countlsuhk.cpp b/libc/src/stdfix/countlsuhk.cpp
new file mode 100644
index 0000000000000..2cc266f47da1f
--- /dev/null
+++ b/libc/src/stdfix/countlsuhk.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation for countlsuhk function  ---------------------------===//
+//
+// 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 "countlsuhk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsuhk, (unsigned short accum f)) {
+  return fixed_point::countls(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/stdfix/countlsuhk.h b/libc/src/stdfix/countlsuhk.h
new file mode 100644
index 0000000000000..fcb2fec3500d4
--- /dev/null
+++ b/libc/src/stdfix/countlsuhk.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for countlsuhk function -----------*- 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_STDFIX_COUNTLSUHK_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSUHK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsuhk(unsigned short accum f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSUHK_H

diff  --git a/libc/src/stdfix/countlsuhr.cpp b/libc/src/stdfix/countlsuhr.cpp
new file mode 100644
index 0000000000000..f30b0dd731aa9
--- /dev/null
+++ b/libc/src/stdfix/countlsuhr.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation for countlsuhr function  ---------------------------===//
+//
+// 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 "countlsuhr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsuhr, (unsigned short fract f)) {
+  return fixed_point::countls(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/stdfix/countlsuhr.h b/libc/src/stdfix/countlsuhr.h
new file mode 100644
index 0000000000000..b60132dc7f22b
--- /dev/null
+++ b/libc/src/stdfix/countlsuhr.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for countlsuhr function -----------*- 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_STDFIX_COUNTLSUHR_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSUHR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsuhr(unsigned short fract f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSUHR_H

diff  --git a/libc/src/stdfix/countlsuk.cpp b/libc/src/stdfix/countlsuk.cpp
new file mode 100644
index 0000000000000..90617cfeb5cdc
--- /dev/null
+++ b/libc/src/stdfix/countlsuk.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation for countlsuk function  ----------------------------===//
+//
+// 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 "countlsuk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsuk, (unsigned accum f)) {
+  return fixed_point::countls(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/stdfix/countlsuk.h b/libc/src/stdfix/countlsuk.h
new file mode 100644
index 0000000000000..7ad0e701b927b
--- /dev/null
+++ b/libc/src/stdfix/countlsuk.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for countlsuk function ------------*- 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_STDFIX_COUNTLSUK_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSUK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsuk(unsigned accum f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSUK_H

diff  --git a/libc/src/stdfix/countlsulk.cpp b/libc/src/stdfix/countlsulk.cpp
new file mode 100644
index 0000000000000..04090dd86c732
--- /dev/null
+++ b/libc/src/stdfix/countlsulk.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation for countlsulk function  ---------------------------===//
+//
+// 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 "countlsulk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsulk, (unsigned long accum f)) {
+  return fixed_point::countls(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/stdfix/countlsulk.h b/libc/src/stdfix/countlsulk.h
new file mode 100644
index 0000000000000..55ca9d2e20ff0
--- /dev/null
+++ b/libc/src/stdfix/countlsulk.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for countlsulk function -----------*- 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_STDFIX_COUNTLSULK_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSULK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsulk(unsigned long accum f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSULK_H

diff  --git a/libc/src/stdfix/countlsulr.cpp b/libc/src/stdfix/countlsulr.cpp
new file mode 100644
index 0000000000000..d9d6ff404c211
--- /dev/null
+++ b/libc/src/stdfix/countlsulr.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation for countlsulr function  ---------------------------===//
+//
+// 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 "countlsulr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsulr, (unsigned long fract f)) {
+  return fixed_point::countls(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/stdfix/countlsulr.h b/libc/src/stdfix/countlsulr.h
new file mode 100644
index 0000000000000..59e7d726d01b9
--- /dev/null
+++ b/libc/src/stdfix/countlsulr.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for countlsulr function -----------*- 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_STDFIX_COUNTLSULR_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSULR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsulr(unsigned long fract f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSULR_H

diff  --git a/libc/src/stdfix/countlsur.cpp b/libc/src/stdfix/countlsur.cpp
new file mode 100644
index 0000000000000..777e5f387aadf
--- /dev/null
+++ b/libc/src/stdfix/countlsur.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation for countlsur function  ----------------------------===//
+//
+// 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 "countlsur.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsur, (unsigned fract f)) {
+  return fixed_point::countls(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/stdfix/countlsur.h b/libc/src/stdfix/countlsur.h
new file mode 100644
index 0000000000000..1d34e971a52b3
--- /dev/null
+++ b/libc/src/stdfix/countlsur.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for countlsur function ------------*- 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_STDFIX_COUNTLSUR_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSUR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsur(unsigned fract f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSUR_H

diff  --git a/libc/test/src/stdfix/CMakeLists.txt b/libc/test/src/stdfix/CMakeLists.txt
index e4d4fc5b52558..8f0226bf41672 100644
--- a/libc/test/src/stdfix/CMakeLists.txt
+++ b/libc/test/src/stdfix/CMakeLists.txt
@@ -73,6 +73,20 @@ foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
       libc.src.__support.CPP.bit
       libc.src.__support.fixed_point.fx_bits
   )
+
+  add_libc_test(
+    countls${suffix}_test
+    SUITE
+      libc-stdfix-tests
+    HDRS
+      CountlsTest.h
+    SRCS
+      countls${suffix}_test.cpp
+    DEPENDS
+      libc.src.stdfix.countls${suffix}
+      libc.src.__support.fixed_point.fx_rep
+      libc.src.__support.fixed_point.fx_bits
+  )
 endforeach()
 
 add_libc_test(

diff  --git a/libc/test/src/stdfix/CountlsTest.h b/libc/test/src/stdfix/CountlsTest.h
new file mode 100644
index 0000000000000..a8201acb455b5
--- /dev/null
+++ b/libc/test/src/stdfix/CountlsTest.h
@@ -0,0 +1,58 @@
+//===-- Utility class to test countls -------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "test/UnitTest/Test.h"
+
+#include "src/__support/fixed_point/fx_rep.h"
+
+template <typename T> class CountlsTest : public LIBC_NAMESPACE::testing::Test {
+
+  using FXRep = LIBC_NAMESPACE::fixed_point::FXRep<T>;
+  static constexpr T zero = FXRep::ZERO();
+  static constexpr T max = FXRep::MAX();
+  static constexpr T min = FXRep::MIN();
+  static constexpr T one_half = FXRep::ONE_HALF();
+  static constexpr T one_fourth = FXRep::ONE_FOURTH();
+  static constexpr T eps = FXRep::EPS();
+
+public:
+  typedef int (*CountlsFunc)(T);
+
+  void testSpecialNumbers(CountlsFunc func) {
+    constexpr bool is_signed = (FXRep::SIGN_LEN > 0);
+
+    EXPECT_EQ(FXRep::INTEGRAL_LEN, func(one_half));
+    EXPECT_EQ(FXRep::INTEGRAL_LEN + 1, func(one_fourth));
+    EXPECT_EQ(FXRep::VALUE_LEN, func(zero));
+    EXPECT_EQ(FXRep::VALUE_LEN - 1, func(eps));
+    EXPECT_EQ(0, func(max));
+    // If signed, left shifting the minimum value will overflow, so countls = 0.
+    // If unsigned, the minimum value is zero, so countls is the number of value
+    // bits according to ISO/IEC TR 18037.
+    EXPECT_EQ(is_signed ? 0 : FXRep::VALUE_LEN, func(min));
+
+    if (10 <= static_cast<int>(max))
+      EXPECT_EQ(FXRep::INTEGRAL_LEN - 4, func(10));
+
+    if (static_cast<int>(min) <= -10)
+      EXPECT_EQ(FXRep::INTEGRAL_LEN - 4, func(-10));
+
+    if constexpr (is_signed) {
+      EXPECT_EQ(FXRep::VALUE_LEN, func(-zero));
+      EXPECT_EQ(FXRep::VALUE_LEN, func(-eps));
+      EXPECT_EQ(FXRep::INTEGRAL_LEN + 1, func(-one_half));
+      if (FXRep::FRACTION_LEN >= 2)
+        EXPECT_EQ(FXRep::INTEGRAL_LEN + 2, func(-one_fourth));
+    }
+  }
+};
+
+#define LIST_COUNTLS_TESTS(T, func)                                            \
+  using LlvmLibcCountlsTest = CountlsTest<T>;                                  \
+  TEST_F(LlvmLibcCountlsTest, SpecialNumbers) { testSpecialNumbers(&func); }   \
+  static_assert(true, "Require semicolon.")

diff  --git a/libc/test/src/stdfix/countlshk_test.cpp b/libc/test/src/stdfix/countlshk_test.cpp
new file mode 100644
index 0000000000000..659f869706b5f
--- /dev/null
+++ b/libc/test/src/stdfix/countlshk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for countlshk -------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlshk.h"
+
+LIST_COUNTLS_TESTS(short accum, LIBC_NAMESPACE::countlshk);

diff  --git a/libc/test/src/stdfix/countlshr_test.cpp b/libc/test/src/stdfix/countlshr_test.cpp
new file mode 100644
index 0000000000000..361d4acab3b11
--- /dev/null
+++ b/libc/test/src/stdfix/countlshr_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for countlshr -------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlshr.h"
+
+LIST_COUNTLS_TESTS(short fract, LIBC_NAMESPACE::countlshr);

diff  --git a/libc/test/src/stdfix/countlsk_test.cpp b/libc/test/src/stdfix/countlsk_test.cpp
new file mode 100644
index 0000000000000..74cb519ec78de
--- /dev/null
+++ b/libc/test/src/stdfix/countlsk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for countlsk --------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsk.h"
+
+LIST_COUNTLS_TESTS(accum, LIBC_NAMESPACE::countlsk);

diff  --git a/libc/test/src/stdfix/countlslk_test.cpp b/libc/test/src/stdfix/countlslk_test.cpp
new file mode 100644
index 0000000000000..006939db3c87e
--- /dev/null
+++ b/libc/test/src/stdfix/countlslk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for countlslk -------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlslk.h"
+
+LIST_COUNTLS_TESTS(long accum, LIBC_NAMESPACE::countlslk);

diff  --git a/libc/test/src/stdfix/countlslr_test.cpp b/libc/test/src/stdfix/countlslr_test.cpp
new file mode 100644
index 0000000000000..896cf9259c3ea
--- /dev/null
+++ b/libc/test/src/stdfix/countlslr_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for countlslr -------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlslr.h"
+
+LIST_COUNTLS_TESTS(long fract, LIBC_NAMESPACE::countlslr);

diff  --git a/libc/test/src/stdfix/countlsr_test.cpp b/libc/test/src/stdfix/countlsr_test.cpp
new file mode 100644
index 0000000000000..d7ae91ccd6a92
--- /dev/null
+++ b/libc/test/src/stdfix/countlsr_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for countlsr --------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsr.h"
+
+LIST_COUNTLS_TESTS(fract, LIBC_NAMESPACE::countlsr);

diff  --git a/libc/test/src/stdfix/countlsuhk_test.cpp b/libc/test/src/stdfix/countlsuhk_test.cpp
new file mode 100644
index 0000000000000..d8e68d65160e7
--- /dev/null
+++ b/libc/test/src/stdfix/countlsuhk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for countlsuhk ------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsuhk.h"
+
+LIST_COUNTLS_TESTS(unsigned short accum, LIBC_NAMESPACE::countlsuhk);

diff  --git a/libc/test/src/stdfix/countlsuhr_test.cpp b/libc/test/src/stdfix/countlsuhr_test.cpp
new file mode 100644
index 0000000000000..7dbc590d4a552
--- /dev/null
+++ b/libc/test/src/stdfix/countlsuhr_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for countlsuhr ------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsuhr.h"
+
+LIST_COUNTLS_TESTS(unsigned short fract, LIBC_NAMESPACE::countlsuhr);

diff  --git a/libc/test/src/stdfix/countlsuk_test.cpp b/libc/test/src/stdfix/countlsuk_test.cpp
new file mode 100644
index 0000000000000..20f78d8c942b6
--- /dev/null
+++ b/libc/test/src/stdfix/countlsuk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for countlsuk -------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsuk.h"
+
+LIST_COUNTLS_TESTS(unsigned accum, LIBC_NAMESPACE::countlsuk);

diff  --git a/libc/test/src/stdfix/countlsulk_test.cpp b/libc/test/src/stdfix/countlsulk_test.cpp
new file mode 100644
index 0000000000000..81ae208055cd9
--- /dev/null
+++ b/libc/test/src/stdfix/countlsulk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for countlsulk ------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsulk.h"
+
+LIST_COUNTLS_TESTS(unsigned long accum, LIBC_NAMESPACE::countlsulk);

diff  --git a/libc/test/src/stdfix/countlsulr_test.cpp b/libc/test/src/stdfix/countlsulr_test.cpp
new file mode 100644
index 0000000000000..5b9b047f7fd74
--- /dev/null
+++ b/libc/test/src/stdfix/countlsulr_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for countlsulr ------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsulr.h"
+
+LIST_COUNTLS_TESTS(unsigned long fract, LIBC_NAMESPACE::countlsulr);

diff  --git a/libc/test/src/stdfix/countlsur_test.cpp b/libc/test/src/stdfix/countlsur_test.cpp
new file mode 100644
index 0000000000000..67e32d7b56217
--- /dev/null
+++ b/libc/test/src/stdfix/countlsur_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for countlsur -------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsur.h"
+
+LIST_COUNTLS_TESTS(unsigned fract, LIBC_NAMESPACE::countlsur);


        


More information about the libc-commits mailing list