Skip to content

[libc][stdfix] Implement fixed point bitsfx functions in llvm libc #128413

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

Merged
merged 19 commits into from
Feb 27, 2025

Conversation

krishna2803
Copy link
Contributor

@krishna2803 krishna2803 commented Feb 23, 2025

Fixes #113359

@llvmbot llvmbot added the libc label Feb 23, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 23, 2025

@llvm/pr-subscribers-libc

Author: Krishna Pandey (krishna2803)

Changes

Fixes #113359


Patch is 48.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/128413.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/docs/headers/math/stdfix.rst (+1-1)
  • (modified) libc/include/stdfix.yaml (+84)
  • (modified) libc/src/__support/fixed_point/fx_bits.h (+10-3)
  • (modified) libc/src/stdfix/CMakeLists.txt (+14)
  • (added) libc/src/stdfix/bitshk.cpp (+22)
  • (added) libc/src/stdfix/bitshk.h (+22)
  • (added) libc/src/stdfix/bitshr.cpp (+22)
  • (added) libc/src/stdfix/bitshr.h (+22)
  • (added) libc/src/stdfix/bitsk.cpp (+22)
  • (added) libc/src/stdfix/bitsk.h (+22)
  • (added) libc/src/stdfix/bitslk.cpp (+22)
  • (added) libc/src/stdfix/bitslk.h (+22)
  • (added) libc/src/stdfix/bitslr.cpp (+22)
  • (added) libc/src/stdfix/bitslr.h (+22)
  • (added) libc/src/stdfix/bitsr.cpp (+22)
  • (added) libc/src/stdfix/bitsr.h (+22)
  • (added) libc/src/stdfix/bitsuhk.cpp (+22)
  • (added) libc/src/stdfix/bitsuhk.h (+22)
  • (added) libc/src/stdfix/bitsuhr.cpp (+22)
  • (added) libc/src/stdfix/bitsuhr.h (+22)
  • (added) libc/src/stdfix/bitsuk.cpp (+22)
  • (added) libc/src/stdfix/bitsuk.h (+22)
  • (added) libc/src/stdfix/bitsulk.cpp (+22)
  • (added) libc/src/stdfix/bitsulk.h (+22)
  • (added) libc/src/stdfix/bitsulr.cpp (+22)
  • (added) libc/src/stdfix/bitsulr.h (+22)
  • (added) libc/src/stdfix/bitsur.cpp (+22)
  • (added) libc/src/stdfix/bitsur.h (+22)
  • (added) libc/src/stdfix/bitusk.cpp (+22)
  • (added) libc/test/src/stdfix/BitsFxTest.h (+56)
  • (modified) libc/test/src/stdfix/CMakeLists.txt (+16)
  • (added) libc/test/src/stdfix/bitshk_test.cpp (+14)
  • (added) libc/test/src/stdfix/bitshr_test.cpp (+14)
  • (added) libc/test/src/stdfix/bitsk_test.cpp (+14)
  • (added) libc/test/src/stdfix/bitslk_test.cpp (+14)
  • (added) libc/test/src/stdfix/bitslr_test.cpp (+14)
  • (added) libc/test/src/stdfix/bitsr_test.cpp (+14)
  • (added) libc/test/src/stdfix/bitsuhk_test.cpp (+15)
  • (added) libc/test/src/stdfix/bitsuhr_test.cpp (+15)
  • (added) libc/test/src/stdfix/bitsuk_test.cpp (+14)
  • (added) libc/test/src/stdfix/bitsulk_test.cpp (+15)
  • (added) libc/test/src/stdfix/bitsulr_test.cpp (+15)
  • (added) libc/test/src/stdfix/bitsur_test.cpp (+14)
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 370b5462fe9e8..97705960e7b54 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -507,6 +507,18 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
     libc.src.stdfix.ukbits
     libc.src.stdfix.lkbits
     libc.src.stdfix.ulkbits
+    libc.src.stdfix.bitshr
+    libc.src.stdfix.bitsr
+    libc.src.stdfix.bitslr
+    libc.src.stdfix.bitshk
+    libc.src.stdfix.bitsk
+    libc.src.stdfix.bitslk
+    libc.src.stdfix.bitsuhr
+    libc.src.stdfix.bitsur
+    libc.src.stdfix.bitsulr
+    libc.src.stdfix.bitsuhk
+    libc.src.stdfix.bitsuk
+    libc.src.stdfix.bitsulk
     libc.src.stdfix.countlshr
     libc.src.stdfix.countlsr
     libc.src.stdfix.countlslr
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 07311a60a17a2..bebbc94f183cb 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -502,6 +502,18 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
     libc.src.stdfix.ukbits
     libc.src.stdfix.lkbits
     libc.src.stdfix.ulkbits
