-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc][stdfix] Implement countlsfx
functions
#114318
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-libc Author: Duncan (duncpro) ChangesCloses #113357 Patch is 47.32 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/114318.diff 47 Files Affected:
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 68030f7f1775b5..55af5413259a30 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -427,6 +427,18 @@ set(TARGET_LIBM_ENTRYPOINTS
if(LIBC_COMPILER_HAS_FIXED_POINT)
list(APPEND TARGET_LIBM_ENTRYPOINTS
# stdfix.h _Fract and _Accum entrypoints
+ libc.src.stdfix.countlshk
+ libc.src.stdfix.countlshr
+ libc.src.stdfix.countlsk
+ libc.src.stdfix.countlslk
+ libc.src.stdfix.countlslr
+ libc.src.stdfix.countlsr
+ libc.src.stdfix.countlsuhk
+ libc.src.stdfix.countlsuhr
+ libc.src.stdfix.countlsuk
+ libc.src.stdfix.countlsulk
+ libc.src.stdfix.countlsulr
+ libc.src.stdfix.countlsur
libc.src.stdfix.abshk
libc.src.stdfix.abshr
libc.src.stdfix.absk
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 5894b591072ef0..baa4b27b98aee0 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -422,6 +422,18 @@ set(TARGET_LIBM_ENTRYPOINTS
if(LIBC_COMPILER_HAS_FIXED_POINT)
list(APPEND TARGET_LIBM_ENTRYPOINTS
# stdfix.h _Fract and _Accum entrypoints
+ libc.src.stdfix.countlshk
+ libc.src.stdfix.countlshr
+ libc.src.stdfix.countlsk
+ libc.src.stdfix.countlslk
+ libc.src.stdfix.countlslr
+ libc.src.stdfix.countlsr
+ libc.src.stdfix.countlsuhk
+ libc.src.stdfix.countlsuhr
+ libc.src.stdfix.countlsuk
+ libc.src.stdfix.countlsulk
+ libc.src.stdfix.countlsulr
+ libc.src.stdfix.countlsur
libc.src.stdfix.abshk
libc.src.stdfix.abshr
libc.src.stdfix.absk
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 5c09edf7cfb266..cbbe9d226e05f9 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -677,6 +677,18 @@ endif()
if(LIBC_COMPILER_HAS_FIXED_POINT)
list(APPEND TARGET_LIBM_ENTRYPOINTS
# stdfix.h _Fract and _Accum entrypoints
+ libc.src.stdfix.countlshk
+ libc.src.stdfix.countlshr
+ libc.src.stdfix.countlsk
+ libc.src.stdfix.countlslk
+ libc.src.stdfix.countlslr
+ libc.src.stdfix.countlsr
+ libc.src.stdfix.countlsuhk
+ libc.src.stdfix.countlsuhr
+ libc.src.stdfix.countlsuk
+ libc.src.stdfix.countlsulk
+ libc.src.stdfix.countlsulr
+ libc.src.stdfix.countlsur
libc.src.stdfix.abshk
libc.src.stdfix.abshr
libc.src.stdfix.absk
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index a2fb97d04584d5..c0bf1ce50328e5 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -780,6 +780,18 @@ endif()
if(LIBC_COMPILER_HAS_FIXED_POINT)
list(APPEND TARGET_LIBM_ENTRYPOINTS
# stdfix.h _Fract and _Accum entrypoints
+ libc.src.stdfix.countlshk
+ libc.src.stdfix.countlshr
+ libc.src.stdfix.countlsk
+ libc.src.stdfix.countlslk
+ libc.src.stdfix.countlslr
+ libc.src.stdfix.countlsr
+ libc.src.stdfix.countlsuhk
+ libc.src.stdfix.countlsuhr
+ libc.src.stdfix.countlsuk
+ libc.src.stdfix.countlsulk
+ libc.src.stdfix.countlsulr
+ libc.src.stdfix.countlsur
libc.src.stdfix.abshk
libc.src.stdfix.abshr
libc.src.stdfix.absk
diff --git a/libc/spec/stdc_ext.td b/libc/spec/stdc_ext.td
index 6620142146c471..26f2d526168ce7 100644
--- a/libc/spec/stdc_ext.td
+++ b/libc/spec/stdc_ext.td
@@ -24,6 +24,23 @@ def StdcExt : StandardSpec<"stdc_ext"> {
[], // types
[], // enums
[ // functions
+
+ GuardedFunctionSpec<"countlshr", RetValSpec<ShortFractType>, [ArgSpec<ShortFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlsr", RetValSpec<FractType>, [ArgSpec<FractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlslr", RetValSpec<LongFractType>, [ArgSpec<LongFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
+ GuardedFunctionSpec<"countlshk", RetValSpec<ShortAccumType>, [ArgSpec<ShortAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlsk", RetValSpec<AccumType>, [ArgSpec<AccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlslk", RetValSpec<LongAccumType>, [ArgSpec<LongAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
+ GuardedFunctionSpec<"countlsuhr", RetValSpec<UnsignedShortFractType>, [ArgSpec<UnsignedShortFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlsur", RetValSpec<UnsignedFractType>, [ArgSpec<UnsignedFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlsulr", RetValSpec<UnsignedLongFractType>, [ArgSpec<UnsignedLongFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
+ GuardedFunctionSpec<"countlsuhk", RetValSpec<UnsignedShortAccumType>, [ArgSpec<UnsignedShortAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlsuk", RetValSpec<UnsignedAccumType>, [ArgSpec<UnsignedAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlsulk", RetValSpec<UnsignedLongAccumType>, [ArgSpec<UnsignedLongAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
GuardedFunctionSpec<"abshr", RetValSpec<ShortFractType>, [ArgSpec<ShortFractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"absr", RetValSpec<FractType>, [ArgSpec<FractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"abslr", RetValSpec<LongFractType>, [ArgSpec<LongFractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
diff --git a/libc/src/__support/fixed_point/CMakeLists.txt b/libc/src/__support/fixed_point/CMakeLists.txt
index 3b744081765e4f..2531285d5c9cb2 100644
--- a/libc/src/__support/fixed_point/CMakeLists.txt
+++ b/libc/src/__support/fixed_point/CMakeLists.txt
@@ -20,6 +20,7 @@ add_header_library(
libc.src.__support.CPP.type_traits
libc.src.__support.CPP.bit
libc.src.__support.math_extras
+ libc.src.__support.CPP.limits
)
add_header_library(
diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index 0a4c21fb6a14f7..3ff5cc7011fb89 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -11,8 +11,9 @@
#include "include/llvm-libc-macros/stdfix-macros.h"
#include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/limits.h" // numeric_limits
#include "src/__support/CPP/type_traits.h"
-#include "src/__support/macros/attributes.h" // LIBC_INLINE
+#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
#include "src/__support/math_extras.h"
@@ -66,6 +67,23 @@ template <typename T> struct FXBits {
}
}
+ // Clause 6.2.6.3 of ISO/IEC TR 18037 defines the value bits of a fixed-point
+ // type to include the integral and fraction bits but not padding nor sign
+ // bits.
+ //
+ // This function returns the value bits, right-aligned, as an unsigned integer
+ // type which is at least large enough to hold them all.
+ //
+ // Note the integral and fraction bits are contiguous. The rightmost bits in
+ // the returned value are the fraciton bits, then immediately left of those
+ // are the integral bits.
+ //
+ // Any left-padding in the return value is guaranteed to be zero.
+ LIBC_INLINE constexpr StorageType get_value_bits() {
+ constexpr StorageType VALUE_MASK = INTEGRAL_MASK | FRACTION_MASK;
+ return (value & VALUE_MASK) >> FRACTION_OFFSET;
+ }
+
LIBC_INLINE constexpr StorageType get_fraction() {
return (value & FRACTION_MASK) >> FRACTION_OFFSET;
}
@@ -142,6 +160,25 @@ template <typename T> LIBC_INLINE constexpr T abs(T x) {
}
}
+template <typename T>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, int>
+countls(T x) {
+ using FXRep = FXRep<T>;
+ using BitType = typename FXRep::StorageType;
+ constexpr int CONTAIN_LEN = cpp::numeric_limits<BitType>::digits;
+ constexpr int PADDING_LEN = CONTAIN_LEN - FXRep::VALUE_LEN;
+
+ if constexpr (FXRep::SIGN_LEN != 0) {
+ if (x < 0) {
+ x = abs(x + FXRep::EPS());
+ }
+ }
+
+ FXBits<T> fxbits(x);
+ BitType value_bits = fxbits.get_value_bits();
+ return cpp::countl_zero(value_bits) - PADDING_LEN;
+}
+
// Round-to-nearest, tie-to-(+Inf)
template <typename T> LIBC_INLINE constexpr T round(T x, int n) {
using FXRep = FXRep<T>;
diff --git a/libc/src/__support/fixed_point/fx_rep.h b/libc/src/__support/fixed_point/fx_rep.h
index 186938947694e5..f1321e6a629ee5 100644
--- a/libc/src/__support/fixed_point/fx_rep.h
+++ b/libc/src/__support/fixed_point/fx_rep.h
@@ -45,6 +45,7 @@ template <> struct FXRep<short fract> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SFRACT_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return SFRACT_MIN; }
LIBC_INLINE static constexpr Type MAX() { return SFRACT_MAX; }
@@ -65,6 +66,7 @@ template <> struct FXRep<unsigned short fract> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USFRACT_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return USFRACT_MIN; }
LIBC_INLINE static constexpr Type MAX() { return USFRACT_MAX; }
@@ -85,6 +87,7 @@ template <> struct FXRep<fract> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = FRACT_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return FRACT_MIN; }
LIBC_INLINE static constexpr Type MAX() { return FRACT_MAX; }
@@ -105,6 +108,7 @@ template <> struct FXRep<unsigned fract> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = UFRACT_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return UFRACT_MIN; }
LIBC_INLINE static constexpr Type MAX() { return UFRACT_MAX; }
@@ -125,6 +129,7 @@ template <> struct FXRep<long fract> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = LFRACT_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return LFRACT_MIN; }
LIBC_INLINE static constexpr Type MAX() { return LFRACT_MAX; }
@@ -145,6 +150,7 @@ template <> struct FXRep<unsigned long fract> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ULFRACT_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return ULFRACT_MIN; }
LIBC_INLINE static constexpr Type MAX() { return ULFRACT_MAX; }
@@ -165,6 +171,7 @@ template <> struct FXRep<short accum> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SACCUM_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return SACCUM_MIN; }
LIBC_INLINE static constexpr Type MAX() { return SACCUM_MAX; }
@@ -185,6 +192,7 @@ template <> struct FXRep<unsigned short accum> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USACCUM_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return USACCUM_MIN; }
LIBC_INLINE static constexpr Type MAX() { return USACCUM_MAX; }
@@ -205,6 +213,7 @@ template <> struct FXRep<accum> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ACCUM_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return ACCUM_MIN; }
LIBC_INLINE static constexpr Type MAX() { return ACCUM_MAX; }
@@ -225,6 +234,7 @@ template <> struct FXRep<unsigned accum> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = UACCUM_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return UACCUM_MIN; }
LIBC_INLINE static constexpr Type MAX() { return UACCUM_MAX; }
@@ -245,6 +255,7 @@ template <> struct FXRep<long accum> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = LACCUM_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return LACCUM_MIN; }
LIBC_INLINE static constexpr Type MAX() { return LACCUM_MAX; }
@@ -265,6 +276,7 @@ template <> struct FXRep<unsigned long accum> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ULACCUM_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return ULACCUM_MIN; }
LIBC_INLINE static constexpr Type MAX() { return ULACCUM_MAX; }
diff --git a/libc/src/stdfix/CMakeLists.txt b/libc/src/stdfix/CMakeLists.txt
index 10d76ae31349f9..69e0117effb50d 100644
--- a/libc/src/stdfix/CMakeLists.txt
+++ b/libc/src/stdfix/CMakeLists.txt
@@ -2,6 +2,20 @@ if(NOT LIBC_COMPILER_HAS_FIXED_POINT)
return()
endif()
+foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
+ add_entrypoint_object(
+ countls${suffix}
+ HDRS
+ countls${suffix}.h
+ SRCS
+ countls${suffix}.cpp
+ COMPILE_OPTIONS
+ -O3
+ DEPENDS
+ libc.src.__support.fixed_point.fx_bits
+ )
+endforeach()
+
foreach(suffix IN ITEMS hr r lr hk k lk)
add_entrypoint_object(
abs${suffix}
diff --git a/libc/src/stdfix/countlshk.cpp b/libc/src/stdfix/countlshk.cpp
new file mode 100644
index 00000000000000..d65d96312c0768
--- /dev/null
+++ b/libc/src/stdfix/countlshk.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "countlshk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlshk, (short accum x)) {
+ return fixed_point::countls(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlshk.h b/libc/src/stdfix/countlshk.h
new file mode 100644
index 00000000000000..279fb985552347
--- /dev/null
+++ b/libc/src/stdfix/countlshk.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDFIX_COUNTLSHK_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSHK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlshk(short accum x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSHK_H
diff --git a/libc/src/stdfix/countlshr.cpp b/libc/src/stdfix/countlshr.cpp
new file mode 100644
index 00000000000000..ed3fd23e0cdf8f
--- /dev/null
+++ b/libc/src/stdfix/countlshr.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "countlshr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlshr, (short fract x)) {
+ return fixed_point::countls(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlshr.h b/libc/src/stdfix/countlshr.h
new file mode 100644
index 00000000000000..a2307ee0656ced
--- /dev/null
+++ b/libc/src/stdfix/countlshr.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDFIX_COUNTLSHR_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSHR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlshr(short fract x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSHR_H
diff --git a/libc/src/stdfix/countlsk.cpp b/libc/src/stdfix/countlsk.cpp
new file mode 100644
index 00000000000000..470f2e28539c16
--- /dev/null
+++ b/libc/src/stdfix/countlsk.cpp
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "countlsk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsk, (accum x)) { return fixed_point::countls(x); }
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlsk.h b/libc/src/stdfix/countlsk.h
new file mode 100644
index 00000000000000..fff9bed7499c5b
--- /dev/null
+++ b/libc/src/stdfix/countlsk.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDFIX_COUNTLSK_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsk(accum x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSK_H
diff --git a/libc/src/stdfix/countlsl...
[truncated]
|
countlsfx
functionscountlsfx
functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few nits/requests then I'd be happy to give an LGTM after:
- For each of the
LIST_COUNTLS_TESTS
, could you also add one for the saturation equivalent of each test? Saturation shouldn't affect the result but it would be nice to assert this is the case. - Clang also has a mode
-fpadding-on-unsigned-fixed-point
which makes the number of fractional bits for each unsigned fixed point type the same as the number of fractional bits for each corresponding signed type, effectively adding a byte of padding for unsigned types. This is an optional feature that allows us to omit a shift when converting between equivalent signed + unsigned types. Would it also be possible to have a run through each of the tests that enables this flag? I imagine in cmake we could do something likecheck_cxx_compiler_flag(-fpadding-on-unsigned-fixed-point)
to first check if we can build a variant of tests with this flag.
…egative fractional test cases
AFAIK ![]() However, saturating arithmetic can be requested for non- ![]() But it appears ![]() @PiJoules Can you give guidance? |
Oh what I mean was having some tests that pass saturating types to each of the functions taking non-saturating equivalent types, so something like:
I wanted this just to assert that the result is correct independent of the saturation, but in hindsight I think that might not be appropriate here since that would be more along the lines of testing |
✅ With the latest revision this PR passed the C/C++ code formatter. |
@PiJoules Testing The tests fail when this flag is enabled, and after investigating, I don't see any obvious reason. For instance, this assertion fails for EXPECT_EQ(0, func(max)); // EXPECT_EQ(0, 1) I'll continue to investigate. In the meantime if anyone else has any ideas please let me know. EDIT: It turns out the tests were not passing because the compiler flag was not set on both the unit test target and the entrypoint target. I've wired together a target that will build and test with I'll add the entrypoints for the other architectures after you've had a chance to look at this commit and comment on my approach. |
libc.src.__support.fixed_point.fx_bits | ||
) | ||
|
||
if(LIBC_COMPILER_HAS_PADDING_ON_UNSIGNED_FIXED_POINT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need these extra entry points built with this flag? Are they supposed to be on or off by default?
If it's only for testing with and without the -Xclang=-fpadding-on-unsigned-fixed-point
, then using FLAGS
in the main entry points is more apt.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this flag should just be used for tests. This flag isn't on by default in clang but if users want it then they can add it when building llvm-libc from source.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need these extra entry points built with this flag? Are they supposed to be on or off by default? If it's only for testing with and without the
-Xclang=-fpadding-on-unsigned-fixed-point
, then usingFLAGS
in the main entry points is more apt.
Yes, the idea is to run all countlsfx tests twice. Once with -Xclang=-fpadding-on-unsigned-fixed-point
and once without. I'm not sure what you mean by "using FLAGS
in the main entry point".
Are there any other places in the codebase where we run the same test set twice but differ the flags? If so, I can mirror what is done there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM on my end. Thanks! Let's get @lntue's thumbs up before landing.
libc.src.__support.fixed_point.fx_bits | ||
) | ||
|
||
if(LIBC_COMPILER_HAS_PADDING_ON_UNSIGNED_FIXED_POINT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this flag should just be used for tests. This flag isn't on by default in clang but if users want it then they can add it when building llvm-libc from source.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there are some issues with your compile flag checking. Also @lntue do you have any comments on setting this up to use flags?
@@ -140,3 +145,4 @@ check_cxx_compiler_flag("-nostdlib++" LIBC_CC_SUPPORTS_NOSTDLIBPP) | |||
|
|||
# clang-3.0+ | |||
check_cxx_compiler_flag("-nostdlibinc" LIBC_CC_SUPPORTS_NOSTDLIBINC) | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: looks like you added an extra space here
@@ -0,0 +1 @@ | |||
#include "include/llvm-libc-macros/stdfix-macros.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this file supposed to have more? Maybe an ifdef
to check the proper values are being defined? Notably, if you don't pass -ffixed-point
to clang this will compile successfully, since stdfix-macros.h
checks that before defining anything else.
elseif(${feature} STREQUAL "padding_on_unsigned_fixed_point") | ||
list(APPEND compile_options "-Xclang=-fpadding-on-unsigned-fixed-point") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you also need to add -ffixed-point
here.
Closes #113357