1//===-- Implementation header for roundf ------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_ROUNDF_H
10#define LLVM_LIBC_SRC___SUPPORT_MATH_ROUNDF_H
11
12#include "src/__support/FPUtil/NearestIntegerOperations.h"
13#include "src/__support/macros/attributes.h"
14#include "src/__support/macros/config.h"
15#include "src/__support/macros/properties/compiler.h"
16#include "src/__support/macros/properties/cpu_features.h"
17
18namespace LIBC_NAMESPACE_DECL {
19namespace math {
20
21// For the following targets, clang will generate rounding instructions
22// by default:
23// - x86-64 with sse4.1 or after
24// - ARM v8
25// - RISC-V
26
27// Notes: gcc does not generate the instructions for x86-64 by default.
28
29// Notes: for x86-64, if `-ffp-model=strict` is set, `__builtin_round` will
30// generate a callback to `round` and it does not look like there is any way for
31// us to detect that just from the pre-defined macros. The only way to really
32// detect the call back is to compile and link with nostdlib.
33// This also affects `__builtin_elementwise_round`, making it behave identical
34// to `__builtin_round`.
35
36// Notes: `__builtin_elementwise_round` is slightly better than
37// `__builtin_round` in that it is not defined for x86-64 pre-SSE4.1, but it
38// still generate callback for ARM version < 8, and for x86-64 with
39// `-ffp-model=strict`.
40
41LIBC_INLINE LIBC_CONSTEXPR float roundf(float x) {
42#if __has_builtin(__builtin_roundf) && !defined(LIBC_USE_CONSTEXPR) && \
43 (defined(__LIBC_USE_BUILTIN_ROUND) || \
44 (defined(LIBC_COMPILER_IS_CLANG) && \
45 defined(LIBC_TARGET_CPU_HAS_FPU_FLOAT) && \
46 (!defined(__ARM_ARCH) || (__ARM_ARCH >= 8))))
47 return __builtin_roundf(x);
48#else
49 return fputil::round(x);
50#endif
51}
52
53} // namespace math
54} // namespace LIBC_NAMESPACE_DECL
55
56#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ROUNDF_H
57