Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[libc][stdfix] Implement countlsfx functions #114318

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions libc/config/baremetal/arm/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions libc/config/baremetal/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions libc/config/linux/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions libc/spec/stdc_ext.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">,
Expand Down
1 change: 1 addition & 0 deletions libc/src/__support/fixed_point/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
39 changes: 38 additions & 1 deletion libc/src/__support/fixed_point/fx_bits.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 = -(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>;
Expand Down
12 changes: 12 additions & 0 deletions libc/src/__support/fixed_point/fx_rep.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand All @@ -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; }
Expand All @@ -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; }
Expand All @@ -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; }
Expand All @@ -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; }
Expand All @@ -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; }
Expand All @@ -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; }
Expand All @@ -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; }
Expand All @@ -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; }
Expand All @@ -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; }
Expand All @@ -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; }
Expand All @@ -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; }
Expand Down
14 changes: 14 additions & 0 deletions libc/src/stdfix/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
20 changes: 20 additions & 0 deletions libc/src/stdfix/countlshk.cpp
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions libc/src/stdfix/countlshk.h
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions libc/src/stdfix/countlshr.cpp
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions libc/src/stdfix/countlshr.h
Original file line number Diff line number Diff line change
@@ -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
18 changes: 18 additions & 0 deletions libc/src/stdfix/countlsk.cpp
Original file line number Diff line number Diff line change
@@ -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
Loading
Loading