[libc-commits] [libc] [llvm] [libc][math] Refactor isnan family to header-only (PR #195598)
via libc-commits
libc-commits at lists.llvm.org
Mon May 4 00:00:38 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Anonmiraj (AnonMiraj)
<details>
<summary>Changes</summary>
Refactors the isnan math family to be header-only.
part of: #<!-- -->147386
Target Functions:
- isnan
- isnanf
---
Full diff: https://github.com/llvm/llvm-project/pull/195598.diff
19 Files Affected:
- (modified) libc/cmake/modules/CheckCompilerFeatures.cmake (+3)
- (modified) libc/cmake/modules/LLVMLibCCompileOptionRules.cmake (+3)
- (added) libc/cmake/modules/compiler_features/check_builtin_isnan.cpp (+5)
- (modified) libc/shared/math.h (+3)
- (added) libc/shared/math/isnan.h (+23)
- (added) libc/shared/math/isnanf.h (+23)
- (added) libc/shared/math/isnanl.h (+23)
- (modified) libc/src/__support/math/CMakeLists.txt (+27)
- (added) libc/src/__support/math/isnan.h (+29)
- (added) libc/src/__support/math/isnanf.h (+29)
- (added) libc/src/__support/math/isnanl.h (+29)
- (modified) libc/src/math/generic/CMakeLists.txt (+1-1)
- (modified) libc/src/math/generic/isnan.cpp (+2-3)
- (modified) libc/src/math/generic/isnanf.cpp (+2-3)
- (modified) libc/src/math/generic/isnanl.cpp (+2-3)
- (modified) libc/test/shared/CMakeLists.txt (+6)
- (modified) libc/test/shared/shared_math_constexpr_test.cpp (+3)
- (modified) libc/test/shared/shared_math_test.cpp (+3)
- (modified) utils/bazel/llvm-project-overlay/libc/BUILD.bazel (+48)
``````````diff
diff --git a/libc/cmake/modules/CheckCompilerFeatures.cmake b/libc/cmake/modules/CheckCompilerFeatures.cmake
index 4d50d81e0ce45..85f6c6ca1c807 100644
--- a/libc/cmake/modules/CheckCompilerFeatures.cmake
+++ b/libc/cmake/modules/CheckCompilerFeatures.cmake
@@ -7,6 +7,7 @@ set(
"builtin_ceil_floor_rint_trunc"
"builtin_fmax_fmin"
"builtin_fmaxf16_fminf16"
+ "builtin_isnan"
"builtin_round"
"builtin_roundeven"
"float16"
@@ -123,6 +124,8 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
set(LIBC_COMPILER_HAS_BUILTIN_FMAX_FMIN TRUE)
elseif(${feature} STREQUAL "builtin_fmaxf16_fminf16")
set(LIBC_COMPILER_HAS_BUILTIN_FMAXF16_FMINF16 TRUE)
+ elseif(${feature} STREQUAL "builtin_isnan")
+ set(LIBC_COMPILER_HAS_BUILTIN_ISNAN TRUE)
elseif(${feature} STREQUAL "builtin_round")
set(LIBC_COMPILER_HAS_BUILTIN_ROUND TRUE)
elseif(${feature} STREQUAL "builtin_roundeven")
diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
index ea86659cd5590..2d3703eefa0ac 100644
--- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
+++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
@@ -52,6 +52,9 @@ function(_get_compile_options_from_flags output_var)
list(APPEND compile_options "-mfma")
endif()
endif()
+ if(LIBC_COMPILER_HAS_BUILTIN_ISNAN)
+ list(APPEND compile_options "-D__LIBC_USE_BUILTIN_ISNAN")
+ endif()
if(ADD_ROUND_OPT_FLAG)
if(LIBC_TARGET_ARCHITECTURE_IS_X86_64)
# ROUND_OPT_FLAG is only enabled if SSE4.2 is detected, not just SSE4.1,
diff --git a/libc/cmake/modules/compiler_features/check_builtin_isnan.cpp b/libc/cmake/modules/compiler_features/check_builtin_isnan.cpp
new file mode 100644
index 0000000000000..b761833f9ac3d
--- /dev/null
+++ b/libc/cmake/modules/compiler_features/check_builtin_isnan.cpp
@@ -0,0 +1,5 @@
+int try_builtin_isnan(double x) { return __builtin_isnan(x); }
+int try_builtin_isnanf(float x) { return __builtin_isnan(x); }
+int try_builtin_isnanl(long double x) { return __builtin_isnan(x); }
+
+extern "C" void _start() {}
diff --git a/libc/shared/math.h b/libc/shared/math.h
index a3cdbb12f0e51..dc75a8b78cd8e 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -287,6 +287,9 @@
#include "math/iscanonicalf128.h"
#include "math/iscanonicalf16.h"
#include "math/iscanonicall.h"
+#include "math/isnan.h"
+#include "math/isnanf.h"
+#include "math/isnanl.h"
#include "math/issignaling.h"
#include "math/issignalingbf16.h"
#include "math/issignalingf.h"
diff --git a/libc/shared/math/isnan.h b/libc/shared/math/isnan.h
new file mode 100644
index 0000000000000..6039f309d3255
--- /dev/null
+++ b/libc/shared/math/isnan.h
@@ -0,0 +1,23 @@
+//===-- Shared isnan function -----------------------------------*- C++ -*-===//
+//
+// 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_SHARED_MATH_ISNAN_H
+#define LLVM_LIBC_SHARED_MATH_ISNAN_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/isnan.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::isnan;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_ISNAN_H
diff --git a/libc/shared/math/isnanf.h b/libc/shared/math/isnanf.h
new file mode 100644
index 0000000000000..2858342fb13c0
--- /dev/null
+++ b/libc/shared/math/isnanf.h
@@ -0,0 +1,23 @@
+//===-- Shared isnanf function ----------------------------------*- C++ -*-===//
+//
+// 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_SHARED_MATH_ISNANF_H
+#define LLVM_LIBC_SHARED_MATH_ISNANF_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/isnanf.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::isnanf;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_ISNANF_H
diff --git a/libc/shared/math/isnanl.h b/libc/shared/math/isnanl.h
new file mode 100644
index 0000000000000..4cc3b90b5bcf7
--- /dev/null
+++ b/libc/shared/math/isnanl.h
@@ -0,0 +1,23 @@
+//===-- Shared isnanl function ----------------------------------*- C++ -*-===//
+//
+// 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_SHARED_MATH_ISNANL_H
+#define LLVM_LIBC_SHARED_MATH_ISNANL_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/isnanl.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::isnanl;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_ISNANL_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index fb0ecec031c75..e188aed2cd998 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -1677,6 +1677,33 @@ add_header_library(
libc.src.__support.macros.config
)
+add_header_library(
+ isnan
+ HDRS
+ isnan.h
+ DEPENDS
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.macros.config
+)
+
+add_header_library(
+ isnanf
+ HDRS
+ isnanf.h
+ DEPENDS
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.macros.config
+)
+
+add_header_library(
+ isnanl
+ HDRS
+ isnanl.h
+ DEPENDS
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.macros.config
+)
+
add_header_library(
issignaling
HDRS
diff --git a/libc/src/__support/math/isnan.h b/libc/src/__support/math/isnan.h
new file mode 100644
index 0000000000000..c09294ba6967e
--- /dev/null
+++ b/libc/src/__support/math/isnan.h
@@ -0,0 +1,29 @@
+//===-- Implementation header for isnan -------------------------*- C++ -*-===//
+//
+// 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_MATH_ISNAN_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ISNAN_H
+
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+LIBC_INLINE LIBC_CONSTEXPR int isnan(double x) {
+#if defined(__LIBC_USE_BUILTIN_ISNAN) && !defined(LIBC_HAS_CONSTANT_EVALUATION)
+ return __builtin_isnan(x);
+#else
+ return fputil::FPBits<double>(x).is_nan();
+#endif
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ISNAN_H
diff --git a/libc/src/__support/math/isnanf.h b/libc/src/__support/math/isnanf.h
new file mode 100644
index 0000000000000..1f3ee4f7a0803
--- /dev/null
+++ b/libc/src/__support/math/isnanf.h
@@ -0,0 +1,29 @@
+//===-- Implementation header for isnanf ------------------------*- C++ -*-===//
+//
+// 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_MATH_ISNANF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ISNANF_H
+
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+LIBC_INLINE LIBC_CONSTEXPR int isnanf(float x) {
+#if defined(__LIBC_USE_BUILTIN_ISNAN) && !defined(LIBC_HAS_CONSTANT_EVALUATION)
+ return __builtin_isnan(x);
+#else
+ return fputil::FPBits<float>(x).is_nan();
+#endif
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ISNANF_H
diff --git a/libc/src/__support/math/isnanl.h b/libc/src/__support/math/isnanl.h
new file mode 100644
index 0000000000000..51e78ae4131a6
--- /dev/null
+++ b/libc/src/__support/math/isnanl.h
@@ -0,0 +1,29 @@
+//===-- Implementation header for isnanl ------------------------*- C++ -*-===//
+//
+// 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_MATH_ISNANL_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ISNANL_H
+
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+LIBC_INLINE LIBC_CONSTEXPR int isnanl(long double x) {
+#if defined(__LIBC_USE_BUILTIN_ISNAN) && !defined(LIBC_HAS_CONSTANT_EVALUATION)
+ return __builtin_isnan(x);
+#else
+ return fputil::FPBits<long double>(x).is_nan();
+#endif
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ISNANL_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index e4ec5838eda4e..ca374979d0542 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -3090,7 +3090,7 @@ add_entrypoint_object(
HDRS
../nan.h
DEPENDS
- libc.src.__support.math.nan
+ libc.src.__support.math.isnanl
)
add_entrypoint_object(
diff --git a/libc/src/math/generic/isnan.cpp b/libc/src/math/generic/isnan.cpp
index 73230a4e9a299..68392a709ca8d 100644
--- a/libc/src/math/generic/isnan.cpp
+++ b/libc/src/math/generic/isnan.cpp
@@ -7,11 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/isnan.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/isnan.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(int, isnan, (double x)) { return __builtin_isnan(x); }
+LLVM_LIBC_FUNCTION(int, isnan, (double x)) { return math::isnan(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/isnanf.cpp b/libc/src/math/generic/isnanf.cpp
index a1d814eab1825..40cdb01297c2a 100644
--- a/libc/src/math/generic/isnanf.cpp
+++ b/libc/src/math/generic/isnanf.cpp
@@ -7,11 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/isnanf.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/isnanf.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(int, isnanf, (float x)) { return __builtin_isnan(x); }
+LLVM_LIBC_FUNCTION(int, isnanf, (float x)) { return math::isnanf(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/isnanl.cpp b/libc/src/math/generic/isnanl.cpp
index 57ce79f3c7b47..b9bd4518e9475 100644
--- a/libc/src/math/generic/isnanl.cpp
+++ b/libc/src/math/generic/isnanl.cpp
@@ -7,11 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/isnanl.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/isnanl.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(int, isnanl, (long double x)) { return __builtin_isnan(x); }
+LLVM_LIBC_FUNCTION(int, isnanl, (long double x)) { return math::isnanl(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index 680491878705c..c95683b8bd8e4 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -284,6 +284,9 @@ add_fp_unittest(
libc.src.__support.math.iscanonicalf128
libc.src.__support.math.iscanonicalf16
libc.src.__support.math.iscanonicall
+ libc.src.__support.math.isnan
+ libc.src.__support.math.isnanf
+ libc.src.__support.math.isnanl
libc.src.__support.math.issignaling
libc.src.__support.math.issignalingbf16
libc.src.__support.math.issignalingf
@@ -629,6 +632,9 @@ add_fp_unittest(
libc.src.__support.math.iscanonicalf128
libc.src.__support.math.iscanonicalf16
libc.src.__support.math.iscanonicall
+ libc.src.__support.math.isnan
+ libc.src.__support.math.isnanf
+ libc.src.__support.math.isnanl
libc.src.__support.math.issignaling
libc.src.__support.math.issignalingbf16
libc.src.__support.math.issignalingf
diff --git a/libc/test/shared/shared_math_constexpr_test.cpp b/libc/test/shared/shared_math_constexpr_test.cpp
index e99f8691451a3..fc95de84f7c9c 100644
--- a/libc/test/shared/shared_math_constexpr_test.cpp
+++ b/libc/test/shared/shared_math_constexpr_test.cpp
@@ -84,6 +84,8 @@ static_assert(1 == [] {
LIBC_NAMESPACE::shared::nan(&arg))
.is_nan();
}());
+static_assert(0.0 == LIBC_NAMESPACE::shared::isnan(0.0));
+static_assert(0.0 == LIBC_NAMESPACE::shared::isnanf(0.0f));
//===----------------------------------------------------------------------===//
// Float Tests
@@ -325,6 +327,7 @@ static_assert(1 == [] {
const char arg{};
return LIBC_NAMESPACE::fputil::FPBits<long double>(LIBC_NAMESPACE::shared::nanl(&arg)).is_nan();
}());
+static_assert(0.0 == LIBC_NAMESPACE::shared::isnanl(0.0L));
#endif
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index d5753dce2b8ad..a1217ed0226b9 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -307,6 +307,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat) {
EXPECT_EQ(1, LIBC_NAMESPACE::shared::iscanonicalf(0.0f));
EXPECT_EQ(0, LIBC_NAMESPACE::shared::issignalingf(0.0f));
EXPECT_TRUE(FPBits(LIBC_NAMESPACE::shared::nanf("")).is_nan());
+ EXPECT_EQ(0, LIBC_NAMESPACE::shared::isnanf(0.0f));
}
TEST(LlvmLibcSharedMathTest, AllDouble) {
@@ -438,6 +439,7 @@ TEST(LlvmLibcSharedMathTest, AllDouble) {
EXPECT_EQ(1, LIBC_NAMESPACE::shared::iscanonical(0.0L));
EXPECT_EQ(0, LIBC_NAMESPACE::shared::issignaling(0.0));
EXPECT_TRUE(FPBits(LIBC_NAMESPACE::shared::nan("")).is_nan());
+ EXPECT_EQ(0, LIBC_NAMESPACE::shared::isnan(0.0));
}
// TODO: Enable the tests when double-double type is supported.
@@ -551,6 +553,7 @@ TEST(LlvmLibcSharedMathTest, AllLongDouble) {
EXPECT_EQ(1, LIBC_NAMESPACE::shared::iscanonicall(0.0L));
EXPECT_EQ(0, LIBC_NAMESPACE::shared::issignalingl(0.0L));
EXPECT_TRUE(FPBits(LIBC_NAMESPACE::shared::nanl("")).is_nan());
+ EXPECT_EQ(0, LIBC_NAMESPACE::shared::isnanl(0.0L));
}
#endif // LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index f7de59245489a..7953cbc719619 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -4877,6 +4877,33 @@ libc_support_library(
],
)
+libc_support_library(
+ name = "__support_math_isnan",
+ hdrs = ["src/__support/math/isnan.h"],
+ deps = [
+ ":__support_fputil_fp_bits",
+ ":__support_macros_config",
+ ],
+)
+
+libc_support_library(
+ name = "__support_math_isnanf",
+ hdrs = ["src/__support/math/isnanf.h"],
+ deps = [
+ ":__support_fputil_fp_bits",
+ ":__support_macros_config",
+ ],
+)
+
+libc_support_library(
+ name = "__support_math_isnanl",
+ hdrs = ["src/__support/math/isnanl.h"],
+ deps = [
+ ":__support_fputil_fp_bits",
+ ":__support_macros_config",
+ ],
+)
+
libc_support_library(
name = "__support_math_issignaling",
hdrs = ["src/__support/math/issignaling.h"],
@@ -9297,6 +9324,27 @@ libc_math_function(
],
)
+libc_math_function(
+ name = "isnan",
+ additional_deps = [
+ ":__support_math_isnan",
+ ],
+)
+
+libc_math_function(
+ name = "isnanf",
+ additional_deps = [
+ ":__support_math_isnanf",
+ ],
+)
+
+libc_math_function(
+ name = "isnanl",
+ additional_deps = [
+ ":__support_math_isnanl",
+ ],
+)
+
libc_math_function(
name = "issignaling",
additional_deps = [
``````````
</details>
https://github.com/llvm/llvm-project/pull/195598
More information about the libc-commits
mailing list