+    libc.src.stdfix.bitshr
+    libc.src.stdfix.bitsr
+    libc.src.stdfix.bitslr
+    libc.src.stdfix.bitshk
+    libc.src.stdfix.bitsk
+    libc.src.stdfix.bitslk
+    libc.src.stdfix.bitshr
+    libc.src.stdfix.bitsur
+    libc.src.stdfix.bitsulr
+    libc.src.stdfix.bitsuhk
+    libc.src.stdfix.bitsuk
+    libc.src.stdfix.bitsulk
     libc.src.stdfix.countlshr
     libc.src.stdfix.countlsr
     libc.src.stdfix.countlslr
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index a9ba0c257755b..978bc62635df3 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.bitshr
+    libc.src.stdfix.bitsr
+    libc.src.stdfix.bitslr
+    libc.src.stdfix.bitshk
+    libc.src.stdfix.bitsk
+    libc.src.stdfix.bitslk
+    libc.src.stdfix.bitsuhr
+    libc.src.stdfix.bitsur
+    libc.src.stdfix.bitsulr
+    libc.src.stdfix.bitsuhk
+    libc.src.stdfix.bitsuk
+    libc.src.stdfix.bitsulk
     libc.src.stdfix.countlshr
     libc.src.stdfix.countlsr
     libc.src.stdfix.countlslr
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index a4f6671a59789..dbe8575405a3b 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.bitshr
+    libc.src.stdfix.bitsr
+    libc.src.stdfix.bitslr
+    libc.src.stdfix.bitshk
+    libc.src.stdfix.bitsk
+    libc.src.stdfix.bitslk
+    libc.src.stdfix.bitsuhr
+    libc.src.stdfix.bitsur
+    libc.src.stdfix.bitsulr
+    libc.src.stdfix.bitsuhk
+    libc.src.stdfix.bitsuk
+    libc.src.stdfix.bitsulk
     libc.src.stdfix.countlshr
     libc.src.stdfix.countlsr
     libc.src.stdfix.countlslr
diff --git a/libc/docs/headers/math/stdfix.rst b/libc/docs/headers/math/stdfix.rst
index 4507f2b608bf1..e12780a32203c 100644
--- a/libc/docs/headers/math/stdfix.rst
+++ b/libc/docs/headers/math/stdfix.rst
@@ -69,7 +69,7 @@ The following functions are included in the ISO/IEC TR 18037:2008 standard.
 +===============+================+=============+===============+============+================+=============+================+=============+===============+============+================+=============+
 | abs           |                | |check|     |               | |check|    |                | |check|     |                | |check|     |               | |check|    |                | |check|     |
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
-| bits\*        |                |             |               |            |                |             |                |             |               |            |                |             |
+| bits\*        |                | |check|     | |check|       | |check|    | |check|        | |check|     | |check|        | |check|     | |check|       | |check|    |                | |check|     |
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
 | \*bits        |                |             |               |            |                |             |                |             |               |            |                |             |
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
diff --git a/libc/include/stdfix.yaml b/libc/include/stdfix.yaml
index 0abf2f3a9b3b6..707e5a2b09819 100644
--- a/libc/include/stdfix.yaml
+++ b/libc/include/stdfix.yaml
@@ -148,6 +148,90 @@ functions:
     arguments:
       - type: uint_ulk_t
     guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: bitshr
+    standards:
+      - stdc_ext
+    return_type: int_hr_t
+    arguments:
+      - type: short fract
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: bitsuhr
+    standards:
+      - stdc_ext
+    return_type: uint_uhr_t
+    arguments:
+      - type: unsigned short fract
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: bitsr
+    standards:
+      - stdc_ext
+    return_type: int_r_t
+    arguments:
+      - type: fract
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: bitsur
+    standards:
+      - stdc_ext
+    return_type: uint_ur_t
+    arguments:
+      - type: unsigned fract
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: bitslr
+    standards:
+      - stdc_ext
+    return_type: int_lr_t
+    arguments:
+      - type: long fract
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: bitsulr
+    standards:
+      - stdc_ext
+    return_type: uint_ulr_t
+    arguments:
+      - type: unsigned long fract
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: bitshk
+    standards:
+      - stdc_ext
+    return_type: int_hk_t
+    arguments:
+      - type: short accum
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: bitsuhk
+    standards:
+      - stdc_ext
+    return_type: uint_uhk_t
+    arguments:
+      - type: unsigned short accum
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: bitsk
+    standards:
+      - stdc_ext
+    return_type: int_k_t
+    arguments:
+      - type: accum
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: bitsuk
+    standards:
+      - stdc_ext
+    return_type: uint_uk_t
+    arguments:
+      - type: unsigned accum
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: bitslk
+    standards:
+      - stdc_ext
+    return_type: int_lk_t
+    arguments:
+      - type: long accum
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: bitsulk
+    standards:
+      - stdc_ext
+    return_type: uint_ulk_t
+    arguments:
+      - type: unsigned long accum
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
   - name: roundhk
     standards:
       - stdc_ext
diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index 7509419da0c43..a9b7fe248f6f1 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -121,7 +121,7 @@ bit_and(T x, T y) {
   using BitType = typename FXRep<T>::StorageType;
   BitType x_bit = cpp::bit_cast<BitType>(x);
   BitType y_bit = cpp::bit_cast<BitType>(y);
-  // For some reason, bit_cast cannot deduce BitType from the input.
+  // For some reason, bit_cast cannot deduce BitType T the input.
   return cpp::bit_cast<T, BitType>(x_bit & y_bit);
 }
 
@@ -131,7 +131,7 @@ bit_or(T x, T y) {
   using BitType = typename FXRep<T>::StorageType;
   BitType x_bit = cpp::bit_cast<BitType>(x);
   BitType y_bit = cpp::bit_cast<BitType>(y);
-  // For some reason, bit_cast cannot deduce BitType from the input.
+  // For some reason, bit_cast cannot deduce BitType T the input.
   return cpp::bit_cast<T, BitType>(x_bit | y_bit);
 }
 
@@ -140,7 +140,7 @@ LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, T>
 bit_not(T x) {
   using BitType = typename FXRep<T>::StorageType;
   BitType x_bit = cpp::bit_cast<BitType>(x);
-  // For some reason, bit_cast cannot deduce BitType from the input.
+  // For some reason, bit_cast cannot deduce BitType T the input.
   return cpp::bit_cast<T, BitType>(static_cast<BitType>(~x_bit));
 }
 
@@ -194,6 +194,13 @@ countls(T f) {
   return cpp::countl_zero(value_bits) - FXRep::SIGN_LEN;
 }
 
+// fixed-point to integer conversion
+template <typename T, typename XType>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, XType>
+bitsfx(T f) {
+  return cpp::bit_cast<XType, T>(f);
+}
+
 } // namespace fixed_point
 } // namespace LIBC_NAMESPACE_DECL
 
diff --git a/libc/src/stdfix/CMakeLists.txt b/libc/src/stdfix/CMakeLists.txt
index 6fb06b8d7e9ae..362af0bf0d55c 100644
--- a/libc/src/stdfix/CMakeLists.txt
+++ b/libc/src/stdfix/CMakeLists.txt
@@ -48,6 +48,20 @@ foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
       libc.src.__support.fixed_point.fx_bits
   )
 
