Skip to content

Commit 50f1237

Browse files
committed
[libc][math] Optimize nearest integer functions using builtins when available
1 parent 22a7f6d commit 50f1237

22 files changed

+202
-18
lines changed

libc/cmake/modules/CheckCompilerFeatures.cmake

Lines changed: 24 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_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,11 +47,19 @@ 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})
4553
if(${feature} STREQUAL "fixed_point")
4654
list(APPEND compile_options "-ffixed-point")
55+
elseif(${feature} MATCHES "^builtin_")
56+
set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT})
57+
# The compiler might handle calls to rounding builtins by generating calls
58+
# to the respective libc math functions, in which case we cannot use these
59+
# builtins in our implementations of these functions. We check that this is
60+
# not the case by trying to link an executable, since linking would fail due
61+
# to unresolved references if calls to libc functions were generated.
62+
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
4763
endif()
4864

4965
try_compile(
@@ -60,6 +76,12 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
6076
set(LIBC_TYPES_HAS_FLOAT128 TRUE)
6177
elseif(${feature} STREQUAL "fixed_point")
6278
set(LIBC_COMPILER_HAS_FIXED_POINT TRUE)
79+
elseif(${feature} STREQUAL "builtin_ceil_floor_trunc")
80+
set(LIBC_COMPILER_HAS_BUILTIN_CEIL_FLOOR_TRUNC TRUE)
81+
elseif(${feature} STREQUAL "builtin_round")
82+
set(LIBC_COMPILER_HAS_BUILTIN_ROUND TRUE)
83+
elseif(${feature} STREQUAL "builtin_roundeven")
84+
set(LIBC_COMPILER_HAS_BUILTIN_ROUNDEVEN TRUE)
6385
endif()
6486
endif()
6587
endforeach()

libc/cmake/modules/LLVMLibCCompileOptionRules.cmake

Lines changed: 17 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,22 @@ 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_TRUNC)
27+
list(APPEND compile_options "-D__LIBC_USE_BUILTIN_CEIL_FLOOR_TRUNC")
28+
endif()
29+
if(LIBC_COMPILER_HAS_BUILTIN_ROUND)
30+
list(APPEND compile_options "-D__LIBC_USE_BUILTIN_ROUND")
31+
endif()
32+
if(LIBC_COMPILER_HAS_BUILTIN_ROUNDEVEN)
33+
list(APPEND compile_options "-D__LIBC_USE_BUILTIN_ROUNDEVEN")
34+
endif()
2135
endif()
2236
if(ADD_EXPLICIT_SIMD_OPT_FLAG)
2337
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: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
float try_builtin_ceilf(float x) { return __builtin_ceilf(x); }
2+
float try_builtin_floorf(float x) { return __builtin_ceilf(x); }
3+
float try_builtin_truncf(float x) { return __builtin_truncf(x); }
4+
5+
double try_builtin_ceil(double x) { return __builtin_ceil(x); }
6+
double try_builtin_floor(double x) { return __builtin_ceil(x); }
7+
double try_builtin_trunc(double x) { return __builtin_trunc(x); }
8+
9+
int main() {}
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+
int main() {}
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+
int main() {}

libc/src/math/generic/CMakeLists.txt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ add_entrypoint_object(
7070
-O3
7171
DEPENDS
7272
libc.src.__support.FPUtil.nearest_integer_operations
73+
FLAGS
74+
ROUND_OPT
7375
)
7476

