diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt --- a/libc/src/__support/FPUtil/CMakeLists.txt +++ b/libc/src/__support/FPUtil/CMakeLists.txt @@ -13,6 +13,7 @@ NormalFloat.h PlatformDefs.h UInt.h + builtin_wrappers.h DEPENDS libc.include.math libc.include.errno diff --git a/libc/src/__support/FPUtil/builtin_wrappers.h b/libc/src/__support/FPUtil/builtin_wrappers.h new file mode 100644 --- /dev/null +++ b/libc/src/__support/FPUtil/builtin_wrappers.h @@ -0,0 +1,61 @@ +//===--Convenient template for builtins -------------------------*- C++ -*-===// +// (Count Lead Zeroes) and (Count Trailing Zeros) +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_BUILTIN_WRAPPERS_H +#define LLVM_LIBC_SRC_SUPPORT_FPUTIL_BUILTIN_WRAPPERS_H + +namespace __llvm_libc { +namespace fputil { + +// The following overloads are matched based on what is accepted by +// __builtin_clz/ctz* rather than using the exactly-sized aliases from stdint.h. +// This way, we can avoid making any assumptions about integer sizes and let the +// compiler match for us. +template static inline int clz(T val); +template <> inline int clz(unsigned int val) { + return __builtin_clz(val); +} +template <> inline int clz(unsigned long int val) { + return __builtin_clzl(val); +} +template <> inline int clz(unsigned long long int val) { + return __builtin_clzll(val); +} + +template static inline int ctz(T val); +template <> inline int ctz(unsigned int val) { + return __builtin_ctz(val); +} +template <> inline int ctz(unsigned long int val) { + return __builtin_ctzl(val); +} +template <> inline int ctz(unsigned long long int val) { + return __builtin_ctzll(val); +} + +template static inline bool isnan(T val) { + return __builtin_isnan(val); +} + +template static inline bool isinf(T val) { + return __builtin_isinf(val); +} + +template static inline bool isfinite(T val) { + return __builtin_isfinite(val); +} + +inline float quiet_NaN(float) { return __builtin_nanf(""); } +inline double quiet_NaN(double) { return __builtin_nan(""); } +inline long double quiet_NaN(long double) { return __builtin_nanl(""); } + +} // namespace fputil +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_BUILTIN_WRAPPERS_H diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h --- a/libc/src/__support/FPUtil/generic/sqrt.h +++ b/libc/src/__support/FPUtil/generic/sqrt.h @@ -15,6 +15,7 @@ #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PlatformDefs.h" +#include "src/__support/FPUtil/builtin_wrappers.h" namespace __llvm_libc { namespace fputil { @@ -31,20 +32,7 @@ }; #endif // SPECIAL_X86_LONG_DOUBLE -// The following overloads are matched based on what is accepted by -// __builtin_clz* rather than using the exactly-sized aliases from stdint.h. -// This way, we can avoid making any assumptions about integer sizes and let the -// compiler match for us. -template static inline int clz(T val); -template <> inline int clz(unsigned int val) { - return __builtin_clz(val); -} -template <> inline int clz(unsigned long int val) { - return __builtin_clzl(val); -} -template <> inline int clz(unsigned long long int val) { - return __builtin_clzll(val); -} +using fputil::ctz; template static inline void normalize(int &exponent,