+  add_entrypoint_object(
+    bits${suffix}
+    HDRS
+      bits${suffix}.h
+    SRCS
+      bits${suffix}.cpp
+    COMPILE_OPTIONS
+      ${libc_opt_high_flag}
+    DEPENDS
+      libc.src.__support.fixed_point.fx_bits
+      libc.include.llvm-libc-types.stdfix-types
+      libc.include.llvm-libc-macros.stdfix_macros
+  )
+
   add_entrypoint_object(
     countls${suffix}
     HDRS
diff --git a/libc/src/stdfix/bitshk.cpp b/libc/src/stdfix/bitshk.cpp
new file mode 100644
index 0000000000000..d0a3e128bdd65
--- /dev/null
+++ b/libc/src/stdfix/bitshk.cpp
@@ -0,0 +1,22 @@
+//===-- Implementation of bitshk 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 "bitshk.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // short accum
+#include "include/llvm-libc-types/stdfix-types.h"   // int_hk_t
+#include "src/__support/common.h"                   // LLVM_LIBC_FUNCTION
+#include "src/__support/fixed_point/fx_bits.h"      // fixed_point
+#include "src/__support/macros/config.h"            // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int_hk_t, bitshk, (short accum f)) {
+  return fixed_point::bitsfx<short accum, int_hk_t>(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/bitshk.h b/libc/src/stdfix/bitshk.h
new file mode 100644
index 0000000000000..a1505e2e56d85
--- /dev/null
+++ b/libc/src/stdfix/bitshk.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for bitshk 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_BITSHK_H
+#define LLVM_LIBC_SRC_STDFIX_BITSHK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h" // short accum
+#include "include/llvm-libc-types/stdfix-types.h"   // int_hk_t
+#include "src/__support/macros/config.h"            // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int_hk_t bitshk(short accum f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_BITSHK_H
diff --git a/libc/src/stdfix/bitshr.cpp b/libc/src/stdfix/bitshr.cpp
new file mode 100644
index 0000000000000..394d1f08f6ae5
--- /dev/null
+++ b/libc/src/stdfix/bitshr.cpp
@@ -0,0 +1,22 @@
+//===-- Implementation of bitshr 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 "bitshr.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // short fract
+#include "include/llvm-libc-types/stdfix-types.h"   // int_hr_t
+#include "src/__support/common.h"                   // LLVM_LIBC_FUNCTION
+#include "src/__support/fixed_point/fx_bits.h"      // fixed_point
+#include "src/__support/macros/config.h"            // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int_hr_t, bitshr, (short fract f)) {
+  return fixed_point::bitsfx<short fract, int_hr_t>(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/bitshr.h b/libc/src/stdfix/bitshr.h
new file mode 100644
index 0000000000000..d5b4b8f56a7e9
--- /dev/null
+++ b/libc/src/stdfix/bitshr.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for bitshr 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_BITSHR_H
+#define LLVM_LIBC_SRC_STDFIX_BITSHR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h" // short fract
+#include "include/llvm-libc-types/stdfix-types.h"   // int_hr_t
+#include "src/__support/macros/config.h"            // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int_hr_t bitshr(short fract f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_BITSHR_H
diff --git a/libc/src/stdfix/bitsk.cpp b/libc/src/stdfix/bitsk.cpp
new file mode 100644
index 0000000000000..f8c9d77d56e9c
--- /dev/null
+++ b/libc/src/stdfix/bitsk.cpp
@@ -0,0 +1,22 @@
+//===-- Implementation for bitsk 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 "bitsk.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // accum
+#include "include/llvm-libc-types/stdfix-types.h"   // int_k_t
+#include "src/__support/common.h"                   // LLVM_LIBC_FUNCTION
+#include "src/__support/fixed_point/fx_bits.h"      // fixed_point
+#include "src/__support/macros/config.h"            // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int_k_t, bitsk, (accum f)) {
+  return fixed_point::bitsfx<accum, int_k_t>(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/bitsk.h b/libc/src/stdfix/bitsk.h
new file mode 100644
index 0000000000000..32d5a724dfb0b
--- /dev/null
+++ b/libc/src/stdfix/bitsk.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for bitsk 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_BITSK_H
+#define LLVM_LIBC_SRC_STDFIX_BITSK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h" // accum
+#include "include/llvm-libc-types/stdfix-types.h"   // int_k_t
+#include "src/__support/macros/config.h"            // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int_k_t bitsk(accum f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_BITSK_H
diff --git a/libc/src/stdfix/bitslk.cpp b/libc/src/stdfix/bitslk.cpp
new file mode 100644
index 0000000000000..f4af2a8cd8b99
--- /dev/null
+++ b/libc/src/stdfix/bitslk.cpp
@@ -0,0 +1,22 @@
+//===-- Implementation for bitslk 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 "bitslk.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // long accum
+#include "include/llvm-libc-types/stdfix-types.h"   // int_lk_t
+#include "src/__support/common.h"                   // LLVM_LIBC_FUNCTION
+#include "src/__support/fixed_point/fx_bits.h"      // fixed_point
+#include "src/__support/macros/config.h"            // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int_lk_t, bitslk, (long accum f)) {
+  return fixed_point::bitsfx<long accum, int_lk_t>(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/bitslk.h b/libc/src/stdfix/bitslk.h
new file mode 100644
index 0000000000000..821116b9a7c1b
--- /dev/null
+++ b/libc/src/stdfix/bitslk.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for bitslk 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_BITSLK_H
+#define LLVM_LIBC_SRC_STDFIX_BITSLK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h" // long accum
+#include "include/llvm-libc-types/stdfix-types.h"   // int_lk_t
+#include "src/__support/macros/config.h"            // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int_lk_t bitslk(long accum f);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_BITSLK_H
diff --git a/libc/src/stdfix/bitslr.cpp b/libc/src/stdfix/bitslr.cpp
new file mode 100644
index 0000000000000..3b38aa21a6338
--- /dev/null
+++ b/libc/src/stdfix/bitslr.cpp
@@ -0,0 +1,22 @@
+//===-- Implementation of bitslr 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 "bitslr.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // long fract
+#include "include/llvm-libc-types/stdfix-types.h"   // int_lr_t
+#include "src/__support/common.h"                   // LLVM_LIBC_FUNCTION
+#include "src/__support/fixed_point/fx_bits.h"      // fixed_point
+#include "src/__support/macros/config.h"            // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int_lr_t, bitslr, (long fract f)) {
+  return fixed_point::bitsfx<long fract, int_lr_t>(f);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/bitslr.h b/libc/src/stdfix/bitslr.h
new file mode 100644
index 0000000000000..0cb597214f550
--- /dev/null
+++ b/libc/src/stdfix/bitslr.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for bitslr 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_BITSLR_H
+#define LLVM_LIBC_SRC_STDFIX_BITSLR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h" // long fract
+#include "include/llvm-libc-types/stdfix-types.h"   // int_lr_t
+#include "src/__support/macros/config.h"            // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DE...
[truncated]

@krishna2803
Copy link
Contributor Author

@PiJoules @lntue @nickdesaulniers

Tests for int_hr_t (short fract) don't seem to work as it's just a typedef for signed char, and we don't have defined tests for that (and also signed char != char), I’ve excluded the tests for this type from libc/test/CMakeLists.txt for now. Apart from that, I built on the implementations of the already existing fxbits and countlsfx functions for this patch.

A side note: I noticed that the documentation for the fxbits functions is not updated in libc/docs/headers/math/stdfix.rst, even though we have an implementation for those. This also means that the "checks" are missing from the llvm website.

@lntue lntue requested review from PiJoules and lntue February 23, 2025 22:20
@@ -121,7 +121,7 @@ bit_and(T x, T y) {
using BitType = typename FXRep<T>::StorageType;
BitType x_bit = cpp::bit_cast<BitType>(x);
BitType y_bit = cpp::bit_cast<BitType>(y);
// For some reason, bit_cast cannot deduce BitType from the input.
// For some reason, bit_cast cannot deduce BitType T the input.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the from -> T here intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh sorry, that's an artifact of me doing a find and replace of a silly variable name that i overlooked

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 6bd83934


// (0.6875)_10 = (0.1011)_2
EXPECT_EQ(static_cast<XType>(11ULL << (FXRep::FRACTION_LEN - 4)),
func(0.6875));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be overthinking this, but using 0.6875 here is a double which gets implicitly converted to some fixed point type. This could be evaluated at compile time, but I don't think the standard guarantees that a compiler always has to do it.

Kind of a nit: I think we can always force the compile-time conversion by instead assigning this to a constexpr variable of the corresponding fixed point type. This just avoids having to emit the instructions for doing the implicit conversion from double to fixed point.

Something like constexpr T special = 0.6875; should do and group it with the other special numbers above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed here:

static constexpr T zero_point_six_eight_seven_five_t = 0.6875;

// (0.6875)_10 = (0.1011)_2
EXPECT_EQ(static_cast<XType>(11ULL << (FXRep::FRACTION_LEN - 4)),
func(zero_point_six_eight_seven_five_t));

public:
typedef XType (*BitsFxFunc)(T);

void testSpecialNumbers(BitsFxFunc func) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also add tests for negative values for each of the special numbers when the fixed point type is signed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added here:

if constexpr (FXRep::SIGN_LEN > 0)
EXPECT_EQ(static_cast<XType>(-(11ULL << (FXRep::FRACTION_LEN - 4))),
func(negative_zero_point_six_eight_seven_five_t));

and here:

if constexpr (FXRep::SIGN_LEN > 0 && FXRep::INTEGRAL_LEN > 0) {
if (static_cast<int>(min) <= -11)
switch (FXRep::FRACTION_LEN) {
case 7:
EXPECT_EQ(static_cast<XType>(-1372), func(negative_special_num_t));
break;
case 15:
EXPECT_EQ(static_cast<XType>(-351232), func(negative_special_num_t));
break;
case 23:
EXPECT_EQ(static_cast<XType>(-89915392),
func(negative_special_num_t));
break;
default:
break;
}
}

Comment on lines +18 to +19
static constexpr T max = FXRep::MAX();
static constexpr T min = FXRep::MIN();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like these two are unused. Could you also add tests that check against these?

// (0.42)_10 =
// (0.0110101110000101000111101011100001010001111010111000010100011110)_2 =
// (0.0x6b851eb851eb851e)_16
static constexpr unsigned long long zero_point_forty_two =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also add one or two special numbers greater than 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in an attempt to test for 10.72 (just as an example), i tried:

// (10.72)_10 =
// (1010.101110000101000111101011100001010001111010111000010100011110)_2 =
// (a.b851eb851eb851e)_16
static constexpr unsigned long long ten_point_seven_two = 0xab851eb851eb851eULL;

static constexpr T ten_point_seven_two_t = 10.72;

if constexpr (FXRep::INTEGRAL_LEN > 0)
  EXPECT_EQ(
    static_cast<XType>(ten_point_seven_two >> (64 - (FXRep::VALUE_LEN))),
    func(ten_point_seven_two_t)
  );

where FXRep::VALUE_LEN is just FXRep::INTEGRAL_LEN + FXRep::FRACTION_LEN. When I traced the definition for FXRep::INTEGRAL_LEN, I found them to be different than the spec for example for short accum the spec suggests s4.7 (ref, pg11) while the FXRep::INTEGRAL_LEN is 8 for short fract defined here:

#ifdef __SACCUM_IBIT__
#define SACCUM_IBIT __SACCUM_IBIT__
#else
#define SACCUM_IBIT 8
#endif // SACCUM_IBIT

so the above test fails.


but when i do:

// (10.72)_10 =
// (1010.101110000101000111101011100001010001111010111000010100011110)_2 =
// (a.b851eb851eb851e)_16
static constexpr unsigned long long ten_point_seven_two = 0xab851eb851eb851eULL;

static constexpr T ten_point_seven_two_t = 10.72;

if constexpr (FXRep::INTEGRAL_LEN > 0)
  EXPECT_EQ(
    // just hardcoded 4 here in place of INTEGRAL_LEN
    static_cast<XType>(ten_point_seven_two >> (64 - (FXRep::FRACTION_LEN + 4))),
    func(ten_point_seven_two_t)
  );

the test passes! could you please provide some guidance on how to handle this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in an attempt to test for 10.72 (just as an example), i tried:

// (10.72)_10 =
// (1010.101110000101000111101011100001010001111010111000010100011110)_2 =
// (a.b851eb851eb851e)_16
static constexpr unsigned long long ten_point_seven_two = 0xab851eb851eb851eULL;

static constexpr T ten_point_seven_two_t = 10.72;

if constexpr (FXRep::INTEGRAL_LEN > 0)
  EXPECT_EQ(
    static_cast<XType>(ten_point_seven_two >> (64 - (FXRep::VALUE_LEN))),
    func(ten_point_seven_two_t)
  );

where FXRep::VALUE_LEN is just FXRep::INTEGRAL_LEN + FXRep::FRACTION_LEN. When I traced the definition for FXRep::INTEGRAL_LEN, I found them to be different than the spec for example for short accum the spec suggests s4.7 (ref, pg11) while the FXRep::INTEGRAL_LEN is 8 for short fract defined here:

#ifdef __SACCUM_IBIT__
#define SACCUM_IBIT __SACCUM_IBIT__
#else
#define SACCUM_IBIT 8
#endif // SACCUM_IBIT

so the above test fails.

That section is for the minimal formats of each type. Any implementation can have different integral and fractional bits as long as they meet those minimum formats. There's other possible formats in A.3 Possible Data Type Implementations. Clang's default formats are the typical desktop processor formats but we shouldn't assume those will always be the formats.

but when i do:

// (10.72)_10 =
// (1010.101110000101000111101011100001010001111010111000010100011110)_2 =
// (a.b851eb851eb851e)_16
static constexpr unsigned long long ten_point_seven_two = 0xab851eb851eb851eULL;

static constexpr T ten_point_seven_two_t = 10.72;

if constexpr (FXRep::INTEGRAL_LEN > 0)
  EXPECT_EQ(
    // just hardcoded 4 here in place of INTEGRAL_LEN
    static_cast<XType>(ten_point_seven_two >> (64 - (FXRep::FRACTION_LEN + 4))),
    func(ten_point_seven_two_t)
  );

the test passes! could you please provide some guidance on how to handle this?

Hmmm so 10.72 can't precisely fit in a fixed point number, so the actual fixed point value will be either rounded up or down to the nearest fixed point value within 1 ULP. This means for something like 10.72 as a short accum with 7 fractional bits, it's actual value will be either 10.71875 or 10.7265625. If we test against T ten_point_seven_two_t = 10.72 then we'd actually be testing against one of these 2 values. I think perhaps it would instead be better to test precise values that fit into the fixed point type rather than guessing the rounding here. That is, for a short accum use either 10.7265625 or 10.71875 rather than 10.72 directly.

Rather than using a hardcoded hex and shifting from a more precise number, I think maybe it would be easier if we tested against known values. That is, for a short accum with a value of 10.71875 and 7 fractional bits, we explicitly expect 1372.

Copy link
Contributor Author

@krishna2803 krishna2803 Feb 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for checks with the other accum types, would it be okay if i use a switch statement something like:

if constexpr (FXRep::INTEGRAL_LEN > 0) {
  switch (FXRep::FRACTIONAL_LEN) {
  case 7:
    // todo
    break;
  case 15:
    // todo
    break;
  case 23:
    // todo
    break;
  default:
    break;
  }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that should be fine.

Comment on lines 45 to 48
EXPECT_EQ(
static_cast<XType>(zero_point_forty_two >> (64 - FXRep::FRACTION_LEN)),
func(0.42));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that if the value cannot precisely fit in the fixed point type, rounding up or down is implementation-defined. I think this check assumes we always round down. Perhaps for numbers that don't precisely fit in a fixed point type, we should check the numbers both above and below the true value.

For example, for 0.42 as a short fract which has 7 fractional bits for this implementation, we check the result of bitshr is 53 or 54.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually disregard this comment, the rounding I mentioned will happen when 0.42 is passed as the argument, so the argument will have one of 2 values but the result of func could then have more than 2 possible return values. So I think rather than using values that don't fit precisely in a fixed point type, we should use precise values that do. So rather than 0.42, maybe use one of the fixed point values that is within 1 ULP of that value for that type. For example, for a short accum with 7 fractional bits, this would instead be either 0.421875 or 0.4140625.

@PiJoules
Copy link
Contributor

Tests for int_hr_t (short fract) don't seem to work as it's just a typedef for signed char, and we don't have defined tests for that (and also signed char != char), I’ve excluded the tests for this type from libc/test/CMakeLists.txt for now. Apart from that, I built on the implementations of the already existing fxbits and countlsfx functions for this patch.

What's the failure you're seeing for short fract?

@krishna2803
Copy link
Contributor Author

FAILED: libc/test/src/stdfix/libc.test.src.stdfix.bitshr_test.__unit__.__build__ 
: && /home/krishna/OpenSource/llvm-project/build/bin/clang++ --target=x86_64-unknown-linux-gnu -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -O3 -DNDEBUG -fuse-ld=lld -Wl,--color-diagnostics    -fpie -ffixed-point -Wimplicit-fallthrough -Wwrite-strings -Wno-c99-extensions -Wno-gnu-imaginary-constant -Wno-pedantic -Wstrict-prototypes -Wextra-semi -Wnewline-eof -Wnonportable-system-include-path -Wthread-safety -Xlinker --dependency-file=libc/test/src/stdfix/CMakeFiles/libc.test.src.stdfix.bitshr_test.__unit__.__build__.dir/link.d libc/test/src/stdfix/CMakeFiles/libc.test.src.stdfix.bitshr_test.__unit__.__build__.dir/bitshr_test.cpp.o -o libc/test/src/stdfix/libc.test.src.stdfix.bitshr_test.__unit__.__build__  libc/src/stdfix/CMakeFiles/libc.src.stdfix.bitshr.__internal__.dir/./bitshr.cpp.o  libc/src/errno/CMakeFiles/libc.src.errno.errno.__internal__.dir/./libc_errno.cpp.o  libc/src/__support/StringUtil/CMakeFiles/libc.src.__support.StringUtil.error_to_string.dir/./error_to_string.cpp.o  libc/src/__support/OSUtil/linux/CMakeFiles/libc.src.__support.OSUtil.linux.linux_util.dir/./exit.cpp.o  libc/src/__support/OSUtil/linux/CMakeFiles/libc.src.__support.OSUtil.linux.linux_util.dir/./fcntl.cpp.o  libc/test/UnitTest/libLibcDeathTestExecutors.unit.a  libc/test/UnitTest/libLibcTest.unit.a && :
ld.lld: error: undefined hidden symbol: bool __llvm_libc_21_0_0_git::testing::internal::test<signed char>(__llvm_libc_21_0_0_git::testing::internal::RunContext*, __llvm_libc_21_0_0_git::testing::TestCond, signed char, signed char, char const*, char const*, __llvm_libc_21_0_0_git::testing::internal::Location)
>>> referenced by bitshr_test.cpp
>>>               libc/test/src/stdfix/CMakeFiles/libc.test.src.stdfix.bitshr_test.__unit__.__build__.dir/bitshr_test.cpp.o:(LlvmLibcBitshrTest_SpecialNumbers::Run())
>>> referenced by bitshr_test.cpp
>>>               libc/test/src/stdfix/CMakeFiles/libc.test.src.stdfix.bitshr_test.__unit__.__build__.dir/bitshr_test.cpp.o:(LlvmLibcBitshrTest_SpecialNumbers::Run())
>>> referenced by bitshr_test.cpp
>>>               libc/test/src/stdfix/CMakeFiles/libc.test.src.stdfix.bitshr_test.__unit__.__build__.dir/bitshr_test.cpp.o:(LlvmLibcBitshrTest_SpecialNumbers::Run())
>>> referenced 3 more times
>>> did you mean: bool __llvm_libc_21_0_0_git::testing::internal::test<bool>(__llvm_libc_21_0_0_git::testing::internal::RunContext*, __llvm_libc_21_0_0_git::testing::TestCond, bool, bool, char const*, char const*, __llvm_libc_21_0_0_git::testing::internal::Location)
>>> defined in: libc/test/UnitTest/libLibcTest.unit.a(LibcTest.cpp.o)
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

this is the exact failure for int_hr_t (short fract)

@lntue
Copy link
Contributor

lntue commented Feb 26, 2025

FAILED: libc/test/src/stdfix/libc.test.src.stdfix.bitshr_test.__unit__.__build__ 
: && /home/krishna/OpenSource/llvm-project/build/bin/clang++ --target=x86_64-unknown-linux-gnu -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -O3 -DNDEBUG -fuse-ld=lld -Wl,--color-diagnostics    -fpie -ffixed-point -Wimplicit-fallthrough -Wwrite-strings -Wno-c99-extensions -Wno-gnu-imaginary-constant -Wno-pedantic -Wstrict-prototypes -Wextra-semi -Wnewline-eof -Wnonportable-system-include-path -Wthread-safety -Xlinker --dependency-file=libc/test/src/stdfix/CMakeFiles/libc.test.src.stdfix.bitshr_test.__unit__.__build__.dir/link.d libc/test/src/stdfix/CMakeFiles/libc.test.src.stdfix.bitshr_test.__unit__.__build__.dir/bitshr_test.cpp.o -o libc/test/src/stdfix/libc.test.src.stdfix.bitshr_test.__unit__.__build__  libc/src/stdfix/CMakeFiles/libc.src.stdfix.bitshr.__internal__.dir/./bitshr.cpp.o  libc/src/errno/CMakeFiles/libc.src.errno.errno.__internal__.dir/./libc_errno.cpp.o  libc/src/__support/StringUtil/CMakeFiles/libc.src.__support.StringUtil.error_to_string.dir/./error_to_string.cpp.o  libc/src/__support/OSUtil/linux/CMakeFiles/libc.src.__support.OSUtil.linux.linux_util.dir/./exit.cpp.o  libc/src/__support/OSUtil/linux/CMakeFiles/libc.src.__support.OSUtil.linux.linux_util.dir/./fcntl.cpp.o  libc/test/UnitTest/libLibcDeathTestExecutors.unit.a  libc/test/UnitTest/libLibcTest.unit.a && :
ld.lld: error: undefined hidden symbol: bool __llvm_libc_21_0_0_git::testing::internal::test<signed char>(__llvm_libc_21_0_0_git::testing::internal::RunContext*, __llvm_libc_21_0_0_git::testing::TestCond, signed char, signed char, char const*, char const*, __llvm_libc_21_0_0_git::testing::internal::Location)
>>> referenced by bitshr_test.cpp
>>>               libc/test/src/stdfix/CMakeFiles/libc.test.src.stdfix.bitshr_test.__unit__.__build__.dir/bitshr_test.cpp.o:(LlvmLibcBitshrTest_SpecialNumbers::Run())
>>> referenced by bitshr_test.cpp
>>>               libc/test/src/stdfix/CMakeFiles/libc.test.src.stdfix.bitshr_test.__unit__.__build__.dir/bitshr_test.cpp.o:(LlvmLibcBitshrTest_SpecialNumbers::Run())
>>> referenced by bitshr_test.cpp
>>>               libc/test/src/stdfix/CMakeFiles/libc.test.src.stdfix.bitshr_test.__unit__.__build__.dir/bitshr_test.cpp.o:(LlvmLibcBitshrTest_SpecialNumbers::Run())
>>> referenced 3 more times
>>> did you mean: bool __llvm_libc_21_0_0_git::testing::internal::test<bool>(__llvm_libc_21_0_0_git::testing::internal::RunContext*, __llvm_libc_21_0_0_git::testing::TestCond, bool, bool, char const*, char const*, __llvm_libc_21_0_0_git::testing::internal::Location)
>>> defined in: libc/test/UnitTest/libLibcTest.unit.a(LibcTest.cpp.o)
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

this is the exact failure for int_hr_t (short fract)

You might need to add signed char to this list of speciallizations https://github.com/llvm/llvm-project/blob/main/libc/test/UnitTest/LibcTest.cpp#L220

@krishna2803 krishna2803 requested a review from PiJoules February 26, 2025 21:07
Copy link
Contributor

@PiJoules PiJoules left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good so far. Just a few more comments from me.

Comment on lines 54 to 65
switch (FXRep::FRACTION_LEN) {
case 7:
EXPECT_EQ(static_cast<XType>(1372), func(special_num_t));
break;
case 15:
EXPECT_EQ(static_cast<XType>(351232), func(special_num_t));
break;
case 23:
EXPECT_EQ(static_cast<XType>(89915392), func(special_num_t));
break;
default:
break;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm ok rather than having the switch, perhaps we could do something like have a preset number for the lowest value we know and do the shifts. That is, we have something like

constexpr size_t kMinFbits = 7;
if (max >= 11 && FXRep::FRACTION_LEN >= kMinFbits) {
  constexpr XType kExpected = 1372;  // 10.71875 with a scale of 7 equals this.
  EXPECT_EQ(XType << (FXRep::FRACTION_LEN - kMinFbits), func(special_num_t));
}

This way we can always have these tests even if the fractional bits aren't one of 7, 15, or 23.

Sorry I probably should've said this instead of accepting the switch from your comment earlier. I just though of this now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated! here:

if (max >= 11 && FXRep::FRACTION_LEN >= kMinFbits) {
// (10.71875)_10 = (1010.1011100)_2
constexpr long long kExpected = 1372;
EXPECT_EQ(
static_cast<XType>(kExpected << (FXRep::FRACTION_LEN - kMinFbits)),
func(special_num_t));
}


if constexpr (FXRep::SIGN_LEN > 0 && FXRep::INTEGRAL_LEN > 0) {
if (static_cast<int>(min) <= -11)
switch (FXRep::FRACTION_LEN) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also apply the comment I made above to this switch?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated here:

if constexpr (FXRep::SIGN_LEN > 0) {
if (min <= -11 && FXRep::FRACTION_LEN >= kMinFbits) {
// (-10.71875)_10 = (-1010.1011100)_2
constexpr long long kExpected = -1372;
EXPECT_EQ(static_cast<XType>(kExpected
<< (FXRep::FRACTION_LEN - kMinFbits)),
func(negative_special_num_t));
}

also refactored the tests for signed accum types to share the common if for FXRep::INTEGRAL_LEN > 0

Copy link
Contributor

@PiJoules PiJoules left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks! Maybe wait for an LGTM from Tue also to make sure it conforms to libc standards.

@lntue lntue merged commit f6bfa33 into llvm:main Feb 27, 2025
17 checks passed
@krishna2803 krishna2803 deleted the implement-bitsfx branch February 27, 2025 18:16
joaosaffran pushed a commit to joaosaffran/llvm-project that referenced this pull request Mar 3, 2025
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 bitsfx functions in llvm-libc
4 participants