7577
add_entrypoint_object(
@@ -82,6 +84,8 @@ add_entrypoint_object(
8284
-O3
8385
DEPENDS
8486
libc.src.__support.FPUtil.nearest_integer_operations
87+
FLAGS
88+
ROUND_OPT
8589
)
8690

8791
add_entrypoint_object(
@@ -107,6 +111,9 @@ add_entrypoint_object(
107111
DEPENDS
108112
libc.src.__support.macros.properties.types
109113
libc.src.__support.FPUtil.nearest_integer_operations
114+
libc.src.__support.macros.properties.architectures
115+
FLAGS
116+
ROUND_OPT
110117
)
111118

112119
add_entrypoint_object(
@@ -455,6 +462,8 @@ add_entrypoint_object(
455462
-O3
456463
DEPENDS
457464
libc.src.__support.FPUtil.nearest_integer_operations
465+
FLAGS
466+
ROUND_OPT
458467
)
459468

460469
add_entrypoint_object(
@@ -467,6 +476,8 @@ add_entrypoint_object(
467476
-O3
468477
DEPENDS
469478
libc.src.__support.FPUtil.nearest_integer_operations
479+
FLAGS
480+
ROUND_OPT
470481
)
471482

472483
add_entrypoint_object(
@@ -492,6 +503,9 @@ add_entrypoint_object(
492503
DEPENDS
493504
libc.src.__support.macros.properties.types
494505
libc.src.__support.FPUtil.nearest_integer_operations
506+
libc.src.__support.macros.properties.architectures
507+
FLAGS
508+
ROUND_OPT
495509
)
496510

497511
add_entrypoint_object(
@@ -517,6 +531,8 @@ add_entrypoint_object(
517531
-O3
518532
DEPENDS
519533
libc.src.__support.FPUtil.nearest_integer_operations
534+
FLAGS
535+
ROUND_OPT
520536
)
521537

522538
add_entrypoint_object(
@@ -529,6 +545,8 @@ add_entrypoint_object(
529545
-O3
530546
DEPENDS
531547
libc.src.__support.FPUtil.nearest_integer_operations
548+
FLAGS
549+
ROUND_OPT
532550
)
533551

534552
add_entrypoint_object(
@@ -554,6 +572,9 @@ add_entrypoint_object(
554572
DEPENDS
555573
libc.src.__support.macros.properties.types
556574
libc.src.__support.FPUtil.nearest_integer_operations
575+
libc.src.__support.macros.properties.architectures
576+
FLAGS
577+
ROUND_OPT
557578
)
558579

559580
add_entrypoint_object(
@@ -579,6 +600,8 @@ add_entrypoint_object(
579600
-O3
580601
DEPENDS
581602
libc.src.__support.FPUtil.nearest_integer_operations
603+
FLAGS
604+
ROUND_OPT
582605
)
583606

584607
add_entrypoint_object(
@@ -591,6 +614,8 @@ add_entrypoint_object(
591614
-O3
592615
DEPENDS
593616
libc.src.__support.FPUtil.nearest_integer_operations
617+
FLAGS
618+
ROUND_OPT
594619
)
595620

596621
add_entrypoint_object(
@@ -616,6 +641,9 @@ add_entrypoint_object(
616641
DEPENDS
617642
libc.src.__support.macros.properties.types
618643
libc.src.__support.FPUtil.nearest_integer_operations
644+
libc.src.__support.macros.properties.architectures
645+
FLAGS
646+
ROUND_OPT
619647
)
620648

621649
add_entrypoint_object(
@@ -641,6 +669,8 @@ add_entrypoint_object(
641669
-O3
642670
DEPENDS
643671
libc.src.__support.FPUtil.nearest_integer_operations
672+
FLAGS
673+
ROUND_OPT
644674
)
645675

646676
add_entrypoint_object(
@@ -653,6 +683,8 @@ add_entrypoint_object(
653683
-O3
654684
DEPENDS
655685
libc.src.__support.FPUtil.nearest_integer_operations
686+
FLAGS
687+
ROUND_OPT
656688
)
657689

658690
add_entrypoint_object(
@@ -678,6 +710,9 @@ add_entrypoint_object(
678710
DEPENDS
679711
libc.src.__support.macros.properties.types
680712
libc.src.__support.FPUtil.nearest_integer_operations
713+
libc.src.__support.macros.properties.architectures
714+
FLAGS
715+
ROUND_OPT
681716
)
682717

683718
add_entrypoint_object(

libc/src/math/generic/ceil.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212

1313
namespace LIBC_NAMESPACE {
1414

15-
LLVM_LIBC_FUNCTION(double, ceil, (double x)) { return fputil::ceil(x); }
15+
LLVM_LIBC_FUNCTION(double, ceil, (double x)) {
16+
#ifdef __LIBC_USE_BUILTIN_CEIL_FLOOR_TRUNC
17+
return __builtin_ceil(x);
18+
#else
19+
return fputil::ceil(x);
20+
#endif
21+
}
1622

1723
} // namespace LIBC_NAMESPACE

libc/src/math/generic/ceilf.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212

1313
namespace LIBC_NAMESPACE {
1414

15-
LLVM_LIBC_FUNCTION(float, ceilf, (float x)) { return fputil::ceil(x); }
15+
LLVM_LIBC_FUNCTION(float, ceilf, (float x)) {
16+
#ifdef __LIBC_USE_BUILTIN_CEIL_FLOOR_TRUNC
17+
return __builtin_ceilf(x);
18+
#else
19+
return fputil::ceil(x);
20+
#endif
21+
}
1622

1723
} // namespace LIBC_NAMESPACE

libc/src/math/generic/ceilf16.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,17 @@
99
#include "src/math/ceilf16.h"
1010
#include "src/__support/FPUtil/NearestIntegerOperations.h"
1111
#include "src/__support/common.h"
12+
#include "src/__support/macros/properties/architectures.h"
1213

1314
namespace LIBC_NAMESPACE {
1415

15-
LLVM_LIBC_FUNCTION(float16, ceilf16, (float16 x)) { return fputil::ceil(x); }
16+
LLVM_LIBC_FUNCTION(float16, ceilf16, (float16 x)) {
17+
#if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_TRUNC) && \
18+
defined(LIBC_TARGET_ARCH_IS_AARCH64)
19+
return static_cast<float16>(__builtin_ceilf(x));
20+
#else
21+
return fputil::ceil(x);
22+
#endif
23+
}
1624

1725
} // namespace LIBC_NAMESPACE

libc/src/math/generic/floor.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212

1313
namespace LIBC_NAMESPACE {
1414

15-
LLVM_LIBC_FUNCTION(double, floor, (double x)) { return fputil::floor(x); }
15+
LLVM_LIBC_FUNCTION(double, floor, (double x)) {
16+
#ifdef __LIBC_USE_BUILTIN_CEIL_FLOOR_TRUNC
17+
return __builtin_floor(x);
18+
#else
19+
return fputil::floor(x);
20+
#endif
21+
}
1622

1723
} // namespace LIBC_NAMESPACE

libc/src/math/generic/floorf.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212

1313
namespace LIBC_NAMESPACE {
1414

15-
LLVM_LIBC_FUNCTION(float, floorf, (float x)) { return fputil::floor(x); }
15+
LLVM_LIBC_FUNCTION(float, floorf, (float x)) {
16+
#ifdef __LIBC_USE_BUILTIN_CEIL_FLOOR_TRUNC
17+
return __builtin_floorf(x);
18+
#else
19+
return fputil::floor(x);
20+
#endif
21+
}
1622

1723
} // namespace LIBC_NAMESPACE

libc/src/math/generic/floorf16.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,17 @@
99
#include "src/math/floorf16.h"
1010
#include "src/__support/FPUtil/NearestIntegerOperations.h"
1111
#include "src/__support/common.h"
12+
#include "src/__support/macros/properties/architectures.h"
1213

1314
namespace LIBC_NAMESPACE {
1415

15-
LLVM_LIBC_FUNCTION(float16, floorf16, (float16 x)) { return fputil::floor(x); }
16+
LLVM_LIBC_FUNCTION(float16, floorf16, (float16 x)) {
17+
#if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_TRUNC) && \
18+
defined(LIBC_TARGET_ARCH_IS_AARCH64)
19+
return static_cast<float16>(__builtin_floorf(x));
20+
#else
21+
return fputil::floor(x);
22+
#endif
23+
}
1624

1725
} // namespace LIBC_NAMESPACE

libc/src/math/generic/round.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212

1313
namespace LIBC_NAMESPACE {
1414

15-
LLVM_LIBC_FUNCTION(double, round, (double x)) { return fputil::round(x); }
15+
LLVM_LIBC_FUNCTION(double, round, (double x)) {
16+
#ifdef __LIBC_USE_BUILTIN_ROUND
17+
return __builtin_round(x);
18+
#else
19+
return fputil::round(x);
20+
#endif
21+
}
1622

1723
} // namespace LIBC_NAMESPACE

libc/src/math/generic/roundeven.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@
1313
namespace LIBC_NAMESPACE {
1414

1515
LLVM_LIBC_FUNCTION(double, roundeven, (double x)) {
16+
#ifdef __LIBC_USE_BUILTIN_ROUNDEVEN
17+
return __builtin_roundeven(x);
18+
#else
1619
return fputil::round_using_specific_rounding_mode(x, FP_INT_TONEAREST);
20+
#endif
1721
}
1822

1923
} // namespace LIBC_NAMESPACE

libc/src/math/generic/roundevenf.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@
1313
namespace LIBC_NAMESPACE {
1414

1515
LLVM_LIBC_FUNCTION(float, roundevenf, (float x)) {
16+
#ifdef __LIBC_USE_BUILTIN_ROUNDEVEN
17+
return __builtin_roundevenf(x);
18+
#else
1619
return fputil::round_using_specific_rounding_mode(x, FP_INT_TONEAREST);
20+
#endif
1721
}
1822

1923
} // namespace LIBC_NAMESPACE

0 commit comments

Comments
 (0)