Skip to content

Commit

Permalink
[libc] implement countlsfx
Browse files Browse the repository at this point in the history
  • Loading branch information
duncpro committed Oct 30, 2024
1 parent efc6d33 commit 888f7ce
Show file tree
Hide file tree
Showing 47 changed files with 839 additions and 1 deletion.
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 = 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>;
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

0 comments on commit 888f7ce

Please sign in to comment.