[libc-commits] [libc] [llvm] [libc][stdfix] Add round functions for fixed point types. (PR #81994)

via libc-commits libc-commits at lists.llvm.org
Fri Feb 16 09:27:21 PST 2024


https://github.com/lntue updated https://github.com/llvm/llvm-project/pull/81994

>From 335c91890c187865863b2cba15ee7836ffa6193a Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Fri, 16 Feb 2024 14:36:40 +0000
Subject: [PATCH 1/2] [libc][stdfix] Add round functions for fixed point types.

---
 libc/config/linux/x86_64/entrypoints.txt      | 12 ++++
 libc/docs/math/stdfix.rst                     |  2 +-
 libc/spec/stdc_ext.td                         | 16 +++++
 libc/src/__support/fixed_point/CMakeLists.txt |  1 +
 libc/src/__support/fixed_point/fx_bits.h      | 53 +++++++++++++++
 libc/src/stdfix/CMakeLists.txt                | 15 +++++
 libc/src/stdfix/roundhk.cpp                   | 19 ++++++
 libc/src/stdfix/roundhk.h                     | 20 ++++++
 libc/src/stdfix/roundhr.cpp                   | 19 ++++++
 libc/src/stdfix/roundhr.h                     | 20 ++++++
 libc/src/stdfix/roundk.cpp                    | 19 ++++++
 libc/src/stdfix/roundk.h                      | 20 ++++++
 libc/src/stdfix/roundlk.cpp                   | 19 ++++++
 libc/src/stdfix/roundlk.h                     | 20 ++++++
 libc/src/stdfix/roundlr.cpp                   | 19 ++++++
 libc/src/stdfix/roundlr.h                     | 20 ++++++
 libc/src/stdfix/roundr.cpp                    | 19 ++++++
 libc/src/stdfix/roundr.h                      | 20 ++++++
 libc/src/stdfix/rounduhk.cpp                  | 20 ++++++
 libc/src/stdfix/rounduhk.h                    | 20 ++++++
 libc/src/stdfix/rounduhr.cpp                  | 20 ++++++
 libc/src/stdfix/rounduhr.h                    | 20 ++++++
 libc/src/stdfix/rounduk.cpp                   | 19 ++++++
 libc/src/stdfix/rounduk.h                     | 20 ++++++
 libc/src/stdfix/roundulk.cpp                  | 20 ++++++
 libc/src/stdfix/roundulk.h                    | 20 ++++++
 libc/src/stdfix/roundulr.cpp                  | 20 ++++++
 libc/src/stdfix/roundulr.h                    | 20 ++++++
 libc/src/stdfix/roundur.cpp                   | 19 ++++++
 libc/src/stdfix/roundur.h                     | 20 ++++++
 libc/test/src/stdfix/CMakeLists.txt           | 18 +++++
 libc/test/src/stdfix/RoundTest.h              | 65 +++++++++++++++++++
 libc/test/src/stdfix/roundhk_test.cpp         | 13 ++++
 libc/test/src/stdfix/roundhr_test.cpp         | 13 ++++
 libc/test/src/stdfix/roundk_test.cpp          | 13 ++++
 libc/test/src/stdfix/roundlk_test.cpp         | 13 ++++
 libc/test/src/stdfix/roundlr_test.cpp         | 13 ++++
 libc/test/src/stdfix/roundr_test.cpp          | 13 ++++
 libc/test/src/stdfix/rounduhk_test.cpp        | 13 ++++
 libc/test/src/stdfix/rounduhr_test.cpp        | 13 ++++
 libc/test/src/stdfix/rounduk_test.cpp         | 13 ++++
 libc/test/src/stdfix/roundulk_test.cpp        | 13 ++++
 libc/test/src/stdfix/roundulr_test.cpp        | 13 ++++
 libc/test/src/stdfix/roundur_test.cpp         | 13 ++++
 44 files changed, 809 insertions(+), 1 deletion(-)
 create mode 100644 libc/src/stdfix/roundhk.cpp
 create mode 100644 libc/src/stdfix/roundhk.h
 create mode 100644 libc/src/stdfix/roundhr.cpp
 create mode 100644 libc/src/stdfix/roundhr.h
 create mode 100644 libc/src/stdfix/roundk.cpp
 create mode 100644 libc/src/stdfix/roundk.h
 create mode 100644 libc/src/stdfix/roundlk.cpp
 create mode 100644 libc/src/stdfix/roundlk.h
 create mode 100644 libc/src/stdfix/roundlr.cpp
 create mode 100644 libc/src/stdfix/roundlr.h
 create mode 100644 libc/src/stdfix/roundr.cpp
 create mode 100644 libc/src/stdfix/roundr.h
 create mode 100644 libc/src/stdfix/rounduhk.cpp
 create mode 100644 libc/src/stdfix/rounduhk.h
 create mode 100644 libc/src/stdfix/rounduhr.cpp
 create mode 100644 libc/src/stdfix/rounduhr.h
 create mode 100644 libc/src/stdfix/rounduk.cpp
 create mode 100644 libc/src/stdfix/rounduk.h
 create mode 100644 libc/src/stdfix/roundulk.cpp
 create mode 100644 libc/src/stdfix/roundulk.h
 create mode 100644 libc/src/stdfix/roundulr.cpp
 create mode 100644 libc/src/stdfix/roundulr.h
 create mode 100644 libc/src/stdfix/roundur.cpp
 create mode 100644 libc/src/stdfix/roundur.h
 create mode 100644 libc/test/src/stdfix/RoundTest.h
 create mode 100644 libc/test/src/stdfix/roundhk_test.cpp
 create mode 100644 libc/test/src/stdfix/roundhr_test.cpp
 create mode 100644 libc/test/src/stdfix/roundk_test.cpp
 create mode 100644 libc/test/src/stdfix/roundlk_test.cpp
 create mode 100644 libc/test/src/stdfix/roundlr_test.cpp
 create mode 100644 libc/test/src/stdfix/roundr_test.cpp
 create mode 100644 libc/test/src/stdfix/rounduhk_test.cpp
 create mode 100644 libc/test/src/stdfix/rounduhr_test.cpp
 create mode 100644 libc/test/src/stdfix/rounduk_test.cpp
 create mode 100644 libc/test/src/stdfix/roundulk_test.cpp
 create mode 100644 libc/test/src/stdfix/roundulr_test.cpp
 create mode 100644 libc/test/src/stdfix/roundur_test.cpp

diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 69912d3b32f030..beb7a5ed448ded 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -451,6 +451,18 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
     libc.src.stdfix.absr
     libc.src.stdfix.abslk
     libc.src.stdfix.abslr
+    libc.src.stdfix.roundhk
+    libc.src.stdfix.roundhr
+    libc.src.stdfix.roundk
+    libc.src.stdfix.roundr
+    libc.src.stdfix.roundlk
+    libc.src.stdfix.roundlr
+    libc.src.stdfix.rounduhk
+    libc.src.stdfix.rounduhr
+    libc.src.stdfix.rounduk
+    libc.src.stdfix.roundur
+    libc.src.stdfix.roundulk
+    libc.src.stdfix.roundulr
   )
 endif()
 
