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

Closed
wants to merge 7 commits into from
Closed
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
6 changes: 6 additions & 0 deletions libc/cmake/modules/CheckCompilerFeatures.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ set(
"float16_conversion"
"float128"
"fixed_point"
"padding_on_unsigned_fixed_point"
)

# Making sure ALL_COMPILER_FEATURES is sorted.
Expand Down Expand Up @@ -62,6 +63,8 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
set(link_options "")
if(${feature} STREQUAL "fixed_point")
list(APPEND compile_options "-ffixed-point")
elseif(${feature} STREQUAL "padding_on_unsigned_fixed_point")
list(APPEND compile_options "-Xclang=-fpadding-on-unsigned-fixed-point")
Comment on lines +66 to +67
Copy link
Contributor

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.

elseif(${feature} MATCHES "^builtin_" OR
${feature} STREQUAL "float16_conversion")
set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT})
Expand Down Expand Up @@ -110,6 +113,8 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
set(LIBC_TYPES_HAS_FLOAT128 TRUE)
elseif(${feature} STREQUAL "fixed_point")
set(LIBC_COMPILER_HAS_FIXED_POINT TRUE)
elseif(${feature} STREQUAL "padding_on_unsigned_fixed_point")
set(LIBC_COMPILER_HAS_PADDING_ON_UNSIGNED_FIXED_POINT TRUE)
elseif(${feature} STREQUAL "builtin_ceil_floor_rint_trunc")
set(LIBC_COMPILER_HAS_BUILTIN_CEIL_FLOOR_RINT_TRUNC TRUE)
elseif(${feature} STREQUAL "builtin_fmax_fmin")
Expand Down Expand Up @@ -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)

Copy link
Contributor

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

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "include/llvm-libc-macros/stdfix-macros.h"
Copy link
Contributor

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.

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
29 changes: 29 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -778,8 +778,37 @@ if(LIBC_TYPES_HAS_FLOAT128)
endif()

if(LIBC_COMPILER_HAS_FIXED_POINT)
if(LIBC_COMPILER_HAS_PADDING_ON_UNSIGNED_FIXED_POINT)
list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.stdfix.countlshk_padding_on_unsigned_fixed_point
libc.src.stdfix.countlshr_padding_on_unsigned_fixed_point
libc.src.stdfix.countlsk_padding_on_unsigned_fixed_point
libc.src.stdfix.countlslk_padding_on_unsigned_fixed_point
libc.src.stdfix.countlslr_padding_on_unsigned_fixed_point
libc.src.stdfix.countlsr_padding_on_unsigned_fixed_point
libc.src.stdfix.countlsuhk_padding_on_unsigned_fixed_point
libc.src.stdfix.countlsuhr_padding_on_unsigned_fixed_point
libc.src.stdfix.countlsuk_padding_on_unsigned_fixed_point
libc.src.stdfix.countlsulk_padding_on_unsigned_fixed_point
libc.src.stdfix.countlsulr_padding_on_unsigned_fixed_point
libc.src.stdfix.countlsur_padding_on_unsigned_fixed_point
)
endif()

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
2 changes: 1 addition & 1 deletion libc/docs/math/stdfix.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ The following functions are included in the ISO/IEC TR 18037:2008 standard.
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
| \*bits | | | | | | | | | | | | |
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
| countls | | | | | | | | | | | | |
| countls | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| |
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
| divi | | | | | | | | | | | | |
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
Expand Down
84 changes: 84 additions & 0 deletions libc/newhdrgen/yaml/stdfix.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,90 @@ types: []
enums: []
objects: []
functions:
- name: countlshk
standards:
- stdc_ext
return_type: int
arguments:
- type: short accum
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: countlshr
standards:
- stdc_ext
return_type: int
arguments:
- type: short fract
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: countlsk
standards:
- stdc_ext
return_type: int
arguments:
- type: accum
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: countlslk
standards:
- stdc_ext
return_type: int
arguments:
- type: long accum
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: countlslr
standards:
- stdc_ext
return_type: int
arguments:
- type: long fract
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: countlsr
standards:
- stdc_ext
return_type: int
arguments:
- type: fract
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: countlsuhk
standards:
- stdc_ext
return_type: int
arguments:
- type: unsigned short accum
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: countlsuhr
standards:
- stdc_ext
return_type: int
arguments:
- type: unsigned short fract
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: countlsuk
standards:
- stdc_ext
return_type: int
arguments:
- type: unsigned accum
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: countlsulk
standards:
- stdc_ext
return_type: int
arguments:
- type: unsigned long accum
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: countlsulr
standards:
- stdc_ext
return_type: int
arguments:
- type: unsigned long fract
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: countlsur
standards:
- stdc_ext
return_type: int
arguments:
- type: unsigned fract
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: abshk
standards:
- stdc_ext
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
31 changes: 30 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 @@ -50,6 +51,11 @@ template <typename T> struct FXBits {
static constexpr StorageType SIGN_MASK =
(fx_rep::SIGN_LEN == 0 ? 0 : StorageType(1) << SIGN_OFFSET);

// The integral and fraction bits, but not the sign bit nor the padding bits.
static constexpr StorageType VALUE_MASK = INTEGRAL_MASK | FRACTION_MASK;
// The integral, fraction, and sign bits, but not the padding bits.
static constexpr StorageType TOTAL_MASK = SIGN_MASK | VALUE_MASK;

public:
LIBC_INLINE constexpr FXBits() = default;

Expand All @@ -66,6 +72,12 @@ template <typename T> struct FXBits {
}
}

