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