Skip to content

Commit 4531f82

Browse files
authored
[libc][math] Optimize nearest integer functions using builtins when available (#98376)
1 parent c6b3f50 commit 4531f82

36 files changed

+278
-274
lines changed

libc/cmake/modules/CheckCompilerFeatures.cmake

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,15 @@
22
# Compiler features definition and flags
33
# ------------------------------------------------------------------------------
44

5-
set(ALL_COMPILER_FEATURES "float16" "float128" "fixed_point")
5+
set(
6+
ALL_COMPILER_FEATURES
7+
"builtin_ceil_floor_rint_trunc"
8+
"builtin_round"
9+
"builtin_roundeven"
10+
"float16"
11+
"float128"
12+
"fixed_point"
13+
)
614

715
# Making sure ALL_COMPILER_FEATURES is sorted.
816
list(SORT ALL_COMPILER_FEATURES)
@@ -39,18 +47,30 @@ endfunction()
3947
set(AVAILABLE_COMPILER_FEATURES "")
4048

4149
# Try compile a C file to check if flag is supported.
42-
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
4350
foreach(feature IN LISTS ALL_COMPILER_FEATURES)
51+
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
4452
set(compile_options ${LIBC_COMPILE_OPTIONS_NATIVE})
53+
set(link_options "")
4554
if(${feature} STREQUAL "fixed_point")
4655
list(APPEND compile_options "-ffixed-point")
56+
elseif(${feature} MATCHES "^builtin_")
57+
set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT})
58+
set(link_options -nostdlib)
59+
# The compiler might handle calls to rounding builtins by generating calls
60+
# to the respective libc math functions, in which case we cannot use these
61+
# builtins in our implementations of these functions. We check that this is
62+
# not the case by trying to link an executable, since linking would fail due
63+
# to unresolved references with -nostdlib if calls to libc functions were
64+
# generated.
65+
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
4766
endif()
4867

4968
try_compile(
5069
has_feature
5170
${CMAKE_CURRENT_BINARY_DIR}/compiler_features
5271
SOURCES ${LIBC_SOURCE_DIR}/cmake/modules/compiler_features/check_${feature}.cpp
5372
COMPILE_DEFINITIONS -I${LIBC_SOURCE_DIR} ${compile_options}
73+
LINK_OPTIONS ${link_options}
5474
)
5575
if(has_feature)
5676
list(APPEND AVAILABLE_COMPILER_FEATURES ${feature})
@@ -60,6 +80,12 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
6080
set(LIBC_TYPES_HAS_FLOAT128 TRUE)
6181
elseif(${feature} STREQUAL "fixed_point")
6282
set(LIBC_COMPILER_HAS_FIXED_POINT TRUE)
83+
elseif(${feature} STREQUAL "builtin_ceil_floor_rint_trunc")
84+
set(LIBC_COMPILER_HAS_BUILTIN_CEIL_FLOOR_RINT_TRUNC TRUE)
85+
elseif(${feature} STREQUAL "builtin_round")
86+
set(LIBC_COMPILER_HAS_BUILTIN_ROUND TRUE)
87+
elseif(${feature} STREQUAL "builtin_roundeven")
88+
set(LIBC_COMPILER_HAS_BUILTIN_ROUNDEVEN TRUE)
6389
endif()
6490
endif()
6591
endforeach()

libc/cmake/modules/LLVMLibCCompileOptionRules.cmake

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ function(_get_compile_options_from_flags output_var)
44
if(LIBC_TARGET_ARCHITECTURE_IS_RISCV64 OR(LIBC_CPU_FEATURES MATCHES "FMA"))
55
check_flag(ADD_FMA_FLAG ${FMA_OPT_FLAG} ${ARGN})
66
endif()
7-
check_flag(ADD_SSE4_2_FLAG ${ROUND_OPT_FLAG} ${ARGN})
7+
check_flag(ADD_ROUND_OPT_FLAG ${ROUND_OPT_FLAG} ${ARGN})
88
check_flag(ADD_EXPLICIT_SIMD_OPT_FLAG ${EXPLICIT_SIMD_OPT_FLAG} ${ARGN})
99

