[libc-commits] [libc] 5ff2774 - [libc][stdfix] Implement `idivfx` functions in LLVM libc (#133005)
via libc-commits
libc-commits at lists.llvm.org
Fri Apr 25 04:58:19 PDT 2025
Author: Krishna Pandey
Date: 2025-04-25T07:58:16-04:00
New Revision: 5ff277462dd717d0c52a9a8517f624b0b484e45a
URL: https://github.com/llvm/llvm-project/commit/5ff277462dd717d0c52a9a8517f624b0b484e45a
DIFF: https://github.com/llvm/llvm-project/commit/5ff277462dd717d0c52a9a8517f624b0b484e45a.diff
LOG: [libc][stdfix] Implement `idivfx` functions in LLVM libc (#133005)
This PR implements the following 8 functions along with the tests.
```c++
int idivr(fract, fract);
long int idivlr(long fract, long fract);
int idivk(accum, accum);
long int idivlk(long accum, long accum);
unsigned int idivur(unsigned fract, unsigned fract);
unsigned long int idivulr(unsigned long fract, unsigned long fract);
unsigned int idivuk(unsigned accum, unsigned accum);
unsigned long int idivulk(unsigned long accum, unsigned long accum);
```
ref: https://www.iso.org/standard/51126.html
Fixes #129125
---------
Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
Added:
libc/src/stdfix/idivk.cpp
libc/src/stdfix/idivk.h
libc/src/stdfix/idivlk.cpp
libc/src/stdfix/idivlk.h
libc/src/stdfix/idivlr.cpp
libc/src/stdfix/idivlr.h
libc/src/stdfix/idivr.cpp
libc/src/stdfix/idivr.h
libc/src/stdfix/idivuk.cpp
libc/src/stdfix/idivuk.h
libc/src/stdfix/idivulk.cpp
libc/src/stdfix/idivulk.h
libc/src/stdfix/idivulr.cpp
libc/src/stdfix/idivulr.h
libc/src/stdfix/idivur.cpp
libc/src/stdfix/idivur.h
libc/test/src/stdfix/IdivTest.h
libc/test/src/stdfix/idivk_test.cpp
libc/test/src/stdfix/idivlk_test.cpp
libc/test/src/stdfix/idivlr_test.cpp
libc/test/src/stdfix/idivr_test.cpp
libc/test/src/stdfix/idivuk_test.cpp
libc/test/src/stdfix/idivulk_test.cpp
libc/test/src/stdfix/idivulr_test.cpp
libc/test/src/stdfix/idivur_test.cpp
Modified:
libc/config/baremetal/arm/entrypoints.txt
libc/config/baremetal/riscv/entrypoints.txt
libc/config/linux/riscv/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/docs/headers/stdfix.rst
libc/include/stdfix.yaml
libc/src/__support/fixed_point/CMakeLists.txt
libc/src/__support/fixed_point/fx_bits.h
libc/src/__support/macros/null_check.h
libc/src/stdfix/CMakeLists.txt
libc/test/src/stdfix/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 835ed023fc1dc..acafef17fa5d1 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -820,6 +820,14 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
libc.src.stdfix.countlsuhk
libc.src.stdfix.countlsuk
libc.src.stdfix.countlsulk
+ libc.src.stdfix.idivr
+ libc.src.stdfix.idivlr
+ libc.src.stdfix.idivk
+ libc.src.stdfix.idivlk
+ libc.src.stdfix.idivur
+ libc.src.stdfix.idivulr
+ libc.src.stdfix.idivuk
+ libc.src.stdfix.idivulk
)
endif()
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index f224e1ea336c5..023826f12d723 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -820,6 +820,14 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
libc.src.stdfix.countlsuhk
libc.src.stdfix.countlsuk
libc.src.stdfix.countlsulk
+ libc.src.stdfix.idivr
+ libc.src.stdfix.idivlr
+ libc.src.stdfix.idivk
+ libc.src.stdfix.idivlk
+ libc.src.stdfix.idivur
+ libc.src.stdfix.idivulr
+ libc.src.stdfix.idivuk
+ libc.src.stdfix.idivulk
)
endif()
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index e3c4fe5170104..efca4c302ad31 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -775,6 +775,14 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
libc.src.stdfix.countlsuhk
libc.src.stdfix.countlsuk
libc.src.stdfix.countlsulk
+ libc.src.stdfix.idivr
+ libc.src.stdfix.idivlr
+ libc.src.stdfix.idivk
+ libc.src.stdfix.idivulk
+ libc.src.stdfix.idivur
+ libc.src.stdfix.idivulr
+ libc.src.stdfix.idivuk
+ libc.src.stdfix.idivulk
)
endif()
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 641e0a942e7bd..b598670ebc7da 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -920,6 +920,14 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
libc.src.stdfix.countlsuhk
libc.src.stdfix.countlsuk
libc.src.stdfix.countlsulk
+ libc.src.stdfix.idivr
+ libc.src.stdfix.idivlr
+ libc.src.stdfix.idivk
+ libc.src.stdfix.idivlk
+ libc.src.stdfix.idivur
+ libc.src.stdfix.idivulr
+ libc.src.stdfix.idivuk
+ libc.src.stdfix.idivulk
)
endif()
diff --git a/libc/docs/headers/stdfix.rst b/libc/docs/headers/stdfix.rst
index 20f68b4a1ed35..a2f5e94774798 100644
--- a/libc/docs/headers/stdfix.rst
+++ b/libc/docs/headers/stdfix.rst
@@ -77,7 +77,7 @@ The following functions are included in the ISO/IEC TR 18037:2008 standard.
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
| divi\* | | | | | | | | | | | | |
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
-| idiv\* | | | | | | | | | | | | |
+| idiv\* | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| |
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
| muli | | | | | | | | | | | | |
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
diff --git a/libc/include/stdfix.yaml b/libc/include/stdfix.yaml
index 29c4d8b5c8960..5b385124eb63d 100644
--- a/libc/include/stdfix.yaml
+++ b/libc/include/stdfix.yaml
@@ -238,6 +238,70 @@ functions:
arguments:
- type: unsigned long accum
guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: idivr
+ standards:
+ - stdc_ext
+ return_type: int
+ arguments:
+ - type: fract
+ - type: fract
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: idivlr
+ standards:
+ - stdc_ext
+ return_type: long int
+ arguments:
+ - type: long fract
+ - type: long fract
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: idivk
+ standards:
+ - stdc_ext
+ return_type: int
+ arguments:
+ - type: accum
+ - type: accum
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: idivlk
+ standards:
+ - stdc_ext
+ return_type: long int
+ arguments:
+ - type: long accum
+ - type: long accum
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: idivur
+ standards:
+ - stdc_ext
+ return_type: unsigned int
+ arguments:
+ - type: unsigned fract
+ - type: unsigned fract
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: idivulr
+ standards:
+ - stdc_ext
+ return_type: unsigned long int
+ arguments:
+ - type: unsigned long fract
+ - type: unsigned long fract
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: idivuk
+ standards:
+ - stdc_ext
+ return_type: unsigned int
+ arguments:
+ - type: unsigned accum
+ - type: unsigned accum
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: idivulk
+ standards:
+ - stdc_ext
+ return_type: unsigned long int
+ arguments:
+ - type: unsigned long accum
+ - type: unsigned long accum
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: roundhk
standards:
- stdc_ext
diff --git a/libc/src/__support/fixed_point/CMakeLists.txt b/libc/src/__support/fixed_point/CMakeLists.txt
index b415e2c00c488..235c03048cfa4 100644
--- a/libc/src/__support/fixed_point/CMakeLists.txt
+++ b/libc/src/__support/fixed_point/CMakeLists.txt
@@ -16,6 +16,7 @@ add_header_library(
.fx_rep
libc.include.llvm-libc-macros.stdfix_macros
libc.src.__support.macros.attributes
+ libc.src.__support.macros.null_check
libc.src.__support.macros.optimization
libc.src.__support.CPP.type_traits
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 b05f46bd34660..00c6119b4f353 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -15,6 +15,7 @@
#include "src/__support/CPP/type_traits.h"
#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+#include "src/__support/macros/null_check.h" // LIBC_CRASH_ON_VALUE
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
#include "src/__support/math_extras.h"
@@ -201,6 +202,28 @@ bitsfx(T f) {
return cpp::bit_cast<XType, T>(f);
}
+// divide the two fixed-point types and return an integer result
+template <typename T, typename XType>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, XType>
+idiv(T x, T y) {
+ using FXBits = FXBits<T>;
+ using FXRep = FXRep<T>;
+ using CompType = typename FXRep::CompType;
+
+ // If the value of the second operand of the / operator is zero, the
+ // behavior is undefined. Ref: ISO/IEC TR 18037:2008(E) p.g. 16
+ LIBC_CRASH_ON_VALUE(y, FXRep::ZERO());
+
+ CompType x_comp = static_cast<CompType>(FXBits(x).get_bits());
+ CompType y_comp = static_cast<CompType>(FXBits(y).get_bits());
+
+ // If an integer result of one of these functions overflows, the behavior is
+ // undefined. Ref: ISO/IEC TR 18037:2008(E) p.g. 16
+ CompType result = x_comp / y_comp;
+
+ return static_cast<XType>(result);
+}
+
} // namespace fixed_point
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/macros/null_check.h b/libc/src/__support/macros/null_check.h
index eda19f889235e..abf65c56c404b 100644
--- a/libc/src/__support/macros/null_check.h
+++ b/libc/src/__support/macros/null_check.h
@@ -19,10 +19,19 @@
if (LIBC_UNLIKELY((ptr) == nullptr)) \
__builtin_trap(); \
} while (0)
+#define LIBC_CRASH_ON_VALUE(var, value) \
+ do { \
+ if (LIBC_UNLIKELY((var) == (value))) \
+ __builtin_trap(); \
+ } while (0)
+
#else
#define LIBC_CRASH_ON_NULLPTR(ptr) \
do { \
} while (0)
+#define LIBC_CRASH_ON_VALUE(var, value) \
+ do { \
+ } while (0)
#endif
#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_NULL_CHECK_H
diff --git a/libc/src/stdfix/CMakeLists.txt b/libc/src/stdfix/CMakeLists.txt
index 362af0bf0d55c..843111e3f80b1 100644
--- a/libc/src/stdfix/CMakeLists.txt
+++ b/libc/src/stdfix/CMakeLists.txt
@@ -75,6 +75,20 @@ foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
)
endforeach()
+foreach(suffix IN ITEMS r lr k lk ur ulr uk ulk)
+ add_entrypoint_object(
+ idiv${suffix}
+ HDRS
+ idiv${suffix}.h
+ SRCS
+ idiv${suffix}.cpp
+ COMPILE_OPTIONS
+ ${libc_opt_high_flag}
+ DEPENDS
+ libc.src.__support.fixed_point.fx_bits
+ )
+endforeach()
+
add_entrypoint_object(
uhksqrtus
HDRS
diff --git a/libc/src/stdfix/idivk.cpp b/libc/src/stdfix/idivk.cpp
new file mode 100644
index 0000000000000..d1d758dc56995
--- /dev/null
+++ b/libc/src/stdfix/idivk.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of idivk 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 "idivk.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // accum
+#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, idivk, (accum x, accum y)) {
+ return fixed_point::idiv<accum, int>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/idivk.h b/libc/src/stdfix/idivk.h
new file mode 100644
index 0000000000000..a84bd0da2d533
--- /dev/null
+++ b/libc/src/stdfix/idivk.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for idivk ------------------------*- 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_IDIVK_H
+#define LLVM_LIBC_SRC_STDFIX_IDIVK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h" // accum
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int idivk(accum x, accum y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_IDIVK_H
diff --git a/libc/src/stdfix/idivlk.cpp b/libc/src/stdfix/idivlk.cpp
new file mode 100644
index 0000000000000..36e1df6cc58fb
--- /dev/null
+++ b/libc/src/stdfix/idivlk.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of idivlk 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 "idivlk.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // long accum
+#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(long int, idivlk, (long accum x, long accum y)) {
+ return fixed_point::idiv<long accum, long int>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/idivlk.h b/libc/src/stdfix/idivlk.h
new file mode 100644
index 0000000000000..274a61a9d82c3
--- /dev/null
+++ b/libc/src/stdfix/idivlk.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for idivlk -----------------------*- 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_IDIVLK_H
+#define LLVM_LIBC_SRC_STDFIX_IDIVLK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h" // long accum
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+long int idivlk(long accum x, long accum y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_IDIVLK_H
diff --git a/libc/src/stdfix/idivlr.cpp b/libc/src/stdfix/idivlr.cpp
new file mode 100644
index 0000000000000..1c9d62d196a29
--- /dev/null
+++ b/libc/src/stdfix/idivlr.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of idivlr 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 "idivlr.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // long fract
+#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(long int, idivlr, (long fract x, long fract y)) {
+ return fixed_point::idiv<long fract, long int>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/idivlr.h b/libc/src/stdfix/idivlr.h
new file mode 100644
index 0000000000000..de36035f289a4
--- /dev/null
+++ b/libc/src/stdfix/idivlr.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for idivlr -----------------------*- 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_IDIVLR_H
+#define LLVM_LIBC_SRC_STDFIX_IDIVLR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h" // long fract
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+long int idivlr(long fract x, long fract y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_IDIVLR_H
diff --git a/libc/src/stdfix/idivr.cpp b/libc/src/stdfix/idivr.cpp
new file mode 100644
index 0000000000000..80dd1b2107272
--- /dev/null
+++ b/libc/src/stdfix/idivr.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of idivr 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 "idivr.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // fract
+#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, idivr, (fract x, fract y)) {
+ return fixed_point::idiv<fract, int>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/idivr.h b/libc/src/stdfix/idivr.h
new file mode 100644
index 0000000000000..f3a95e2d516c3
--- /dev/null
+++ b/libc/src/stdfix/idivr.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for idivr ------------------------*- 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_IDIVR_H
+#define LLVM_LIBC_SRC_STDFIX_IDIVR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h" // fract
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+int idivr(fract x, fract y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_IDIVR_H
diff --git a/libc/src/stdfix/idivuk.cpp b/libc/src/stdfix/idivuk.cpp
new file mode 100644
index 0000000000000..27bf8edd80927
--- /dev/null
+++ b/libc/src/stdfix/idivuk.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of idivuk 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 "idivuk.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned accum
+#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(unsigned int, idivuk, (unsigned accum x, unsigned accum y)) {
+ return fixed_point::idiv<unsigned accum, unsigned int>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/idivuk.h b/libc/src/stdfix/idivuk.h
new file mode 100644
index 0000000000000..a8dce0a0b4c8b
--- /dev/null
+++ b/libc/src/stdfix/idivuk.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for idivuk ------------------------*- 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_IDIVUK_H
+#define LLVM_LIBC_SRC_STDFIX_IDIVUK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned accum
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned int idivuk(unsigned accum x, unsigned accum y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_IDIVUK_H
diff --git a/libc/src/stdfix/idivulk.cpp b/libc/src/stdfix/idivulk.cpp
new file mode 100644
index 0000000000000..8b4e63c1b78fb
--- /dev/null
+++ b/libc/src/stdfix/idivulk.cpp
@@ -0,0 +1,22 @@
+//===-- Implementation of idivulk 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 "idivulk.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned long accum
+#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(unsigned long int, idivulk,
+ (unsigned long accum x, unsigned long accum y)) {
+ return fixed_point::idiv<unsigned long accum, unsigned long int>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/idivulk.h b/libc/src/stdfix/idivulk.h
new file mode 100644
index 0000000000000..b463e76b98f5e
--- /dev/null
+++ b/libc/src/stdfix/idivulk.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for idivlk -----------------------*- 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_IDIVULK_H
+#define LLVM_LIBC_SRC_STDFIX_IDIVULK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned long accum
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned long int idivulk(unsigned long accum x, unsigned long accum y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_IDIVULK_H
diff --git a/libc/src/stdfix/idivulr.cpp b/libc/src/stdfix/idivulr.cpp
new file mode 100644
index 0000000000000..6e6a780c1b8c5
--- /dev/null
+++ b/libc/src/stdfix/idivulr.cpp
@@ -0,0 +1,22 @@
+//===-- Implementation of idivulr 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 "idivulr.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned long fract
+#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(unsigned long int, idivulr,
+ (unsigned long fract x, unsigned long fract y)) {
+ return fixed_point::idiv<unsigned long fract, unsigned long int>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/idivulr.h b/libc/src/stdfix/idivulr.h
new file mode 100644
index 0000000000000..c2f6a1911bd37
--- /dev/null
+++ b/libc/src/stdfix/idivulr.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for idivulr ----------------------*- 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_IDIVULR_H
+#define LLVM_LIBC_SRC_STDFIX_IDIVULR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned long fract
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned long int idivulr(unsigned long fract x, unsigned long fract y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_IDIVULR_H
diff --git a/libc/src/stdfix/idivur.cpp b/libc/src/stdfix/idivur.cpp
new file mode 100644
index 0000000000000..319817b9662d3
--- /dev/null
+++ b/libc/src/stdfix/idivur.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of idivur 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 "idivur.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned fract
+#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(unsigned int, idivur, (unsigned fract x, unsigned fract y)) {
+ return fixed_point::idiv<unsigned fract, unsigned int>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/idivur.h b/libc/src/stdfix/idivur.h
new file mode 100644
index 0000000000000..f69db20bcf512
--- /dev/null
+++ b/libc/src/stdfix/idivur.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for idivur -----------------------*- 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_IDIVUR_H
+#define LLVM_LIBC_SRC_STDFIX_IDIVUR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned fract
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned int idivur(unsigned fract x, unsigned fract y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_IDIVUR_H
diff --git a/libc/test/src/stdfix/CMakeLists.txt b/libc/test/src/stdfix/CMakeLists.txt
index a3dc25762f549..e2b4bc1805f7c 100644
--- a/libc/test/src/stdfix/CMakeLists.txt
+++ b/libc/test/src/stdfix/CMakeLists.txt
@@ -104,6 +104,22 @@ foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
)
endforeach()
+foreach(suffix IN ITEMS r lr k lk ur ulr uk ulk)
+ add_libc_test(
+ idiv${suffix}_test
+ SUITE
+ libc-stdfix-tests
+ HDRS
+ IdivTest.h
+ SRCS
+ idiv${suffix}_test.cpp
+ DEPENDS
+ libc.src.stdfix.idiv${suffix}
+ libc.src.__support.fixed_point.fx_bits
+ libc.hdr.signal_macros
+ )
+endforeach()
+
add_libc_test(
uhksqrtus_test
SUITE
diff --git a/libc/test/src/stdfix/IdivTest.h b/libc/test/src/stdfix/IdivTest.h
new file mode 100644
index 0000000000000..6bfe9dff01a39
--- /dev/null
+++ b/libc/test/src/stdfix/IdivTest.h
@@ -0,0 +1,91 @@
+//===-- Utility class to test idivfx functions ------------------*- 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"
+#include "src/__support/macros/sanitizer.h"
+
+#include "hdr/signal_macros.h"
+
+template <typename T, typename XType>
+class IdivTest : public LIBC_NAMESPACE::testing::Test {
+
+ using FXRep = LIBC_NAMESPACE::fixed_point::FXRep<T>;
+
+ static constexpr T zero = FXRep::ZERO();
+ static constexpr T max = FXRep::MAX();
+ static constexpr T min = FXRep::MIN();
+ static constexpr T one_half = FXRep::ONE_HALF();
+ static constexpr T one_fourth = FXRep::ONE_FOURTH();
+
+public:
+ typedef XType (*IdivFunc)(T, T);
+
+ void testSpecialNumbers(IdivFunc func) {
+ constexpr bool is_signed = (FXRep::SIGN_LEN > 0);
+ constexpr bool has_integral = (FXRep::INTEGRAL_LEN > 0);
+
+ EXPECT_EQ(func(one_half, one_fourth), static_cast<XType>(2));
+ EXPECT_EQ(func(one_half, one_half), static_cast<XType>(1));
+ EXPECT_EQ(func(one_fourth, one_half), static_cast<XType>(0));
+ EXPECT_EQ(func(0.75, 0.25), static_cast<XType>(3));
+ EXPECT_EQ(func(0.625, 0.125), static_cast<XType>(5));
+
+ if constexpr (is_signed) {
+ EXPECT_EQ(func(min, one_half), static_cast<XType>(min) * 2);
+ } else {
+ EXPECT_EQ(func(min, one_half), static_cast<XType>(0));
+ }
+
+ if constexpr (has_integral && min <= 7 && max >= 5) {
+ EXPECT_EQ(func(6.9, 4.2), static_cast<XType>(1));
+ EXPECT_EQ(func(4.2, 6.9), static_cast<XType>(0));
+ EXPECT_EQ(func(4.5, 2.2), static_cast<XType>(2));
+ EXPECT_EQ(func(2.2, 1.1), static_cast<XType>(2));
+ EXPECT_EQ(func(2.25, 1.0), static_cast<XType>(2));
+ EXPECT_EQ(func(2.25, 3.0), static_cast<XType>(0));
+
+ if constexpr (is_signed) {
+ EXPECT_EQ(func(4.2, -6.9), static_cast<XType>(0));
+ EXPECT_EQ(func(-6.9, 4.2), static_cast<XType>(-1));
+ EXPECT_EQ(func(-2.5, 1.25), static_cast<XType>(-2));
+ EXPECT_EQ(func(-2.25, 1.0), static_cast<XType>(-2));
+ EXPECT_EQ(func(2.25, -3.0), static_cast<XType>(0));
+ }
+ }
+ }
+
+ void testInvalidNumbers(IdivFunc func) {
+ constexpr bool has_integral = (FXRep::INTEGRAL_LEN > 0);
+
+ EXPECT_DEATH([func] { func(0.5, 0.0); }, WITH_SIGNAL(SIGILL));
+ if constexpr (has_integral) {
+ EXPECT_DEATH([func] { func(2.5, 0.0); }, WITH_SIGNAL(SIGSEGV));
+ }
+ }
+};
+
+#if defined(LIBC_ADD_NULL_CHECKS) && !defined(LIBC_HAS_SANITIZER)
+#define LIST_IDIV_TESTS(Name, T, XTYpe, func) \
+ using LlvmLibcIdiv##Name##Test = IdivTest<T, XType>; \
+ TEST_F(LlvmLibcIdiv##Name##Test, InvalidNumbers) { \
+ testInvalidNumbers(&func); \
+ } \
+ TEST_F(LlvmLibcIdiv##Name##Test, SpecialNumbers) { \
+ testSpecialNumbers(&func); \
+ } \
+ static_assert(true, "Require semicolon.")
+#else
+#define LIST_IDIV_TESTS(Name, T, XType, func) \
+ using LlvmLibcIdiv##Name##Test = IdivTest<T, XType>; \
+ TEST_F(LlvmLibcIdiv##Name##Test, SpecialNumbers) { \
+ testSpecialNumbers(&func); \
+ } \
+ static_assert(true, "Require semicolon.")
+#endif // LIBC_HAS_ADDRESS_SANITIZER
diff --git a/libc/test/src/stdfix/idivk_test.cpp b/libc/test/src/stdfix/idivk_test.cpp
new file mode 100644
index 0000000000000..b10a43ed6135a
--- /dev/null
+++ b/libc/test/src/stdfix/idivk_test.cpp
@@ -0,0 +1,14 @@
+//===-- Unittests for idivk -----------------------------------------------===//
+//
+// 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 "IdivTest.h"
+
+#include "llvm-libc-macros/stdfix-macros.h" // accum
+#include "src/stdfix/idivk.h"
+
+LIST_IDIV_TESTS(k, accum, int, LIBC_NAMESPACE::idivk);
diff --git a/libc/test/src/stdfix/idivlk_test.cpp b/libc/test/src/stdfix/idivlk_test.cpp
new file mode 100644
index 0000000000000..dcd4ccbcc4a78
--- /dev/null
+++ b/libc/test/src/stdfix/idivlk_test.cpp
@@ -0,0 +1,14 @@
+//===-- Unittests for idivlk ----------------------------------------------===//
+//
+// 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 "IdivTest.h"
+
+#include "llvm-libc-macros/stdfix-macros.h" // long accum
+#include "src/stdfix/idivlk.h"
+
+LIST_IDIV_TESTS(lk, long accum, long int, LIBC_NAMESPACE::idivlk);
diff --git a/libc/test/src/stdfix/idivlr_test.cpp b/libc/test/src/stdfix/idivlr_test.cpp
new file mode 100644
index 0000000000000..0fdb1e3a19e8f
--- /dev/null
+++ b/libc/test/src/stdfix/idivlr_test.cpp
@@ -0,0 +1,14 @@
+//===-- Unittests for idivlr ----------------------------------------------===//
+//
+// 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 "IdivTest.h"
+
+#include "llvm-libc-macros/stdfix-macros.h" // long fract
+#include "src/stdfix/idivlr.h"
+
+LIST_IDIV_TESTS(lr, long fract, long int, LIBC_NAMESPACE::idivlr);
diff --git a/libc/test/src/stdfix/idivr_test.cpp b/libc/test/src/stdfix/idivr_test.cpp
new file mode 100644
index 0000000000000..82bec5c7be069
--- /dev/null
+++ b/libc/test/src/stdfix/idivr_test.cpp
@@ -0,0 +1,14 @@
+//===-- Unittests for idivr -----------------------------------------------===//
+//
+// 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 "IdivTest.h"
+
+#include "llvm-libc-macros/stdfix-macros.h" // fract
+#include "src/stdfix/idivr.h"
+
+LIST_IDIV_TESTS(r, fract, int, LIBC_NAMESPACE::idivr);
diff --git a/libc/test/src/stdfix/idivuk_test.cpp b/libc/test/src/stdfix/idivuk_test.cpp
new file mode 100644
index 0000000000000..2bfd93da3ed4a
--- /dev/null
+++ b/libc/test/src/stdfix/idivuk_test.cpp
@@ -0,0 +1,14 @@
+//===-- Unittests for idivuk ----------------------------------------------===//
+//
+// 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 "IdivTest.h"
+
+#include "llvm-libc-macros/stdfix-macros.h" // unsigned accum
+#include "src/stdfix/idivuk.h"
+
+LIST_IDIV_TESTS(uk, unsigned accum, unsigned int, LIBC_NAMESPACE::idivuk);
diff --git a/libc/test/src/stdfix/idivulk_test.cpp b/libc/test/src/stdfix/idivulk_test.cpp
new file mode 100644
index 0000000000000..31eb96114a0ce
--- /dev/null
+++ b/libc/test/src/stdfix/idivulk_test.cpp
@@ -0,0 +1,15 @@
+//===-- Unittests for idivulk ---------------------------------------------===//
+//
+// 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 "IdivTest.h"
+
+#include "llvm-libc-macros/stdfix-macros.h" // unsigned long accum
+#include "src/stdfix/idivulk.h"
+
+LIST_IDIV_TESTS(ulk, unsigned long accum, unsigned long int,
+ LIBC_NAMESPACE::idivulk);
diff --git a/libc/test/src/stdfix/idivulr_test.cpp b/libc/test/src/stdfix/idivulr_test.cpp
new file mode 100644
index 0000000000000..6f43df149a127
--- /dev/null
+++ b/libc/test/src/stdfix/idivulr_test.cpp
@@ -0,0 +1,15 @@
+//===-- Unittests for idivulr ---------------------------------------------===//
+//
+// 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 "IdivTest.h"
+
+#include "llvm-libc-macros/stdfix-macros.h" // unsigned long fract
+#include "src/stdfix/idivulr.h"
+
+LIST_IDIV_TESTS(ulr, unsigned long fract, unsigned long int,
+ LIBC_NAMESPACE::idivulr);
diff --git a/libc/test/src/stdfix/idivur_test.cpp b/libc/test/src/stdfix/idivur_test.cpp
new file mode 100644
index 0000000000000..c2d2f9caf19d9
--- /dev/null
+++ b/libc/test/src/stdfix/idivur_test.cpp
@@ -0,0 +1,14 @@
+//===-- Unittests for idivur ----------------------------------------------===//
+//
+// 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 "IdivTest.h"
+
+#include "llvm-libc-macros/stdfix-macros.h" // unsigned fract
+#include "src/stdfix/idivur.h"
+
+LIST_IDIV_TESTS(ur, unsigned fract, unsigned int, LIBC_NAMESPACE::idivur);
More information about the libc-commits
mailing list