xref: /freebsd/contrib/llvm-project/libc/src/__support/FPUtil/sqrt.h (revision bb722a7d0f1642bff6487f943ad0427799a6e5bf)
1 //===-- Square root of IEEE 754 floating point numbers ----------*- 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_FPUTIL_SQRT_H
10 #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_SQRT_H
11 
12 #include "src/__support/macros/properties/architectures.h"
13 #include "src/__support/macros/properties/cpu_features.h"
14 
15 #include "src/__support/FPUtil/generic/sqrt.h"
16 
17 // Generic instruction specializations with __builtin_elementwise_sqrt.
18 #if defined(LIBC_TARGET_CPU_HAS_FPU_FLOAT) ||                                  \
19     defined(LIBC_TARGET_CPU_HAS_FPU_DOUBLE)
20 
21 #if __has_builtin(__builtin_elementwise_sqrt)
22 
23 namespace LIBC_NAMESPACE_DECL {
24 namespace fputil {
25 
26 #ifdef LIBC_TARGET_CPU_HAS_FPU_FLOAT
27 template <> LIBC_INLINE float sqrt<float>(float x) {
28   return __builtin_elementwise_sqrt(x);
29 }
30 #endif // LIBC_TARGET_CPU_HAS_FPU_FLOAT
31 
32 #ifdef LIBC_TARGET_CPU_HAS_FPU_DOUBLE
33 template <> LIBC_INLINE double sqrt<double>(double x) {
34   return __builtin_elementwise_sqrt(x);
35 }
36 #endif // LIBC_TARGET_CPU_HAS_FPU_DOUBLE
37 
38 // Use 80-bit long double instruction on x86.
39 // https://godbolt.org/z/oWEaj6hxK
40 #ifdef LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
41 template <> LIBC_INLINE long double sqrt<long double>(long double x) {
42   return __builtin_elementwise_sqrt(x);
43 }
44 #endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
45 
46 } // namespace fputil
47 } // namespace LIBC_NAMESPACE_DECL
48 
49 #else // __builtin_elementwise_sqrt
50 // Use inline assembly when __builtin_elementwise_sqrt is not available.
51 #if defined(LIBC_TARGET_CPU_HAS_SSE2)
52 #include "x86_64/sqrt.h"
53 #elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && defined(__ARM_FP)
54 #include "aarch64/sqrt.h"
55 #elif defined(LIBC_TARGET_ARCH_IS_ARM)
56 #include "arm/sqrt.h"
57 #elif defined(LIBC_TARGET_ARCH_IS_ANY_RISCV)
58 #include "riscv/sqrt.h"
59 #endif // Target specific header of inline asm.
60 
61 #endif // __builtin_elementwise_sqrt
62 
63 #endif // LIBC_TARGET_CPU_HAS_FPU_FLOAT or DOUBLE
64 
65 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_SQRT_H
66