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