diff --git a/libc/include/llvm-libc-macros/math-function-macros.h b/libc/include/llvm-libc-macros/math-function-macros.h index 68f9ff9d1c033..c740eb2d18825 100644 --- a/libc/include/llvm-libc-macros/math-function-macros.h +++ b/libc/include/llvm-libc-macros/math-function-macros.h @@ -20,5 +20,9 @@ __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x) #define isnormal(x) __builtin_isnormal(x) #define issubnormal(x) (fpclassify(x) == FP_SUBNORMAL) +#if (defined(__clang__) && __clang_major__ >= 18) || \ + (defined(__GNUC__) && __GNUC__ >= 13) +#define issignaling(x) __builtin_issignaling(x) +#endif #endif // LLVM_LIBC_MACROS_MATH_FUNCTION_MACROS_H diff --git a/libc/test/include/CMakeLists.txt b/libc/test/include/CMakeLists.txt index 12692eed417c4..dd8f21bdd07ae 100644 --- a/libc/test/include/CMakeLists.txt +++ b/libc/test/include/CMakeLists.txt @@ -81,6 +81,36 @@ add_libc_test( libc.include.llvm-libc-macros.stdckdint_macros ) +add_libc_test( + issignaling_test + SUITE + libc_include_tests + SRCS + issignaling_test.cpp + DEPENDS + libc.include.llvm-libc-macros.math_function_macros +) + +add_libc_test( + issignalingf_test + SUITE + libc_include_tests + SRCS + issignalingf_test.cpp + DEPENDS + libc.include.llvm-libc-macros.math_function_macros +) + +add_libc_test( + issignalingl_test + SUITE + libc_include_tests + SRCS + issignalingl_test.cpp + DEPENDS + libc.include.llvm-libc-macros.math_function_macros +) + add_libc_test( issubnormal_test SUITE @@ -366,6 +396,21 @@ add_libc_test( libc.include.llvm-libc-macros.math_function_macros ) +add_libc_test( + issignaling_c_test + C_TEST + UNIT_TEST_ONLY + SUITE + libc_include_tests + SRCS + issignaling_test.c + COMPILE_OPTIONS + -Wall + -Werror + DEPENDS + libc.include.llvm-libc-macros.math_function_macros +) + add_libc_test( isinf_c_test C_TEST diff --git a/libc/test/include/IsSignalingTest.h b/libc/test/include/IsSignalingTest.h new file mode 100644 index 0000000000000..c369cfe090ed3 --- /dev/null +++ b/libc/test/include/IsSignalingTest.h @@ -0,0 +1,49 @@ +//===-- Utility class to test the issignaling macro ------------*- 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_TEST_INCLUDE_MATH_ISSIGNALING_H +#define LLVM_LIBC_TEST_INCLUDE_MATH_ISSIGNALING_H + +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +#include "include/llvm-libc-macros/math-function-macros.h" + +template +class IsSignalingTest : public LIBC_NAMESPACE::testing::Test { + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef int (*IsSignalingFunc)(T); + + void testSpecialNumbers(IsSignalingFunc func) { + EXPECT_EQ(func(aNaN), 0); + EXPECT_EQ(func(neg_aNaN), 0); + EXPECT_EQ(func(sNaN), 1); + EXPECT_EQ(func(neg_sNaN), 1); + EXPECT_EQ(func(inf), 0); + EXPECT_EQ(func(neg_inf), 0); + EXPECT_EQ(func(min_normal), 0); + EXPECT_EQ(func(max_normal), 0); + EXPECT_EQ(func(neg_max_normal), 0); + EXPECT_EQ(func(min_denormal), 0); + EXPECT_EQ(func(neg_min_denormal), 0); + EXPECT_EQ(func(max_denormal), 0); + EXPECT_EQ(func(zero), 0); + EXPECT_EQ(func(neg_zero), 0); + } +}; + +#define LIST_ISSIGNALING_TESTS(T, func) \ + using LlvmLibcIsSignalingTest = IsSignalingTest; \ + TEST_F(LlvmLibcIsSignalingTest, SpecialNumbers) { \ + auto issignaling_func = [](T x) { return func(x); }; \ + testSpecialNumbers(issignaling_func); \ + } + +#endif // LLVM_LIBC_TEST_INCLUDE_MATH_ISSIGNALING_H diff --git a/libc/test/include/issignaling_test.c b/libc/test/include/issignaling_test.c new file mode 100644 index 0000000000000..2c080696404ae --- /dev/null +++ b/libc/test/include/issignaling_test.c @@ -0,0 +1,24 @@ +//===-- Unittests for issignaling macro -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-function-macros.h" + +#include + +// TODO: enable the test unconditionally when issignaling macro is fixed for +// older compiler +int main(void) { +#ifdef issignaling + assert(issignaling(__builtin_nans("")) == 1); + assert(issignaling(__builtin_nansf("")) == 1); + assert(issignaling(__builtin_nansl("")) == 1); + assert(issignaling(1.819f) == 0); + assert(issignaling(-1.726) == 0); + assert(issignaling(1.426L) == 0); +#endif + return 0; +} diff --git a/libc/test/include/issignaling_test.cpp b/libc/test/include/issignaling_test.cpp new file mode 100644 index 0000000000000..ef007feb0a633 --- /dev/null +++ b/libc/test/include/issignaling_test.cpp @@ -0,0 +1,18 @@ +//===-- Unittest for issignaling[d] macro ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "IsSignalingTest.h" +#include "include/llvm-libc-macros/math-function-macros.h" + +// TODO: enable the test unconditionally when issignaling macro is fixed for +// older compiler +#ifdef issignaling +LIST_ISSIGNALING_TESTS(double, issignaling) +#else +int main() { return 0; } +#endif diff --git a/libc/test/include/issignalingf_test.cpp b/libc/test/include/issignalingf_test.cpp new file mode 100644 index 0000000000000..9b236f2bb84d7 --- /dev/null +++ b/libc/test/include/issignalingf_test.cpp @@ -0,0 +1,18 @@ +//===-- Unittest for issignaling[f] macro ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "IsSignalingTest.h" +#include "include/llvm-libc-macros/math-function-macros.h" + +// TODO: enable the test unconditionally when issignaling macro is fixed for +// older compiler +#ifdef issignaling +LIST_ISSIGNALING_TESTS(float, issignaling) +#else +int main() { return 0; } +#endif diff --git a/libc/test/include/issignalingl_test.cpp b/libc/test/include/issignalingl_test.cpp new file mode 100644 index 0000000000000..35482cb4b0202 --- /dev/null +++ b/libc/test/include/issignalingl_test.cpp @@ -0,0 +1,18 @@ +//===-- Unittest for issignaling[l] macro ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "IsSignalingTest.h" +#include "include/llvm-libc-macros/math-function-macros.h" + +// TODO: enable the test unconditionally when issignaling macro is fixed for +// older compiler +#ifdef issignaling +LIST_ISSIGNALING_TESTS(long double, issignaling) +#else +int main() { return 0; } +#endif