// Returns the complete bitstring representation of the fixed-point number.
// The bitstring is of the form `padding | sign | integral | fraction`.
LIBC_INLINE constexpr StorageType get_bits() {
return (value & TOTAL_MASK) >> FRACTION_OFFSET;
}

LIBC_INLINE constexpr StorageType get_fraction() {
return (value & FRACTION_MASK) >> FRACTION_OFFSET;
}
Expand Down Expand Up @@ -142,6 +154,23 @@ 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 - get_value_len<FXRep>();

if constexpr (FXRep::SIGN_LEN != 0) {
if (x < 0)
x = bit_not(x);
}

BitType value_bits = FXBits<T>(x).get_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
4 changes: 4 additions & 0 deletions libc/src/__support/fixed_point/fx_rep.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,10 @@ template <> struct FXRep<unsigned sat accum> : FXRep<unsigned accum> {};
template <>
struct FXRep<unsigned long sat accum> : FXRep<unsigned long accum> {};

template <typename FXRep> LIBC_INLINE constexpr int get_value_len() {
return FXRep::INTEGRAL_LEN + FXRep::FRACTION_LEN;
}

} // namespace fixed_point
} // namespace LIBC_NAMESPACE_DECL

Expand Down
28 changes: 28 additions & 0 deletions libc/src/stdfix/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,34 @@ foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
DEPENDS
libc.src.__support.fixed_point.fx_bits
)

add_entrypoint_object(
countls${suffix}
HDRS
countls${suffix}.h
SRCS
countls${suffix}.cpp
COMPILE_OPTIONS
-O3
DEPENDS
libc.src.__support.fixed_point.fx_bits
)

if(LIBC_COMPILER_HAS_PADDING_ON_UNSIGNED_FIXED_POINT)
Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor Author

@duncpro duncpro Nov 7, 2024

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.

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.

add_entrypoint_object(
countls${suffix}_padding_on_unsigned_fixed_point
HDRS
countls${suffix}.h
SRCS
countls${suffix}.cpp
COMPILE_OPTIONS
-O3
-Xclang=-fpadding-on-unsigned-fixed-point
DEPENDS
libc.src.__support.fixed_point.fx_bits
)
endif()

endforeach()

add_entrypoint_object(
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
Loading
Loading