Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc][stdfix] Implement countlsfx functions #114318

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

duncpro
Copy link

@duncpro duncpro commented Oct 30, 2024

Closes #113357

Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added the libc label Oct 30, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Oct 30, 2024

@llvm/pr-subscribers-libc

Author: Duncan (duncpro)

Changes

Closes #113357


Patch is 47.32 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/114318.diff

47 Files Affected:

  • (modified) libc/config/baremetal/arm/entrypoints.txt (+12)
  • (modified) libc/config/baremetal/riscv/entrypoints.txt (+12)
  • (modified) libc/config/linux/riscv/entrypoints.txt (+12)
  • (modified) libc/config/linux/x86_64/entrypoints.txt (+12)
  • (modified) libc/spec/stdc_ext.td (+17)
  • (modified) libc/src/__support/fixed_point/CMakeLists.txt (+1)
  • (modified) libc/src/__support/fixed_point/fx_bits.h (+38-1)
  • (modified) libc/src/__support/fixed_point/fx_rep.h (+12)
  • (modified) libc/src/stdfix/CMakeLists.txt (+14)
  • (added) libc/src/stdfix/countlshk.cpp (+20)
  • (added) libc/src/stdfix/countlshk.h (+21)
  • (added) libc/src/stdfix/countlshr.cpp (+20)
  • (added) libc/src/stdfix/countlshr.h (+21)
  • (added) libc/src/stdfix/countlsk.cpp (+18)
  • (added) libc/src/stdfix/countlsk.h (+21)
  • (added) libc/src/stdfix/countlslk.cpp (+20)
  • (added) libc/src/stdfix/countlslk.h (+21)
  • (added) libc/src/stdfix/countlslr.cpp (+20)
  • (added) libc/src/stdfix/countlslr.h (+21)
  • (added) libc/src/stdfix/countlsr.cpp (+18)
  • (added) libc/src/stdfix/countlsr.h (+21)
  • (added) libc/src/stdfix/countlsuhk.cpp (+20)
  • (added) libc/src/stdfix/countlsuhk.h (+21)
  • (added) libc/src/stdfix/countlsuhr.cpp (+20)
  • (added) libc/src/stdfix/countlsuhr.h (+21)
  • (added) libc/src/stdfix/countlsuk.cpp (+20)
  • (added) libc/src/stdfix/countlsuk.h (+21)
  • (added) libc/src/stdfix/countlsulk.cpp (+20)
  • (added) libc/src/stdfix/countlsulk.h (+21)
  • (added) libc/src/stdfix/countlsulr.cpp (+20)
  • (added) libc/src/stdfix/countlsulr.h (+21)
  • (added) libc/src/stdfix/countlsur.cpp (+20)
  • (added) libc/src/stdfix/countlsur.h (+21)
  • (modified) libc/test/src/stdfix/CMakeLists.txt (+17)
  • (added) libc/test/src/stdfix/CountlsTest.h (+48)
  • (added) libc/test/src/stdfix/countlshk_test.cpp (+13)
  • (added) libc/test/src/stdfix/countlshr_test.cpp (+13)
  • (added) libc/test/src/stdfix/countlsk_test.cpp (+13)
  • (added) libc/test/src/stdfix/countlslk_test.cpp (+13)
  • (added) libc/test/src/stdfix/countlslr_test.cpp (+13)
  • (added) libc/test/src/stdfix/countlsr_test.cpp (+13)
  • (added) libc/test/src/stdfix/countlsuhk_test.cpp (+13)
  • (added) libc/test/src/stdfix/countlsuhr_test.cpp (+13)
  • (added) libc/test/src/stdfix/countlsuk_test.cpp (+13)
  • (added) libc/test/src/stdfix/countlsulk_test.cpp (+13)
  • (added) libc/test/src/stdfix/countlsulr_test.cpp (+13)
  • (added) libc/test/src/stdfix/countlsur_test.cpp (+13)
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 68030f7f1775b5..55af5413259a30 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -427,6 +427,18 @@ set(TARGET_LIBM_ENTRYPOINTS
 if(LIBC_COMPILER_HAS_FIXED_POINT)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
     # stdfix.h _Fract and _Accum entrypoints
+    libc.src.stdfix.countlshk
+    libc.src.stdfix.countlshr
+    libc.src.stdfix.countlsk
+    libc.src.stdfix.countlslk
+    libc.src.stdfix.countlslr
+    libc.src.stdfix.countlsr
+    libc.src.stdfix.countlsuhk
+    libc.src.stdfix.countlsuhr
+    libc.src.stdfix.countlsuk
+    libc.src.stdfix.countlsulk
+    libc.src.stdfix.countlsulr
+    libc.src.stdfix.countlsur
     libc.src.stdfix.abshk
     libc.src.stdfix.abshr
     libc.src.stdfix.absk
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 5894b591072ef0..baa4b27b98aee0 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -422,6 +422,18 @@ set(TARGET_LIBM_ENTRYPOINTS
 if(LIBC_COMPILER_HAS_FIXED_POINT)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
     # stdfix.h _Fract and _Accum entrypoints
+    libc.src.stdfix.countlshk
+    libc.src.stdfix.countlshr
+    libc.src.stdfix.countlsk
+    libc.src.stdfix.countlslk
+    libc.src.stdfix.countlslr
+    libc.src.stdfix.countlsr
+    libc.src.stdfix.countlsuhk
+    libc.src.stdfix.countlsuhr
+    libc.src.stdfix.countlsuk
+    libc.src.stdfix.countlsulk
+    libc.src.stdfix.countlsulr
+    libc.src.stdfix.countlsur
     libc.src.stdfix.abshk
     libc.src.stdfix.abshr
     libc.src.stdfix.absk
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 5c09edf7cfb266..cbbe9d226e05f9 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -677,6 +677,18 @@ endif()
 if(LIBC_COMPILER_HAS_FIXED_POINT)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
     # stdfix.h _Fract and _Accum entrypoints
+    libc.src.stdfix.countlshk
+    libc.src.stdfix.countlshr
+    libc.src.stdfix.countlsk
+    libc.src.stdfix.countlslk
+    libc.src.stdfix.countlslr
+    libc.src.stdfix.countlsr
+    libc.src.stdfix.countlsuhk
+    libc.src.stdfix.countlsuhr
+    libc.src.stdfix.countlsuk
+    libc.src.stdfix.countlsulk
+    libc.src.stdfix.countlsulr
+    libc.src.stdfix.countlsur
     libc.src.stdfix.abshk
     libc.src.stdfix.abshr
     libc.src.stdfix.absk
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index a2fb97d04584d5..c0bf1ce50328e5 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -780,6 +780,18 @@ endif()
 if(LIBC_COMPILER_HAS_FIXED_POINT)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
     # stdfix.h _Fract and _Accum entrypoints
+    libc.src.stdfix.countlshk
+    libc.src.stdfix.countlshr
+    libc.src.stdfix.countlsk
+    libc.src.stdfix.countlslk
+    libc.src.stdfix.countlslr
+    libc.src.stdfix.countlsr
+    libc.src.stdfix.countlsuhk
+    libc.src.stdfix.countlsuhr
+    libc.src.stdfix.countlsuk
+    libc.src.stdfix.countlsulk
+    libc.src.stdfix.countlsulr
+    libc.src.stdfix.countlsur
     libc.src.stdfix.abshk
     libc.src.stdfix.abshr
     libc.src.stdfix.absk
diff --git a/libc/spec/stdc_ext.td b/libc/spec/stdc_ext.td
index 6620142146c471..26f2d526168ce7 100644
--- a/libc/spec/stdc_ext.td
+++ b/libc/spec/stdc_ext.td
@@ -24,6 +24,23 @@ def StdcExt : StandardSpec<"stdc_ext"> {
       [],  // types
       [],  // enums
       [    // functions
+
+          GuardedFunctionSpec<"countlshr", RetValSpec<ShortFractType>, [ArgSpec<ShortFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"countlsr", RetValSpec<FractType>, [ArgSpec<FractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"countlslr", RetValSpec<LongFractType>, [ArgSpec<LongFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
+          GuardedFunctionSpec<"countlshk", RetValSpec<ShortAccumType>, [ArgSpec<ShortAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"countlsk", RetValSpec<AccumType>, [ArgSpec<AccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"countlslk", RetValSpec<LongAccumType>, [ArgSpec<LongAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
+          GuardedFunctionSpec<"countlsuhr", RetValSpec<UnsignedShortFractType>, [ArgSpec<UnsignedShortFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"countlsur", RetValSpec<UnsignedFractType>, [ArgSpec<UnsignedFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"countlsulr", RetValSpec<UnsignedLongFractType>, [ArgSpec<UnsignedLongFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
+          GuardedFunctionSpec<"countlsuhk", RetValSpec<UnsignedShortAccumType>, [ArgSpec<UnsignedShortAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"countlsuk", RetValSpec<UnsignedAccumType>, [ArgSpec<UnsignedAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"countlsulk", RetValSpec<UnsignedLongAccumType>, [ArgSpec<UnsignedLongAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+  
           GuardedFunctionSpec<"abshr", RetValSpec<ShortFractType>, [ArgSpec<ShortFractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
           GuardedFunctionSpec<"absr", RetValSpec<FractType>, [ArgSpec<FractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
           GuardedFunctionSpec<"abslr", RetValSpec<LongFractType>, [ArgSpec<LongFractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
diff --git a/libc/src/__support/fixed_point/CMakeLists.txt b/libc/src/__support/fixed_point/CMakeLists.txt
index 3b744081765e4f..2531285d5c9cb2 100644
--- a/libc/src/__support/fixed_point/CMakeLists.txt
+++ b/libc/src/__support/fixed_point/CMakeLists.txt
@@ -20,6 +20,7 @@ add_header_library(
     libc.src.__support.CPP.type_traits
     libc.src.__support.CPP.bit
     libc.src.__support.math_extras
+    libc.src.__support.CPP.limits
 )
 
 add_header_library(
diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index 0a4c21fb6a14f7..3ff5cc7011fb89 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -11,8 +11,9 @@
 
 #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/attributes.h" // LIBC_INLINE
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 #include "src/__support/math_extras.h"
@@ -66,6 +67,23 @@ template <typename T> struct FXBits {
     }
   }
 
+  // Clause 6.2.6.3 of ISO/IEC TR 18037 defines the value bits of a fixed-point
+  // type to include the integral and fraction bits but not padding nor sign
+  // bits.
+  //
+  // This function returns the value bits, right-aligned, as an unsigned integer
+  // type which is at least large enough to hold them all.
+  //
+  // Note the integral and fraction bits are contiguous. The rightmost bits in
+  // the returned value are the fraciton bits, then immediately left of those
+  // are the integral bits.
+  //
+  // Any left-padding in the return value is guaranteed to be zero.
+  LIBC_INLINE constexpr StorageType get_value_bits() {
+    constexpr StorageType VALUE_MASK = INTEGRAL_MASK | FRACTION_MASK;
+    return (value & VALUE_MASK) >> FRACTION_OFFSET;
+  }
+
   LIBC_INLINE constexpr StorageType get_fraction() {
     return (value & FRACTION_MASK) >> FRACTION_OFFSET;
   }
@@ -142,6 +160,25 @@ template <typename T> LIBC_INLINE constexpr T abs(T x) {
   }
 }
 
+template <typename T>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, int>
+countls(T x) {
+  using FXRep = FXRep<T>;
+  using BitType = typename FXRep::StorageType;
+  constexpr int CONTAIN_LEN = cpp::numeric_limits<BitType>::digits;
+  constexpr int PADDING_LEN = CONTAIN_LEN - FXRep::VALUE_LEN;
+
+  if constexpr (FXRep::SIGN_LEN != 0) {
+    if (x < 0) {
+      x = abs(x + FXRep::EPS());
+    }
+  }
+
+  FXBits<T> fxbits(x);
+  BitType value_bits = fxbits.get_value_bits();
+  return cpp::countl_zero(value_bits) - PADDING_LEN;
+}
+
 // Round-to-nearest, tie-to-(+Inf)
 template <typename T> LIBC_INLINE constexpr T round(T x, int n) {
   using FXRep = FXRep<T>;
diff --git a/libc/src/__support/fixed_point/fx_rep.h b/libc/src/__support/fixed_point/fx_rep.h
index 186938947694e5..f1321e6a629ee5 100644
--- a/libc/src/__support/fixed_point/fx_rep.h
+++ b/libc/src/__support/fixed_point/fx_rep.h
@@ -45,6 +45,7 @@ template <> struct FXRep<short fract> {
   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 static constexpr Type MIN() { return SFRACT_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return SFRACT_MAX; }
@@ -65,6 +66,7 @@ template <> struct FXRep<unsigned short fract> {
   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 static constexpr Type MIN() { return USFRACT_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return USFRACT_MAX; }
@@ -85,6 +87,7 @@ template <> struct FXRep<fract> {
   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 static constexpr Type MIN() { return FRACT_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return FRACT_MAX; }
@@ -105,6 +108,7 @@ template <> struct FXRep<unsigned fract> {
   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 static constexpr Type MIN() { return UFRACT_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return UFRACT_MAX; }
@@ -125,6 +129,7 @@ template <> struct FXRep<long fract> {
   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 static constexpr Type MIN() { return LFRACT_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return LFRACT_MAX; }
@@ -145,6 +150,7 @@ template <> struct FXRep<unsigned long fract> {
   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 static constexpr Type MIN() { return ULFRACT_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return ULFRACT_MAX; }
@@ -165,6 +171,7 @@ template <> struct FXRep<short accum> {
   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 static constexpr Type MIN() { return SACCUM_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return SACCUM_MAX; }
@@ -185,6 +192,7 @@ template <> struct FXRep<unsigned short accum> {
   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 static constexpr Type MIN() { return USACCUM_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return USACCUM_MAX; }
@@ -205,6 +213,7 @@ template <> struct FXRep<accum> {
   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 static constexpr Type MIN() { return ACCUM_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return ACCUM_MAX; }
@@ -225,6 +234,7 @@ template <> struct FXRep<unsigned accum> {
   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 static constexpr Type MIN() { return UACCUM_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return UACCUM_MAX; }
@@ -245,6 +255,7 @@ template <> struct FXRep<long accum> {
   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 static constexpr Type MIN() { return LACCUM_MIN; }
   LIBC_INLINE static constexpr Type MAX() { return LACCUM_MAX; }
@@ -265,6 +276,7 @@ template <> struct FXRep<unsigned long accum> {
   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 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 10d76ae31349f9..69e0117effb50d 100644
--- a/libc/src/stdfix/CMakeLists.txt
+++ b/libc/src/stdfix/CMakeLists.txt
@@ -2,6 +2,20 @@ if(NOT LIBC_COMPILER_HAS_FIXED_POINT)
   return()
 endif()
 
+foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
+  add_entrypoint_object(
+    countls${suffix}
+    HDRS
+      countls${suffix}.h
+    SRCS
+      countls${suffix}.cpp
+    COMPILE_OPTIONS
+      -O3
+    DEPENDS
+      libc.src.__support.fixed_point.fx_bits
+  )
+endforeach()
+
 foreach(suffix IN ITEMS hr r lr hk k lk)
   add_entrypoint_object(
     abs${suffix}
diff --git a/libc/src/stdfix/countlshk.cpp b/libc/src/stdfix/countlshk.cpp
new file mode 100644
index 00000000000000..d65d96312c0768
--- /dev/null
+++ b/libc/src/stdfix/countlshk.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlshk, (short accum x)) {
+  return fixed_point::countls(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlshk.h b/libc/src/stdfix/countlshk.h
new file mode 100644
index 00000000000000..279fb985552347
--- /dev/null
+++ b/libc/src/stdfix/countlshk.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlshk(short accum x);
+
+} // 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 00000000000000..ed3fd23e0cdf8f
--- /dev/null
+++ b/libc/src/stdfix/countlshr.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlshr, (short fract x)) {
+  return fixed_point::countls(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlshr.h b/libc/src/stdfix/countlshr.h
new file mode 100644
index 00000000000000..a2307ee0656ced
--- /dev/null
+++ b/libc/src/stdfix/countlshr.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlshr(short fract x);
+
+} // 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 00000000000000..470f2e28539c16
--- /dev/null
+++ b/libc/src/stdfix/countlsk.cpp
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsk, (accum x)) { return fixed_point::countls(x); }
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlsk.h b/libc/src/stdfix/countlsk.h
new file mode 100644
index 00000000000000..fff9bed7499c5b
--- /dev/null
+++ b/libc/src/stdfix/countlsk.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsk(accum x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSK_H
diff --git a/libc/src/stdfix/countlsl...
[truncated]

@lntue lntue changed the title [libc] implement countlsfx functions [libc][stdfix] Implement countlsfx functions Oct 30, 2024
@lntue lntue self-requested a review October 31, 2024 00:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement fixed point countls functions in llvm-libc
2 participants