diff --git a/libc/docs/math/stdfix.rst b/libc/docs/math/stdfix.rst
index d05e3fdeabf1c5..080066e53bd2f1 100644
--- a/libc/docs/math/stdfix.rst
+++ b/libc/docs/math/stdfix.rst
@@ -76,7 +76,7 @@ Fixed-point Arithmetics
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
 | rdivi         |                |             |               |            |                |             |                |             |               |            |                |             |
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
-| round         |                |             |               |            |                |             |                |             |               |            |                |             |
+| round         | |check|        | |check|     | |check|       | |check|    | |check|        | |check|     | |check|        | |check|     | |check|       | |check|    | |check|        | |check|     |
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
 | sqrt          |                |             |               |            |                |             |                |             |               |            |                |             |
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
diff --git a/libc/spec/stdc_ext.td b/libc/spec/stdc_ext.td
index dd9f06d1a8cba4..6620142146c471 100644
--- a/libc/spec/stdc_ext.td
+++ b/libc/spec/stdc_ext.td
@@ -31,6 +31,22 @@ def StdcExt : StandardSpec<"stdc_ext"> {
           GuardedFunctionSpec<"abshk", RetValSpec<ShortAccumType>, [ArgSpec<ShortAccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
           GuardedFunctionSpec<"absk", RetValSpec<AccumType>, [ArgSpec<AccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
           GuardedFunctionSpec<"abslk", RetValSpec<LongAccumType>, [ArgSpec<LongAccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
+          GuardedFunctionSpec<"roundhr", RetValSpec<ShortFractType>, [ArgSpec<ShortFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"roundr", RetValSpec<FractType>, [ArgSpec<FractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"roundlr", RetValSpec<LongFractType>, [ArgSpec<LongFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
+          GuardedFunctionSpec<"roundhk", RetValSpec<ShortAccumType>, [ArgSpec<ShortAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"roundk", RetValSpec<AccumType>, [ArgSpec<AccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"roundlk", RetValSpec<LongAccumType>, [ArgSpec<LongAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
+          GuardedFunctionSpec<"rounduhr", RetValSpec<UnsignedShortFractType>, [ArgSpec<UnsignedShortFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"roundur", RetValSpec<UnsignedFractType>, [ArgSpec<UnsignedFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"roundulr", RetValSpec<UnsignedLongFractType>, [ArgSpec<UnsignedLongFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
+          GuardedFunctionSpec<"rounduhk", RetValSpec<UnsignedShortAccumType>, [ArgSpec<UnsignedShortAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"rounduk", RetValSpec<UnsignedAccumType>, [ArgSpec<UnsignedAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+          GuardedFunctionSpec<"roundulk", RetValSpec<UnsignedLongAccumType>, [ArgSpec<UnsignedLongAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
       ]
   >;
 
diff --git a/libc/src/__support/fixed_point/CMakeLists.txt b/libc/src/__support/fixed_point/CMakeLists.txt
index 4dac9b33325adb..c6bb9e17adfa8e 100644
--- a/libc/src/__support/fixed_point/CMakeLists.txt
+++ b/libc/src/__support/fixed_point/CMakeLists.txt
@@ -17,4 +17,5 @@ add_header_library(
     libc.include.llvm-libc-macros.stdfix_macros
     libc.src.__support.macros.attributes
     libc.src.__support.macros.optimization
+    libc.src.__support.CPP.bit
 )
diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index ad3a6fc97c0a1f..626cd689cdfd0f 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -10,6 +10,8 @@
 #define LLVM_LIBC_SRC___SUPPORT_FIXEDPOINT_FXBITS_H
 
 #include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/type_traits.h"
 #include "src/__support/macros/attributes.h"   // LIBC_INLINE
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 
@@ -19,6 +21,36 @@
 
 namespace LIBC_NAMESPACE::fixed_point {
 
+// Bit-wise operations are not available for fixed point types yet.
+template <typename T>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, T>
+bit_and(T x, T y) {
+  using BitType = typename FXRep<T>::StorageType;
+  static_assert(sizeof(BitType) * CHAR_BIT == sizeof(T) * CHAR_BIT);
+  BitType x_bit = cpp::bit_cast<BitType>(x);
+  BitType y_bit = cpp::bit_cast<BitType>(y);
+  return cpp::bit_cast<T, BitType>(x_bit & y_bit);
+}
+
+template <typename T>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, T>
+bit_or(T x, T y) {
+  using BitType = typename FXRep<T>::StorageType;
+  static_assert(sizeof(BitType) * CHAR_BIT == FXRep<T>::TOTAL_LEN);
+  BitType x_bit = cpp::bit_cast<BitType>(x);
+  BitType y_bit = cpp::bit_cast<BitType>(y);
+  return cpp::bit_cast<T, BitType>(x_bit | y_bit);
+}
+
+template <typename T>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, T>
+bit_not(T x) {
+  using BitType = typename FXRep<T>::StorageType;
+  static_assert(sizeof(BitType) * CHAR_BIT == sizeof(T) * CHAR_BIT);
+  BitType x_bit = cpp::bit_cast<BitType>(x);
+  return cpp::bit_cast<T, BitType>(~x_bit);
+}
+
 template <typename T> LIBC_INLINE constexpr T abs(T x) {
   using FXRep = FXRep<T>;
   if constexpr (FXRep::SIGN_LEN == 0)
@@ -30,6 +62,27 @@ template <typename T> LIBC_INLINE constexpr T abs(T x) {
   }
 }
 
+// Round-to-nearest, tie-to-(+Inf)
+template <typename T> LIBC_INLINE constexpr T round(T x, int n) {
+  using FXRep = FXRep<T>;
+  if (LIBC_UNLIKELY(n < 0))
+    n = 0;
+  if (LIBC_UNLIKELY(n >= FXRep::FRACTION_LEN))
+    return x;
+
+  T round_bit = FXRep::EPS() << (FXRep::FRACTION_LEN - n - 1);
+  // Check for overflow.
+  if (LIBC_UNLIKELY(FXRep::MAX() - round_bit < x))
+    return FXRep::MAX();
+
+  T all_ones = bit_not(FXRep::ZERO());
+
+  int shift = FXRep::FRACTION_LEN - n;
+  T rounding_mask =
+      (shift == FXRep::TOTAL_LEN) ? FXRep::ZERO() : (all_ones << shift);
+  return bit_and((x + round_bit), rounding_mask);
+}
+
 } // namespace LIBC_NAMESPACE::fixed_point
 
 #endif // LIBC_COMPILER_HAS_FIXED_POINT
diff --git a/libc/src/stdfix/CMakeLists.txt b/libc/src/stdfix/CMakeLists.txt
index 1eaf64bb82a21b..6e2ed1bdfeafe7 100644
--- a/libc/src/stdfix/CMakeLists.txt
+++ b/libc/src/stdfix/CMakeLists.txt
@@ -16,3 +16,18 @@ foreach(suffix IN ITEMS hr r lr hk k lk)
       libc.src.__support.fixed_point.fx_bits
   )
 endforeach()
+
+foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
+  add_entrypoint_object(
+    round${suffix}
+    HDRS
+      round${suffix}.h
+    SRCS
+      round${suffix}.cpp
+    COMPILE_OPTIONS
+      -O3
+      -ffixed-point
+    DEPENDS
+      libc.src.__support.fixed_point.fx_bits
+  )
+endforeach()
diff --git a/libc/src/stdfix/roundhk.cpp b/libc/src/stdfix/roundhk.cpp
new file mode 100644
index 00000000000000..a4f459ea0d6538
--- /dev/null
+++ b/libc/src/stdfix/roundhk.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of roundhk 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 "roundhk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(short accum, roundhk, (short accum x, int n)) {
+  return fixed_point::round(x, n);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/roundhk.h b/libc/src/stdfix/roundhk.h
new file mode 100644
index 00000000000000..9a5c874cc030db
--- /dev/null
+++ b/libc/src/stdfix/roundhk.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for roundhk -----------------------*- 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_ROUNDHK_H
+#define LLVM_LIBC_SRC_STDFIX_ROUNDHK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+
+namespace LIBC_NAMESPACE {
+
+short accum roundhk(short accum x, int n);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ROUNDHK_H
diff --git a/libc/src/stdfix/roundhr.cpp b/libc/src/stdfix/roundhr.cpp
new file mode 100644
index 00000000000000..7757d1cc735f4c
--- /dev/null
+++ b/libc/src/stdfix/roundhr.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of roundhr 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 "roundhr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(short fract, roundhr, (short fract x, int n)) {
+  return fixed_point::round(x, n);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/roundhr.h b/libc/src/stdfix/roundhr.h
new file mode 100644
index 00000000000000..ba5a67945d6c3b
--- /dev/null
+++ b/libc/src/stdfix/roundhr.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for roundhr -----------------------*- 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_ROUNDHR_H
+#define LLVM_LIBC_SRC_STDFIX_ROUNDHR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+
+namespace LIBC_NAMESPACE {
+
+short fract roundhr(short fract x, int n);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ROUNDHR_H
diff --git a/libc/src/stdfix/roundk.cpp b/libc/src/stdfix/roundk.cpp
new file mode 100644
index 00000000000000..bf47dd9898d8f1
--- /dev/null
+++ b/libc/src/stdfix/roundk.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of roundk 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 "roundk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(accum, roundk, (accum x, int n)) {
+  return fixed_point::round(x, n);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/roundk.h b/libc/src/stdfix/roundk.h
new file mode 100644
index 00000000000000..e9fa6d8f9c3b8c
--- /dev/null
+++ b/libc/src/stdfix/roundk.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for roundk ------------------------*- 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_ROUNDK_H
+#define LLVM_LIBC_SRC_STDFIX_ROUNDK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+
+namespace LIBC_NAMESPACE {
+
+accum roundk(accum x, int n);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ROUNDK_H
diff --git a/libc/src/stdfix/roundlk.cpp b/libc/src/stdfix/roundlk.cpp
new file mode 100644
index 00000000000000..d2ffe8ab037852
--- /dev/null
+++ b/libc/src/stdfix/roundlk.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of roundlk 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 "roundlk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(long accum, roundlk, (long accum x, int n)) {
+  return fixed_point::round(x, n);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/roundlk.h b/libc/src/stdfix/roundlk.h
new file mode 100644
index 00000000000000..5fa0e90e855a64
--- /dev/null
+++ b/libc/src/stdfix/roundlk.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for roundlk -----------------------*- 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_ROUNDLK_H
+#define LLVM_LIBC_SRC_STDFIX_ROUNDLK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+
+namespace LIBC_NAMESPACE {
+
+long accum roundlk(long accum x, int n);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ROUNDLK_H
diff --git a/libc/src/stdfix/roundlr.cpp b/libc/src/stdfix/roundlr.cpp
new file mode 100644
index 00000000000000..cd4c911ffe68eb
--- /dev/null
+++ b/libc/src/stdfix/roundlr.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of roundlr 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 "roundlr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(long fract, roundlr, (long fract x, int n)) {
+  return fixed_point::round(x, n);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/roundlr.h b/libc/src/stdfix/roundlr.h
new file mode 100644
index 00000000000000..c015292e8f3f28
--- /dev/null
+++ b/libc/src/stdfix/roundlr.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for roundlr -----------------------*- 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_ROUNDLR_H
+#define LLVM_LIBC_SRC_STDFIX_ROUNDLR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+
+namespace LIBC_NAMESPACE {
+
+long fract roundlr(long fract x, int n);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ROUNDLR_H
diff --git a/libc/src/stdfix/roundr.cpp b/libc/src/stdfix/roundr.cpp
new file mode 100644
index 00000000000000..24216936d5f9bc
--- /dev/null
+++ b/libc/src/stdfix/roundr.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of roundr 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 "roundr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(fract, roundr, (fract x, int n)) {
+  return fixed_point::round(x, n);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/roundr.h b/libc/src/stdfix/roundr.h
new file mode 100644
index 00000000000000..b5b1375c882e03
--- /dev/null
+++ b/libc/src/stdfix/roundr.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for roundr ------------------------*- 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_ROUNDR_H
+#define LLVM_LIBC_SRC_STDFIX_ROUNDR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+
+namespace LIBC_NAMESPACE {
+
+fract roundr(fract x, int n);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ROUNDR_H
diff --git a/libc/src/stdfix/rounduhk.cpp b/libc/src/stdfix/rounduhk.cpp
new file mode 100644
index 00000000000000..22561588e03361
--- /dev/null
+++ b/libc/src/stdfix/rounduhk.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of rounduhk 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 "rounduhk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(unsigned short accum, rounduhk,
+                   (unsigned short accum x, int n)) {
+  return fixed_point::round(x, n);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/rounduhk.h b/libc/src/stdfix/rounduhk.h
new file mode 100644
index 00000000000000..85ebf2903ec7e9
--- /dev/null
+++ b/libc/src/stdfix/rounduhk.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for rounduhk ----------------------*- 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_ROUNDUHK_H
+#define LLVM_LIBC_SRC_STDFIX_ROUNDUHK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+
+namespace LIBC_NAMESPACE {
+
+unsigned short accum rounduhk(unsigned short accum x, int n);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ROUNDUHK_H
diff --git a/libc/src/stdfix/rounduhr.cpp b/libc/src/stdfix/rounduhr.cpp
new file mode 100644
index 00000000000000..e2e3435c15ef35
--- /dev/null
+++ b/libc/src/stdfix/rounduhr.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of rounduhr 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 "rounduhr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(unsigned short fract, rounduhr,
+                   (unsigned short fract x, int n)) {
+  return fixed_point::round(x, n);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/rounduhr.h b/libc/src/stdfix/rounduhr.h
new file mode 100644
index 00000000000000..1be0aab1f5a79d
--- /dev/null
+++ b/libc/src/stdfix/rounduhr.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for rounduhr ----------------------*- 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_ROUNDUHR_H
+#define LLVM_LIBC_SRC_STDFIX_ROUNDUHR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+
+namespace LIBC_NAMESPACE {
+
+unsigned short fract rounduhr(unsigned short fract x, int n);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ROUNDUHR_H
diff --git a/libc/src/stdfix/rounduk.cpp b/libc/src/stdfix/rounduk.cpp
new file mode 100644
index 00000000000000..b9f8522aed35d6
--- /dev/null
+++ b/libc/src/stdfix/rounduk.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of rounduk 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 "rounduk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(unsigned accum, rounduk, (unsigned accum x, int n)) {
+  return fixed_point::round(x, n);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/rounduk.h b/libc/src/stdfix/rounduk.h
new file mode 100644
index 00000000000000..8dae89586c4901
--- /dev/null
+++ b/libc/src/stdfix/rounduk.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for rounduk -----------------------*- 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_ROUNDUK_H
+#define LLVM_LIBC_SRC_STDFIX_ROUNDUK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+
+namespace LIBC_NAMESPACE {
+
+unsigned accum rounduk(unsigned accum x, int n);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ROUNDUK_H
diff --git a/libc/src/stdfix/roundulk.cpp b/libc/src/stdfix/roundulk.cpp
new file mode 100644
index 00000000000000..241b2c2c9a061f
--- /dev/null
+++ b/libc/src/stdfix/roundulk.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of roundulk 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 "roundulk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(unsigned long accum, roundulk,
+                   (unsigned long accum x, int n)) {
+  return fixed_point::round(x, n);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/roundulk.h b/libc/src/stdfix/roundulk.h
new file mode 100644
index 00000000000000..81dfd1dceb6001
--- /dev/null
+++ b/libc/src/stdfix/roundulk.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for roundulk ----------------------*- 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_ROUNDULK_H
+#define LLVM_LIBC_SRC_STDFIX_ROUNDULK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+
+namespace LIBC_NAMESPACE {
+
+unsigned long accum roundulk(unsigned long accum x, int n);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ROUNDULK_H
diff --git a/libc/src/stdfix/roundulr.cpp b/libc/src/stdfix/roundulr.cpp
new file mode 100644
index 00000000000000..6c32074520cd5d
--- /dev/null
+++ b/libc/src/stdfix/roundulr.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of roundulr 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 "roundulr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(unsigned long fract, roundulr,
+                   (unsigned long fract x, int n)) {
+  return fixed_point::round(x, n);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/roundulr.h b/libc/src/stdfix/roundulr.h
new file mode 100644
index 00000000000000..002fc94907c613
--- /dev/null
+++ b/libc/src/stdfix/roundulr.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for roundulr ----------------------*- 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_ROUNDULR_H
+#define LLVM_LIBC_SRC_STDFIX_ROUNDULR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+
+namespace LIBC_NAMESPACE {
+
+unsigned long fract roundulr(unsigned long fract x, int n);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ROUNDULR_H
diff --git a/libc/src/stdfix/roundur.cpp b/libc/src/stdfix/roundur.cpp
new file mode 100644
index 00000000000000..e91b7f11037531
--- /dev/null
+++ b/libc/src/stdfix/roundur.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of roundur 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 "roundur.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(unsigned fract, roundur, (unsigned fract x, int n)) {
+  return fixed_point::round(x, n);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/roundur.h b/libc/src/stdfix/roundur.h
new file mode 100644
index 00000000000000..72de44b1e0c4e5
--- /dev/null
+++ b/libc/src/stdfix/roundur.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for roundur -----------------------*- 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_ROUNDUR_H
+#define LLVM_LIBC_SRC_STDFIX_ROUNDUR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+
+namespace LIBC_NAMESPACE {
+
+unsigned fract roundur(unsigned fract x, int n);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ROUNDUR_H
diff --git a/libc/test/src/stdfix/CMakeLists.txt b/libc/test/src/stdfix/CMakeLists.txt
index 3b2ea9e9893126..b6e0256bb68800 100644
--- a/libc/test/src/stdfix/CMakeLists.txt
+++ b/libc/test/src/stdfix/CMakeLists.txt
@@ -21,3 +21,21 @@ foreach(suffix IN ITEMS hr r lr hk k lk)
       libc.src.__support.fixed_point.fx_bits
   )
 endforeach()
+
+foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
+  add_libc_test(
+    round${suffix}_test
+    SUITE
+      libc-stdfix-tests
+    HDRS
+      RoundTest.h
+    SRCS
+      round${suffix}_test.cpp
+    COMPILE_OPTIONS
+      -O3
+      -ffixed-point
+    DEPENDS
+      libc.src.stdfix.round${suffix}
+      libc.src.__support.fixed_point.fx_bits
+  )
+endforeach()
diff --git a/libc/test/src/stdfix/RoundTest.h b/libc/test/src/stdfix/RoundTest.h
new file mode 100644
index 00000000000000..06343addbef20e
--- /dev/null
+++ b/libc/test/src/stdfix/RoundTest.h
@@ -0,0 +1,65 @@
+//===-- Utility class to test fixed-point round -----------------*- 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 RoundTest : public LIBC_NAMESPACE::testing::Test {
+
+  using FXRep = LIBC_NAMESPACE::fixed_point::FXRep<T>;
+  static constexpr T zero = FXRep::ZERO();
+  static constexpr T min = FXRep::MIN();
+  static constexpr T max = FXRep::MAX();
+  static constexpr T half = static_cast<T>(0.5);
+  static constexpr T neg_half = static_cast<T>(-0.5);
+  static constexpr T one =
+      (FXRep::INTEGRAL_LEN > 0) ? static_cast<T>(1) : FXRep::MAX();
+  static constexpr T neg_one = static_cast<T>(-1);
+  static constexpr T eps = FXRep::EPS();
+
+public:
+  typedef T (*RoundFunc)(T, int);
+
+  void testSpecialNumbers(RoundFunc func) {
+    EXPECT_EQ(zero, func(zero, FXRep::FRACTION_LEN - 5));
+    EXPECT_EQ(max, func(min, 0));
+    EXPECT_EQ(max, func(max, FXRep::FRACTION_LEN));
+
+    EXPECT_EQ(one, func(half, 0));
+    EXPECT_EQ(half, func(half, 1));
+    EXPECT_EQ(half, func(half, FXRep::FRACTION_LEN));
+    EXPECT_EQ(one, func(half + eps, 0));
+    EXPECT_EQ(half, func(half + eps, 1));
+    EXPECT_EQ(half, func(half + eps, 2));
+    EXPECT_EQ(zero, func(half - eps, 0));
+    EXPECT_EQ(half, func(half - eps, 1));
+    EXPECT_EQ(half, func(half - eps, 2));
+    EXPECT_EQ(eps, func(eps, FXRep::FRACTION_LEN + 10));
+    EXPECT_EQ(eps << 1, func(eps, FXRep::FRACTION_LEN - 1));
+    EXPECT_EQ(zero, func(eps, FXRep::FRACTION_LEN - 2));
+
+    if constexpr (FXRep::SIGN_LEN) {
+      EXPECT_EQ(zero, func(neg_half, 0));
+      EXPECT_EQ(neg_half, func(neg_half, 1));
+      EXPECT_EQ(neg_half, func(neg_half, 3));
+      EXPECT_EQ(zero, func(neg_half + eps, 0));
+      EXPECT_EQ(neg_half, func(neg_half + eps, 1));
+      EXPECT_EQ(neg_half, func(neg_half + eps, 2));
+      EXPECT_EQ(neg_one, func(neg_half - eps, 0));
+      EXPECT_EQ(neg_half, func(neg_half - eps, 1));
+      EXPECT_EQ(neg_half, func(neg_half - eps, 2));
+      EXPECT_EQ(-eps, func(-eps, FXRep::FRACTION_LEN + 10));
+    }
+  }
+};
+
+#define LIST_ROUND_TESTS(T, func)                                              \
+  using LlvmLibcRoundTest = RoundTest<T>;                                      \
+  TEST_F(LlvmLibcRoundTest, SpecialNumbers) { testSpecialNumbers(&func); }     \
+  static_assert(true, "Require semicolon.")
diff --git a/libc/test/src/stdfix/roundhk_test.cpp b/libc/test/src/stdfix/roundhk_test.cpp
new file mode 100644
index 00000000000000..3cbcfb0e2b1eba
--- /dev/null
+++ b/libc/test/src/stdfix/roundhk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for roundhk ---------------------------------------------===//
+//
+// 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 "RoundTest.h"
+
+#include "src/stdfix/roundhk.h"
+
+LIST_ROUND_TESTS(short accum, LIBC_NAMESPACE::roundhk);
diff --git a/libc/test/src/stdfix/roundhr_test.cpp b/libc/test/src/stdfix/roundhr_test.cpp
new file mode 100644
index 00000000000000..9e58fb5b29061e
--- /dev/null
+++ b/libc/test/src/stdfix/roundhr_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for roundhr ---------------------------------------------===//
+//
+// 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 "RoundTest.h"
+
+#include "src/stdfix/roundhr.h"
+
+LIST_ROUND_TESTS(short fract, LIBC_NAMESPACE::roundhr);
diff --git a/libc/test/src/stdfix/roundk_test.cpp b/libc/test/src/stdfix/roundk_test.cpp
new file mode 100644
index 00000000000000..4092ce3c6f6329
--- /dev/null
+++ b/libc/test/src/stdfix/roundk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for roundk ----------------------------------------------===//
+//
+// 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 "RoundTest.h"
+
+#include "src/stdfix/roundk.h"
+
+LIST_ROUND_TESTS(accum, LIBC_NAMESPACE::roundk);
diff --git a/libc/test/src/stdfix/roundlk_test.cpp b/libc/test/src/stdfix/roundlk_test.cpp
new file mode 100644
index 00000000000000..c8bd1c9cb7ec04
--- /dev/null
+++ b/libc/test/src/stdfix/roundlk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for roundlk ---------------------------------------------===//
+//
+// 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 "RoundTest.h"
+
+#include "src/stdfix/roundlk.h"
+
+LIST_ROUND_TESTS(long accum, LIBC_NAMESPACE::roundlk);
diff --git a/libc/test/src/stdfix/roundlr_test.cpp b/libc/test/src/stdfix/roundlr_test.cpp
new file mode 100644
index 00000000000000..53bfbb8fc6a0e8
--- /dev/null
+++ b/libc/test/src/stdfix/roundlr_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for roundlr ---------------------------------------------===//
+//
+// 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 "RoundTest.h"
+
+#include "src/stdfix/roundlr.h"
+
+LIST_ROUND_TESTS(long fract, LIBC_NAMESPACE::roundlr);
diff --git a/libc/test/src/stdfix/roundr_test.cpp b/libc/test/src/stdfix/roundr_test.cpp
new file mode 100644
index 00000000000000..68527f1fa1400b
--- /dev/null
+++ b/libc/test/src/stdfix/roundr_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for roundr ----------------------------------------------===//
+//
+// 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 "RoundTest.h"
+
+#include "src/stdfix/roundr.h"
+
+LIST_ROUND_TESTS(fract, LIBC_NAMESPACE::roundr);
diff --git a/libc/test/src/stdfix/rounduhk_test.cpp b/libc/test/src/stdfix/rounduhk_test.cpp
new file mode 100644
index 00000000000000..d03774b681559c
--- /dev/null
+++ b/libc/test/src/stdfix/rounduhk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for rounduhk --------------------------------------------===//
+//
+// 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 "RoundTest.h"
+
+#include "src/stdfix/rounduhk.h"
+
+LIST_ROUND_TESTS(unsigned short accum, LIBC_NAMESPACE::rounduhk);
diff --git a/libc/test/src/stdfix/rounduhr_test.cpp b/libc/test/src/stdfix/rounduhr_test.cpp
new file mode 100644
index 00000000000000..889827c3349e51
--- /dev/null
+++ b/libc/test/src/stdfix/rounduhr_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for rounduhr --------------------------------------------===//
+//
+// 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 "RoundTest.h"
+
+#include "src/stdfix/rounduhr.h"
+
+LIST_ROUND_TESTS(unsigned short fract, LIBC_NAMESPACE::rounduhr);
diff --git a/libc/test/src/stdfix/rounduk_test.cpp b/libc/test/src/stdfix/rounduk_test.cpp
new file mode 100644
index 00000000000000..fbf73d5844f1d7
--- /dev/null
+++ b/libc/test/src/stdfix/rounduk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for rounduk ---------------------------------------------===//
+//
+// 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 "RoundTest.h"
+
+#include "src/stdfix/rounduk.h"
+
+LIST_ROUND_TESTS(unsigned accum, LIBC_NAMESPACE::rounduk);
diff --git a/libc/test/src/stdfix/roundulk_test.cpp b/libc/test/src/stdfix/roundulk_test.cpp
new file mode 100644
index 00000000000000..92db54e186c85b
--- /dev/null
+++ b/libc/test/src/stdfix/roundulk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for roundulk --------------------------------------------===//
+//
+// 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 "RoundTest.h"
+
+#include "src/stdfix/roundulk.h"
+
+LIST_ROUND_TESTS(unsigned long accum, LIBC_NAMESPACE::roundulk);
diff --git a/libc/test/src/stdfix/roundulr_test.cpp b/libc/test/src/stdfix/roundulr_test.cpp
new file mode 100644
index 00000000000000..11cbb46263aee0
--- /dev/null
+++ b/libc/test/src/stdfix/roundulr_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for roundulr --------------------------------------------===//
+//
+// 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 "RoundTest.h"
+
+#include "src/stdfix/roundulr.h"
+
+LIST_ROUND_TESTS(unsigned long fract, LIBC_NAMESPACE::roundulr);
diff --git a/libc/test/src/stdfix/roundur_test.cpp b/libc/test/src/stdfix/roundur_test.cpp
new file mode 100644
index 00000000000000..636f3482cdaeb5
--- /dev/null
+++ b/libc/test/src/stdfix/roundur_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for roundur ---------------------------------------------===//
+//
+// 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 "RoundTest.h"
+
+#include "src/stdfix/roundur.h"
+
+LIST_ROUND_TESTS(unsigned fract, LIBC_NAMESPACE::roundur);

>From d3b10a861e31820047887597fb6fd7f1f68eadc2 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Fri, 16 Feb 2024 17:26:36 +0000
Subject: [PATCH 2/2] Update bazel overlay and remove debugging assertions.

---
 libc/src/__support/fixed_point/fx_bits.h          | 6 +++---
 utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 7 ++++++-
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index 626cd689cdfd0f..b26be169a593a3 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -26,9 +26,9 @@ template <typename T>
 LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, T>
 bit_and(T x, T y) {
   using BitType = typename FXRep<T>::StorageType;
-  static_assert(sizeof(BitType) * CHAR_BIT == sizeof(T) * CHAR_BIT);
   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.
   return cpp::bit_cast<T, BitType>(x_bit & y_bit);
 }
 
@@ -36,9 +36,9 @@ template <typename T>
 LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, T>
 bit_or(T x, T y) {
   using BitType = typename FXRep<T>::StorageType;
-  static_assert(sizeof(BitType) * CHAR_BIT == FXRep<T>::TOTAL_LEN);
   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.
   return cpp::bit_cast<T, BitType>(x_bit | y_bit);
 }
 
@@ -46,8 +46,8 @@ template <typename T>
 LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, T>
 bit_not(T x) {
   using BitType = typename FXRep<T>::StorageType;
-  static_assert(sizeof(BitType) * CHAR_BIT == sizeof(T) * CHAR_BIT);
   BitType x_bit = cpp::bit_cast<BitType>(x);
+  // For some reason, bit_cast cannot deduce BitType from the input.
   return cpp::bit_cast<T, BitType>(~x_bit);
 }
 
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index ec5e284957e3c2..8d11fb9be188ff 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -612,10 +612,15 @@ libc_support_library(
 
 libc_support_library(
     name = "__support_fixed_point",
-    hdrs = ["src/__support/fixed_point/fx_rep.h"],
+    hdrs = [
+        "src/__support/fixed_point/fx_rep.h",
+        "src/__support/fixed_point/fx_bits.h",
+    ],
     deps = [
+        ":__support_cpp_bit",
         ":__support_cpp_type_traits",
         ":__support_macros_attributes",
+        ":__support_macros_optimization",
         ":llvm_libc_macros_stdfix_macros",
     ],
 )



More information about the libc-commits mailing list