diff --git a/libc/cmake/modules/CheckCompilerFeatures.cmake b/libc/cmake/modules/CheckCompilerFeatures.cmake index d84c07b35d2d7..a6d793d495c45 100644 --- a/libc/cmake/modules/CheckCompilerFeatures.cmake +++ b/libc/cmake/modules/CheckCompilerFeatures.cmake @@ -2,7 +2,15 @@ # Compiler features definition and flags # ------------------------------------------------------------------------------ -set(ALL_COMPILER_FEATURES "float16" "float128" "fixed_point") +set( + ALL_COMPILER_FEATURES + "builtin_ceil_floor_rint_trunc" + "builtin_round" + "builtin_roundeven" + "float16" + "float128" + "fixed_point" +) # Making sure ALL_COMPILER_FEATURES is sorted. list(SORT ALL_COMPILER_FEATURES) @@ -39,11 +47,22 @@ endfunction() set(AVAILABLE_COMPILER_FEATURES "") # Try compile a C file to check if flag is supported. -set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) foreach(feature IN LISTS ALL_COMPILER_FEATURES) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) set(compile_options ${LIBC_COMPILE_OPTIONS_NATIVE}) + set(link_options "") if(${feature} STREQUAL "fixed_point") list(APPEND compile_options "-ffixed-point") + elseif(${feature} MATCHES "^builtin_") + set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT}) + set(link_options -nostdlib) + # The compiler might handle calls to rounding builtins by generating calls + # to the respective libc math functions, in which case we cannot use these + # builtins in our implementations of these functions. We check that this is + # not the case by trying to link an executable, since linking would fail due + # to unresolved references with -nostdlib if calls to libc functions were + # generated. + set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE) endif() try_compile( @@ -51,6 +70,7 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES) ${CMAKE_CURRENT_BINARY_DIR}/compiler_features SOURCES ${LIBC_SOURCE_DIR}/cmake/modules/compiler_features/check_${feature}.cpp COMPILE_DEFINITIONS -I${LIBC_SOURCE_DIR} ${compile_options} + LINK_OPTIONS ${link_options} ) if(has_feature) list(APPEND AVAILABLE_COMPILER_FEATURES ${feature}) @@ -60,6 +80,12 @@ 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 "builtin_ceil_floor_rint_trunc") + set(LIBC_COMPILER_HAS_BUILTIN_CEIL_FLOOR_RINT_TRUNC TRUE) + elseif(${feature} STREQUAL "builtin_round") + set(LIBC_COMPILER_HAS_BUILTIN_ROUND TRUE) + elseif(${feature} STREQUAL "builtin_roundeven") + set(LIBC_COMPILER_HAS_BUILTIN_ROUNDEVEN TRUE) endif() endif() endforeach() diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake index c5e7dfe8abd0f..253da4ae890e5 100644 --- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake +++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake @@ -4,7 +4,7 @@ function(_get_compile_options_from_flags output_var) if(LIBC_TARGET_ARCHITECTURE_IS_RISCV64 OR(LIBC_CPU_FEATURES MATCHES "FMA")) check_flag(ADD_FMA_FLAG ${FMA_OPT_FLAG} ${ARGN}) endif() - check_flag(ADD_SSE4_2_FLAG ${ROUND_OPT_FLAG} ${ARGN}) + check_flag(ADD_ROUND_OPT_FLAG ${ROUND_OPT_FLAG} ${ARGN}) check_flag(ADD_EXPLICIT_SIMD_OPT_FLAG ${EXPLICIT_SIMD_OPT_FLAG} ${ARGN}) if(LLVM_COMPILER_IS_GCC_COMPATIBLE) @@ -16,8 +16,23 @@ function(_get_compile_options_from_flags output_var) list(APPEND compile_options "-D__LIBC_RISCV_USE_FMA") endif() endif() - if(ADD_SSE4_2_FLAG) - list(APPEND compile_options "-msse4.2") + if(ADD_ROUND_OPT_FLAG) + if(LIBC_TARGET_ARCHITECTURE_IS_X86) + # ROUND_OPT_FLAG is only enabled if SSE4.2 is detected, not just SSE4.1, + # because there was code to check for SSE4.2 already, and few CPUs only + # have SSE4.1. + list(APPEND compile_options "-msse4.2") + endif() + if(LIBC_COMPILER_HAS_BUILTIN_CEIL_FLOOR_RINT_TRUNC) + list(APPEND compile_options + "-D__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC") + endif() + if(LIBC_COMPILER_HAS_BUILTIN_ROUND) + list(APPEND compile_options "-D__LIBC_USE_BUILTIN_ROUND") + endif() + if(LIBC_COMPILER_HAS_BUILTIN_ROUNDEVEN) + list(APPEND compile_options "-D__LIBC_USE_BUILTIN_ROUNDEVEN") + endif() endif() if(ADD_EXPLICIT_SIMD_OPT_FLAG) list(APPEND compile_options "-D__LIBC_EXPLICIT_SIMD_OPT") diff --git a/libc/cmake/modules/LLVMLibCFlagRules.cmake b/libc/cmake/modules/LLVMLibCFlagRules.cmake index 18e36dfde5cc1..eca7ba8d183e6 100644 --- a/libc/cmake/modules/LLVMLibCFlagRules.cmake +++ b/libc/cmake/modules/LLVMLibCFlagRules.cmake @@ -277,6 +277,7 @@ if(NOT(LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "SSE2"))) endif() # Skip ROUND_OPT flag for targets that don't support SSE 4.2. -if(NOT(LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "SSE4_2"))) +if(NOT((LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "SSE4_2")) OR + LIBC_TARGET_ARCHITECTURE_IS_AARCH64)) set(SKIP_FLAG_EXPANSION_ROUND_OPT TRUE) endif() diff --git a/libc/cmake/modules/compiler_features/check_builtin_ceil_floor_rint_trunc.cpp b/libc/cmake/modules/compiler_features/check_builtin_ceil_floor_rint_trunc.cpp new file mode 100644 index 0000000000000..946200001d69f --- /dev/null +++ b/libc/cmake/modules/compiler_features/check_builtin_ceil_floor_rint_trunc.cpp @@ -0,0 +1,11 @@ +float try_builtin_ceilf(float x) { return __builtin_ceilf(x); } +float try_builtin_floorf(float x) { return __builtin_floorf(x); } +float try_builtin_rintf(float x) { return __builtin_rintf(x); } +float try_builtin_truncf(float x) { return __builtin_truncf(x); } + +double try_builtin_ceil(double x) { return __builtin_ceil(x); } +double try_builtin_floor(double x) { return __builtin_floor(x); } +double try_builtin_rint(double x) { return __builtin_rint(x); } +double try_builtin_trunc(double x) { return __builtin_trunc(x); } + +extern "C" void _start() {} diff --git a/libc/cmake/modules/compiler_features/check_builtin_round.cpp b/libc/cmake/modules/compiler_features/check_builtin_round.cpp new file mode 100644 index 0000000000000..79a347ada8b60 --- /dev/null +++ b/libc/cmake/modules/compiler_features/check_builtin_round.cpp @@ -0,0 +1,5 @@ +float try_builtin_roundf(float x) { return __builtin_roundf(x); } + +double try_builtin_round(double x) { return __builtin_round(x); } + +extern "C" void _start() {} diff --git a/libc/cmake/modules/compiler_features/check_builtin_roundeven.cpp b/libc/cmake/modules/compiler_features/check_builtin_roundeven.cpp new file mode 100644 index 0000000000000..0aa40dc7f4b7a --- /dev/null +++ b/libc/cmake/modules/compiler_features/check_builtin_roundeven.cpp @@ -0,0 +1,5 @@ +float try_builtin_roundevenf(float x) { return __builtin_roundevenf(x); } + +double try_builtin_roundeven(double x) { return __builtin_roundeven(x); } + +extern "C" void _start() {} diff --git a/libc/src/math/aarch64/CMakeLists.txt b/libc/src/math/aarch64/CMakeLists.txt deleted file mode 100644 index bbe927a1c7c88..0000000000000 --- a/libc/src/math/aarch64/CMakeLists.txt +++ /dev/null @@ -1,79 +0,0 @@ -add_entrypoint_object( - ceil - SRCS - ceil.cpp - HDRS - ../ceil.h - COMPILE_OPTIONS - -O2 -) - -add_entrypoint_object( - ceilf - SRCS - ceilf.cpp - HDRS - ../ceilf.h - COMPILE_OPTIONS - -O2 -) - -add_entrypoint_object( - floor - SRCS - floor.cpp - HDRS - ../floor.h - COMPILE_OPTIONS - -O2 -) - -add_entrypoint_object( - floorf - SRCS - floorf.cpp - HDRS - ../floorf.h - COMPILE_OPTIONS - -O2 -) - -add_entrypoint_object( - trunc - SRCS - trunc.cpp - HDRS - ../trunc.h - COMPILE_OPTIONS - -O2 -) - -add_entrypoint_object( - truncf - SRCS - truncf.cpp - HDRS - ../truncf.h - COMPILE_OPTIONS - -O2 -) - -add_entrypoint_object( - round - SRCS - round.cpp - HDRS - ../round.h - COMPILE_OPTIONS - -O2 -) - -add_entrypoint_object( - roundf - SRCS - roundf.cpp - HDRS - ../roundf.h - COMPILE_OPTIONS - -O2 -) diff --git a/libc/src/math/aarch64/ceil.cpp b/libc/src/math/aarch64/ceil.cpp deleted file mode 100644 index 5bfd053d603de..0000000000000 --- a/libc/src/math/aarch64/ceil.cpp +++ /dev/null @@ -1,21 +0,0 @@ -//===-- Implementation of the ceil function for aarch64 -------------------===// -// -// 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 "src/math/ceil.h" -#include "src/__support/common.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -LLVM_LIBC_FUNCTION(double, ceil, (double x)) { - double y; - __asm__ __volatile__("frintp %d0, %d1\n\t" : "=w"(y) : "w"(x)); - return y; -} - -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/aarch64/ceilf.cpp b/libc/src/math/aarch64/ceilf.cpp deleted file mode 100644 index 2352245bc8303..0000000000000 --- a/libc/src/math/aarch64/ceilf.cpp +++ /dev/null @@ -1,21 +0,0 @@ -//===-- Implementation of the ceilf function for aarch64 ------------------===// -// -// 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 "src/math/ceilf.h" -#include "src/__support/common.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -LLVM_LIBC_FUNCTION(float, ceilf, (float x)) { - float y; - __asm__ __volatile__("frintp %s0, %s1\n\t" : "=w"(y) : "w"(x)); - return y; -} - -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/aarch64/floor.cpp b/libc/src/math/aarch64/floor.cpp deleted file mode 100644 index f9da52bdd45a8..0000000000000 --- a/libc/src/math/aarch64/floor.cpp +++ /dev/null @@ -1,21 +0,0 @@ -//===-- Implementation of the floor function for aarch64 ------------------===// -// -// 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 "src/math/floor.h" -#include "src/__support/common.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -LLVM_LIBC_FUNCTION(double, floor, (double x)) { - double y; - __asm__ __volatile__("frintm %d0, %d1\n\t" : "=w"(y) : "w"(x)); - return y; -} - -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/aarch64/floorf.cpp b/libc/src/math/aarch64/floorf.cpp deleted file mode 100644 index 980b3c52a00b5..0000000000000 --- a/libc/src/math/aarch64/floorf.cpp +++ /dev/null @@ -1,21 +0,0 @@ -//===-- Implementation of the floorf function for aarch64 -----------------===// -// -// 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 "src/math/floorf.h" -#include "src/__support/common.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -LLVM_LIBC_FUNCTION(float, floorf, (float x)) { - float y; - __asm__ __volatile__("frintm %s0, %s1\n\t" : "=w"(y) : "w"(x)); - return y; -} - -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/aarch64/round.cpp b/libc/src/math/aarch64/round.cpp deleted file mode 100644 index c85445aa19ab5..0000000000000 --- a/libc/src/math/aarch64/round.cpp +++ /dev/null @@ -1,21 +0,0 @@ -//===-- Implementation of the round function for aarch64 ------------------===// -// -// 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 "src/math/round.h" -#include "src/__support/common.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -LLVM_LIBC_FUNCTION(double, round, (double x)) { - double y; - __asm__ __volatile__("frinta %d0, %d1\n\t" : "=w"(y) : "w"(x)); - return y; -} - -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/aarch64/roundf.cpp b/libc/src/math/aarch64/roundf.cpp deleted file mode 100644 index 0c7f7640e8278..0000000000000 --- a/libc/src/math/aarch64/roundf.cpp +++ /dev/null @@ -1,21 +0,0 @@ -//===-- Implementation of the roundf function for aarch64 -----------------===// -// -// 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 "src/math/roundf.h" -#include "src/__support/common.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -LLVM_LIBC_FUNCTION(float, roundf, (float x)) { - float y; - __asm__ __volatile__("frinta %s0, %s1\n\t" : "=w"(y) : "w"(x)); - return y; -} - -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/aarch64/trunc.cpp b/libc/src/math/aarch64/trunc.cpp deleted file mode 100644 index 1ef26f44fd234..0000000000000 --- a/libc/src/math/aarch64/trunc.cpp +++ /dev/null @@ -1,21 +0,0 @@ -//===-- Implementation of the trunc function for aarch64 ------------------===// -// -// 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 "src/math/trunc.h" -#include "src/__support/common.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -LLVM_LIBC_FUNCTION(double, trunc, (double x)) { - double y; - __asm__ __volatile__("frintz %d0, %d1\n" : "=w"(y) : "w"(x)); - return y; -} - -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/aarch64/truncf.cpp b/libc/src/math/aarch64/truncf.cpp deleted file mode 100644 index 0c64ef60e91c4..0000000000000 --- a/libc/src/math/aarch64/truncf.cpp +++ /dev/null @@ -1,21 +0,0 @@ -//===-- Implementation of the truncf function for aarch64 -----------------===// -// -// 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 "src/math/truncf.h" -#include "src/__support/common.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -LLVM_LIBC_FUNCTION(float, truncf, (float x)) { - float y; - __asm__ __volatile__("frintz %s0, %s1\n\t" : "=w"(y) : "w"(x)); - return y; -} - -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 5e920307d39de..c2f58fb1a4f71 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -70,6 +70,8 @@ add_entrypoint_object( -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -82,6 +84,8 @@ add_entrypoint_object( -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -107,6 +111,9 @@ add_entrypoint_object( DEPENDS libc.src.__support.macros.properties.types libc.src.__support.FPUtil.nearest_integer_operations + libc.src.__support.macros.properties.architectures + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -455,6 +462,8 @@ add_entrypoint_object( -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -467,6 +476,8 @@ add_entrypoint_object( -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -492,6 +503,9 @@ add_entrypoint_object( DEPENDS libc.src.__support.macros.properties.types libc.src.__support.FPUtil.nearest_integer_operations + libc.src.__support.macros.properties.architectures + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -517,6 +531,8 @@ add_entrypoint_object( -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -529,6 +545,8 @@ add_entrypoint_object( -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -554,6 +572,9 @@ add_entrypoint_object( DEPENDS libc.src.__support.macros.properties.types libc.src.__support.FPUtil.nearest_integer_operations + libc.src.__support.macros.properties.architectures + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -579,6 +600,8 @@ add_entrypoint_object( -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -591,6 +614,8 @@ add_entrypoint_object( -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -616,6 +641,9 @@ add_entrypoint_object( DEPENDS libc.src.__support.macros.properties.types libc.src.__support.FPUtil.nearest_integer_operations + libc.src.__support.macros.properties.architectures + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -641,6 +669,8 @@ add_entrypoint_object( -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -653,6 +683,8 @@ add_entrypoint_object( -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -678,6 +710,9 @@ add_entrypoint_object( DEPENDS libc.src.__support.macros.properties.types libc.src.__support.FPUtil.nearest_integer_operations + libc.src.__support.macros.properties.architectures + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -827,6 +862,8 @@ add_entrypoint_object( -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -839,6 +876,8 @@ add_entrypoint_object( -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations + FLAGS + ROUND_OPT ) add_entrypoint_object( @@ -864,6 +903,9 @@ add_entrypoint_object( DEPENDS libc.src.__support.macros.properties.types libc.src.__support.FPUtil.nearest_integer_operations + libc.src.__support.macros.properties.architectures + FLAGS + ROUND_OPT ) add_entrypoint_object( diff --git a/libc/src/math/generic/ceil.cpp b/libc/src/math/generic/ceil.cpp index a5ac1348834d8..72c6e990fcc71 100644 --- a/libc/src/math/generic/ceil.cpp +++ b/libc/src/math/generic/ceil.cpp @@ -13,6 +13,12 @@ namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(double, ceil, (double x)) { return fputil::ceil(x); } +LLVM_LIBC_FUNCTION(double, ceil, (double x)) { +#ifdef __LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC + return __builtin_ceil(x); +#else + return fputil::ceil(x); +#endif +} } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/ceilf.cpp b/libc/src/math/generic/ceilf.cpp index 0fd54361648dc..dfd0dc62bc51b 100644 --- a/libc/src/math/generic/ceilf.cpp +++ b/libc/src/math/generic/ceilf.cpp @@ -13,6 +13,12 @@ namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(float, ceilf, (float x)) { return fputil::ceil(x); } +LLVM_LIBC_FUNCTION(float, ceilf, (float x)) { +#ifdef __LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC + return __builtin_ceilf(x); +#else + return fputil::ceil(x); +#endif +} } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/ceilf16.cpp b/libc/src/math/generic/ceilf16.cpp index 1d17daf283d07..708bc4cfd4860 100644 --- a/libc/src/math/generic/ceilf16.cpp +++ b/libc/src/math/generic/ceilf16.cpp @@ -10,9 +10,17 @@ #include "src/__support/FPUtil/NearestIntegerOperations.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" +#include "src/__support/macros/properties/architectures.h" namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(float16, ceilf16, (float16 x)) { return fputil::ceil(x); } +LLVM_LIBC_FUNCTION(float16, ceilf16, (float16 x)) { +#if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) && \ + defined(LIBC_TARGET_ARCH_IS_AARCH64) + return static_cast(__builtin_ceilf(x)); +#else + return fputil::ceil(x); +#endif +} } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/floor.cpp b/libc/src/math/generic/floor.cpp index 417d6aca3ffe5..86aed6c61a7cc 100644 --- a/libc/src/math/generic/floor.cpp +++ b/libc/src/math/generic/floor.cpp @@ -13,6 +13,12 @@ namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(double, floor, (double x)) { return fputil::floor(x); } +LLVM_LIBC_FUNCTION(double, floor, (double x)) { +#ifdef __LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC + return __builtin_floor(x); +#else + return fputil::floor(x); +#endif +} } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/floorf.cpp b/libc/src/math/generic/floorf.cpp index ca059e6d02d53..22739eff68ec2 100644 --- a/libc/src/math/generic/floorf.cpp +++ b/libc/src/math/generic/floorf.cpp @@ -13,6 +13,12 @@ namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(float, floorf, (float x)) { return fputil::floor(x); } +LLVM_LIBC_FUNCTION(float, floorf, (float x)) { +#ifdef __LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC + return __builtin_floorf(x); +#else + return fputil::floor(x); +#endif +} } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/floorf16.cpp b/libc/src/math/generic/floorf16.cpp index 46068c2a548a9..84e4b0730ac68 100644 --- a/libc/src/math/generic/floorf16.cpp +++ b/libc/src/math/generic/floorf16.cpp @@ -10,9 +10,17 @@ #include "src/__support/FPUtil/NearestIntegerOperations.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" +#include "src/__support/macros/properties/architectures.h" namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(float16, floorf16, (float16 x)) { return fputil::floor(x); } +LLVM_LIBC_FUNCTION(float16, floorf16, (float16 x)) { +#if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) && \ + defined(LIBC_TARGET_ARCH_IS_AARCH64) + return static_cast(__builtin_floorf(x)); +#else + return fputil::floor(x); +#endif +} } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/rint.cpp b/libc/src/math/generic/rint.cpp index f7837df133484..5defa60ddac1c 100644 --- a/libc/src/math/generic/rint.cpp +++ b/libc/src/math/generic/rint.cpp @@ -14,7 +14,11 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(double, rint, (double x)) { +#ifdef __LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC + return __builtin_rint(x); +#else return fputil::round_using_current_rounding_mode(x); +#endif } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/rintf.cpp b/libc/src/math/generic/rintf.cpp index 29a2845cc85d4..2fe7788241168 100644 --- a/libc/src/math/generic/rintf.cpp +++ b/libc/src/math/generic/rintf.cpp @@ -14,7 +14,11 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(float, rintf, (float x)) { +#ifdef __LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC + return __builtin_rintf(x); +#else return fputil::round_using_current_rounding_mode(x); +#endif } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/rintf16.cpp b/libc/src/math/generic/rintf16.cpp index 69b89de31bf40..0e8c091efcf9b 100644 --- a/libc/src/math/generic/rintf16.cpp +++ b/libc/src/math/generic/rintf16.cpp @@ -10,11 +10,17 @@ #include "src/__support/FPUtil/NearestIntegerOperations.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" +#include "src/__support/macros/properties/architectures.h" namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(float16, rintf16, (float16 x)) { +#if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) && \ + defined(LIBC_TARGET_ARCH_IS_AARCH64) + return static_cast(__builtin_rintf(x)); +#else return fputil::round_using_current_rounding_mode(x); +#endif } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/round.cpp b/libc/src/math/generic/round.cpp index d8b171a2ef092..6ed5be5065962 100644 --- a/libc/src/math/generic/round.cpp +++ b/libc/src/math/generic/round.cpp @@ -13,6 +13,12 @@ namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(double, round, (double x)) { return fputil::round(x); } +LLVM_LIBC_FUNCTION(double, round, (double x)) { +#ifdef __LIBC_USE_BUILTIN_ROUND + return __builtin_round(x); +#else + return fputil::round(x); +#endif +} } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/roundeven.cpp b/libc/src/math/generic/roundeven.cpp index e6f599991bc0f..42f19f38b5385 100644 --- a/libc/src/math/generic/roundeven.cpp +++ b/libc/src/math/generic/roundeven.cpp @@ -14,7 +14,11 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(double, roundeven, (double x)) { +#ifdef __LIBC_USE_BUILTIN_ROUNDEVEN + return __builtin_roundeven(x); +#else return fputil::round_using_specific_rounding_mode(x, FP_INT_TONEAREST); +#endif } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/roundevenf.cpp b/libc/src/math/generic/roundevenf.cpp index 0b63a093edf6c..98bdc6545d94e 100644 --- a/libc/src/math/generic/roundevenf.cpp +++ b/libc/src/math/generic/roundevenf.cpp @@ -14,7 +14,11 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(float, roundevenf, (float x)) { +#ifdef __LIBC_USE_BUILTIN_ROUNDEVEN + return __builtin_roundevenf(x); +#else return fputil::round_using_specific_rounding_mode(x, FP_INT_TONEAREST); +#endif } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/roundevenf16.cpp b/libc/src/math/generic/roundevenf16.cpp index 8a27d81b895ae..b45670bd24ff1 100644 --- a/libc/src/math/generic/roundevenf16.cpp +++ b/libc/src/math/generic/roundevenf16.cpp @@ -10,11 +10,17 @@ #include "src/__support/FPUtil/NearestIntegerOperations.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" +#include "src/__support/macros/properties/architectures.h" namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(float16, roundevenf16, (float16 x)) { +#if defined(__LIBC_USE_BUILTIN_ROUNDEVEN) && \ + defined(LIBC_TARGET_ARCH_IS_AARCH64) + return static_cast(__builtin_roundevenf(x)); +#else return fputil::round_using_specific_rounding_mode(x, FP_INT_TONEAREST); +#endif } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/roundf.cpp b/libc/src/math/generic/roundf.cpp index 68be4b1a51987..d25f7128cb9ce 100644 --- a/libc/src/math/generic/roundf.cpp +++ b/libc/src/math/generic/roundf.cpp @@ -13,6 +13,12 @@ namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(float, roundf, (float x)) { return fputil::round(x); } +LLVM_LIBC_FUNCTION(float, roundf, (float x)) { +#ifdef __LIBC_USE_BUILTIN_ROUND + return __builtin_roundf(x); +#else + return fputil::round(x); +#endif +} } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/roundf16.cpp b/libc/src/math/generic/roundf16.cpp index 06f9a79cc21f3..cb668c0e76388 100644 --- a/libc/src/math/generic/roundf16.cpp +++ b/libc/src/math/generic/roundf16.cpp @@ -10,9 +10,16 @@ #include "src/__support/FPUtil/NearestIntegerOperations.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" +#include "src/__support/macros/properties/architectures.h" namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(float16, roundf16, (float16 x)) { return fputil::round(x); } +LLVM_LIBC_FUNCTION(float16, roundf16, (float16 x)) { +#if defined(__LIBC_USE_BUILTIN_ROUND) && defined(LIBC_TARGET_ARCH_IS_AARCH64) + return static_cast(__builtin_roundf(x)); +#else + return fputil::round(x); +#endif +} } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/trunc.cpp b/libc/src/math/generic/trunc.cpp index 0bf2ac5962e7b..603750f11c9f6 100644 --- a/libc/src/math/generic/trunc.cpp +++ b/libc/src/math/generic/trunc.cpp @@ -13,6 +13,12 @@ namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(double, trunc, (double x)) { return fputil::trunc(x); } +LLVM_LIBC_FUNCTION(double, trunc, (double x)) { +#ifdef __LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC + return __builtin_trunc(x); +#else + return fputil::trunc(x); +#endif +} } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/truncf.cpp b/libc/src/math/generic/truncf.cpp index 371cb9f8229a6..d7b0ffd96da9c 100644 --- a/libc/src/math/generic/truncf.cpp +++ b/libc/src/math/generic/truncf.cpp @@ -13,6 +13,12 @@ namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(float, truncf, (float x)) { return fputil::trunc(x); } +LLVM_LIBC_FUNCTION(float, truncf, (float x)) { +#ifdef __LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC + return __builtin_truncf(x); +#else + return fputil::trunc(x); +#endif +} } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/truncf16.cpp b/libc/src/math/generic/truncf16.cpp index ea7695dc95f0b..b931053e53438 100644 --- a/libc/src/math/generic/truncf16.cpp +++ b/libc/src/math/generic/truncf16.cpp @@ -10,9 +10,17 @@ #include "src/__support/FPUtil/NearestIntegerOperations.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" +#include "src/__support/macros/properties/architectures.h" namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(float16, truncf16, (float16 x)) { return fputil::trunc(x); } +LLVM_LIBC_FUNCTION(float16, truncf16, (float16 x)) { +#if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) && \ + defined(LIBC_TARGET_ARCH_IS_AARCH64) + return static_cast(__builtin_truncf(x)); +#else + return fputil::trunc(x); +#endif +} } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/src/math/performance_testing/CMakeLists.txt b/libc/test/src/math/performance_testing/CMakeLists.txt index c7241317687e0..a75becba04d07 100644 --- a/libc/test/src/math/performance_testing/CMakeLists.txt +++ b/libc/test/src/math/performance_testing/CMakeLists.txt @@ -21,7 +21,7 @@ function(add_perf_binary target_name) "PERF" "" # No optional arguments "SUITE;CXX_STANDARD" # Single value arguments - "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS" # Multi-value arguments + "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS;LINK_LIBRARIES" # Multi-value arguments ${ARGN} ) if(NOT PERF_SRCS) @@ -64,9 +64,13 @@ function(add_perf_binary target_name) ) endif() + set(link_libraries ${link_object_files}) + foreach(lib IN LISTS PERF_LINK_LIBRARIES) + list(APPEND link_libraries ${lib}.unit) + endforeach() target_link_libraries( ${fq_target_name} - PRIVATE ${link_object_files} libc_diff_test_utils) + PRIVATE ${link_libraries} libc_diff_test_utils) set_target_properties(${fq_target_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) @@ -385,12 +389,16 @@ add_perf_binary( libc.src.math.ceilf16 libc.src.math.floorf libc.src.math.floorf16 - libc.src.math.roundevenf - libc.src.math.roundevenf16 + libc.src.math.rintf + libc.src.math.rintf16 libc.src.math.roundf libc.src.math.roundf16 + libc.src.math.roundevenf + libc.src.math.roundevenf16 libc.src.math.truncf libc.src.math.truncf16 COMPILE_OPTIONS -fno-builtin + LINK_LIBRARIES + LibcFPTestHelpers ) diff --git a/libc/test/src/math/performance_testing/nearest_integer_funcs_perf.cpp b/libc/test/src/math/performance_testing/nearest_integer_funcs_perf.cpp index 24176a377e9d4..b7bd6636a72e1 100644 --- a/libc/test/src/math/performance_testing/nearest_integer_funcs_perf.cpp +++ b/libc/test/src/math/performance_testing/nearest_integer_funcs_perf.cpp @@ -11,17 +11,23 @@ #include "src/math/ceilf16.h" #include "src/math/floorf.h" #include "src/math/floorf16.h" +#include "src/math/rintf.h" +#include "src/math/rintf16.h" #include "src/math/roundevenf.h" #include "src/math/roundevenf16.h" #include "src/math/roundf.h" #include "src/math/roundf16.h" #include "src/math/truncf.h" #include "src/math/truncf16.h" +#include "test/UnitTest/RoundingModeUtils.h" #include "test/src/math/performance_testing/Timer.h" #include #include +using LIBC_NAMESPACE::fputil::testing::ForceRoundingMode; +using LIBC_NAMESPACE::fputil::testing::RoundingMode; + namespace LIBC_NAMESPACE::testing { template class NearestIntegerPerf { @@ -36,7 +42,7 @@ template class NearestIntegerPerf { StorageType ending_bit, StorageType step, size_t rounds, std::ofstream &log) { auto runner = [=](Func func) { - volatile T result; + [[maybe_unused]] volatile T result; for (size_t i = 0; i < rounds; i++) { for (StorageType bits = starting_bit; bits <= ending_bit; bits += step) { @@ -146,10 +152,10 @@ int main() { FLOAT16_ROUNDS, "ceilf16_perf.log") NEAREST_INTEGER_PERF(float16, LIBC_NAMESPACE::floorf16, ::placeholderf16, FLOAT16_ROUNDS, "floorf16_perf.log") - NEAREST_INTEGER_PERF(float16, LIBC_NAMESPACE::roundevenf16, ::placeholderf16, - FLOAT16_ROUNDS, "roundevenf16_perf.log") NEAREST_INTEGER_PERF(float16, LIBC_NAMESPACE::roundf16, ::placeholderf16, FLOAT16_ROUNDS, "roundf16_perf.log") + NEAREST_INTEGER_PERF(float16, LIBC_NAMESPACE::roundevenf16, ::placeholderf16, + FLOAT16_ROUNDS, "roundevenf16_perf.log") NEAREST_INTEGER_PERF(float16, LIBC_NAMESPACE::truncf16, ::placeholderf16, FLOAT16_ROUNDS, "truncf16_perf.log") @@ -157,12 +163,37 @@ int main() { "ceilf_perf.log") NEAREST_INTEGER_PERF(float, LIBC_NAMESPACE::floorf, ::floorf, FLOAT_ROUNDS, "floorf_perf.log") - NEAREST_INTEGER_PERF(float, LIBC_NAMESPACE::roundevenf, ::placeholderf, - FLOAT_ROUNDS, "roundevenf_perf.log") NEAREST_INTEGER_PERF(float, LIBC_NAMESPACE::roundf, ::roundf, FLOAT_ROUNDS, "roundf_perf.log") + NEAREST_INTEGER_PERF(float, LIBC_NAMESPACE::roundevenf, ::placeholderf, + FLOAT_ROUNDS, "roundevenf_perf.log") NEAREST_INTEGER_PERF(float, LIBC_NAMESPACE::truncf, ::truncf, FLOAT_ROUNDS, "truncf_perf.log") + if (ForceRoundingMode r(RoundingMode::Upward); r.success) { + NEAREST_INTEGER_PERF(float16, LIBC_NAMESPACE::rintf16, ::placeholderf16, + FLOAT16_ROUNDS, "rintf16_upward_perf.log") + NEAREST_INTEGER_PERF(float, LIBC_NAMESPACE::rintf, ::rintf, FLOAT_ROUNDS, + "rintf_upward_perf.log") + } + if (ForceRoundingMode r(RoundingMode::Downward); r.success) { + NEAREST_INTEGER_PERF(float16, LIBC_NAMESPACE::rintf16, ::placeholderf16, + FLOAT16_ROUNDS, "rintf16_downward_perf.log") + NEAREST_INTEGER_PERF(float, LIBC_NAMESPACE::rintf, ::rintf, FLOAT_ROUNDS, + "rintf_downward_perf.log") + } + if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) { + NEAREST_INTEGER_PERF(float16, LIBC_NAMESPACE::rintf16, ::placeholderf16, + FLOAT16_ROUNDS, "rintf16_towardzero_perf.log") + NEAREST_INTEGER_PERF(float, LIBC_NAMESPACE::rintf, ::rintf, FLOAT_ROUNDS, + "rintf_towardzero_perf.log") + } + if (ForceRoundingMode r(RoundingMode::Nearest); r.success) { + NEAREST_INTEGER_PERF(float16, LIBC_NAMESPACE::rintf16, ::placeholderf16, + FLOAT16_ROUNDS, "rintf16_nearest_perf.log") + NEAREST_INTEGER_PERF(float, LIBC_NAMESPACE::rintf, ::rintf, FLOAT_ROUNDS, + "rintf_nearest_perf.log") + } + return 0; }