1010
if(LLVM_COMPILER_IS_GCC_COMPATIBLE)
@@ -16,8 +16,23 @@ function(_get_compile_options_from_flags output_var)
1616
list(APPEND compile_options "-D__LIBC_RISCV_USE_FMA")
1717
endif()
1818
endif()
19-
if(ADD_SSE4_2_FLAG)
20-
list(APPEND compile_options "-msse4.2")
19+
if(ADD_ROUND_OPT_FLAG)
20+
if(LIBC_TARGET_ARCHITECTURE_IS_X86)
21+
# ROUND_OPT_FLAG is only enabled if SSE4.2 is detected, not just SSE4.1,
22+
# because there was code to check for SSE4.2 already, and few CPUs only
23+
# have SSE4.1.
24+
list(APPEND compile_options "-msse4.2")
25+
endif()
26+
if(LIBC_COMPILER_HAS_BUILTIN_CEIL_FLOOR_RINT_TRUNC)
27+
list(APPEND compile_options
28+
"-D__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC")
29+
endif()
30+
if(LIBC_COMPILER_HAS_BUILTIN_ROUND)
31+
list(APPEND compile_options "-D__LIBC_USE_BUILTIN_ROUND")
32+
endif()
33+
if(LIBC_COMPILER_HAS_BUILTIN_ROUNDEVEN)
34+
list(APPEND compile_options "-D__LIBC_USE_BUILTIN_ROUNDEVEN")
35+
endif()
2136
endif()
2237
if(ADD_EXPLICIT_SIMD_OPT_FLAG)
2338
list(APPEND compile_options "-D__LIBC_EXPLICIT_SIMD_OPT")

libc/cmake/modules/LLVMLibCFlagRules.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ if(NOT(LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "SSE2")))
277277
endif()
278278

279279
# Skip ROUND_OPT flag for targets that don't support SSE 4.2.
280-
if(NOT(LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "SSE4_2")))
280+
if(NOT((LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "SSE4_2")) OR
281+
LIBC_TARGET_ARCHITECTURE_IS_AARCH64))
281282
set(SKIP_FLAG_EXPANSION_ROUND_OPT TRUE)
282283
endif()
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
float try_builtin_ceilf(float x) { return __builtin_ceilf(x); }
2+
float try_builtin_floorf(float x) { return __builtin_floorf(x); }
3+
float try_builtin_rintf(float x) { return __builtin_rintf(x); }
4+
float try_builtin_truncf(float x) { return __builtin_truncf(x); }
5+
6+
double try_builtin_ceil(double x) { return __builtin_ceil(x); }
7+
double try_builtin_floor(double x) { return __builtin_floor(x); }
8+
double try_builtin_rint(double x) { return __builtin_rint(x); }
9+
double try_builtin_trunc(double x) { return __builtin_trunc(x); }
10+
11+
extern "C" void _start() {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
float try_builtin_roundf(float x) { return __builtin_roundf(x); }
2+
3+
double try_builtin_round(double x) { return __builtin_round(x); }
4+
5+
extern "C" void _start() {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
float try_builtin_roundevenf(float x) { return __builtin_roundevenf(x); }
2+
3+
double try_builtin_roundeven(double x) { return __builtin_roundeven(x); }
4+
5+
extern "C" void _start() {}

libc/src/math/aarch64/CMakeLists.txt

Lines changed: 0 additions & 79 deletions
This file was deleted.

libc/src/math/aarch64/ceil.cpp

Lines changed: 0 additions & 21 deletions
This file was deleted.

libc/src/math/aarch64/ceilf.cpp

Lines changed: 0 additions & 21 deletions
This file was deleted.

libc/src/math/aarch64/floor.cpp

Lines changed: 0 additions & 21 deletions
This file was deleted.

libc/src/math/aarch64/floorf.cpp

Lines changed: 0 additions & 21 deletions
This file was deleted.

libc/src/math/aarch64/round.cpp

Lines changed: 0 additions & 21 deletions
This file was deleted.

libc/src/math/aarch64/roundf.cpp

Lines changed: 0 additions & 21 deletions
This file was deleted.

libc/src/math/aarch64/trunc.cpp

Lines changed: 0 additions & 21 deletions
This file was deleted.

libc/src/math/aarch64/truncf.cpp

Lines changed: 0 additions & 21 deletions
This file was deleted.

0 commit comments

Comments
 (0)