From ad7b23430f2596b25e474025519e242f66353c4e Mon Sep 17 00:00:00 2001 From: "Bader, Alexey" Date: Thu, 31 Jul 2025 10:40:39 -0700 Subject: [PATCH 1/5] [SYCL][NVPTX] Move MSVC math functions to headers MSVC's `` header uses a number of non-standard functions defined in ``. Move definitions of these functions to headers to fix compiltion on Windows platform with MSVC. --- libdevice/msvc_math.cpp | 4 +-- .../__sycl_cmath_wrapper_impl.hpp | 36 +++++++++++++++---- sycl/include/sycl/stl_wrappers/math.h | 35 ++++++++++++++++++ 3 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 sycl/include/sycl/stl_wrappers/math.h diff --git a/libdevice/msvc_math.cpp b/libdevice/msvc_math.cpp index 5ca0b5608ffa7..c4619dacdce01 100644 --- a/libdevice/msvc_math.cpp +++ b/libdevice/msvc_math.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#if defined(__SPIR__) || defined(__SPIRV__) || defined(__NVPTX__) +#if defined(__SPIR__) || defined(__SPIRV__) #include "device.h" #include @@ -281,4 +281,4 @@ float _FSinh(float x, float y) { // compute y * sinh(x), |y| <= 1 return neg ? -x : x; } } -#endif // __SPIR__ || __SPIRV__ || __NVPTX__ +#endif // __SPIR__ || __SPIRV__ diff --git a/sycl/include/sycl/stl_wrappers/__sycl_cmath_wrapper_impl.hpp b/sycl/include/sycl/stl_wrappers/__sycl_cmath_wrapper_impl.hpp index fe08d374ca51c..6fcea22496236 100644 --- a/sycl/include/sycl/stl_wrappers/__sycl_cmath_wrapper_impl.hpp +++ b/sycl/include/sycl/stl_wrappers/__sycl_cmath_wrapper_impl.hpp @@ -16,8 +16,7 @@ // The 'sycl_device_only' attribute enables device-side overloading. #define __SYCL_DEVICE __attribute__((sycl_device_only, always_inline)) -#define __SYCL_DEVICE_C \ - extern "C" __attribute__((sycl_device_only, always_inline)) +#define __SYCL_DEVICE_C extern "C" __SYCL_DEVICE #include @@ -259,9 +258,16 @@ __SYCL_SPIRV_MAP_BINARY_C(nextafter); __SYCL_SPIRV_MAP_BINARY_C(copysign); /// Classification and comparison -// -// unsupported: fpclassify +__SYCL_DEVICE_C int fpclassify(float x) { + return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, + FP_ZERO, x); +} +__SYCL_DEVICE_C int fpclassify(double x) { + return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, + FP_ZERO, x); +} + // unsupported: isfinite // unsupported: isinf // unsupported: isnan @@ -460,7 +466,7 @@ template __SYCL_DEVICE __sycl_promote_t scalbn(T x, int exp) { __SYCL_SPIRV_MAP_BINARY_CXX(copysign); // Classification and comparison -// using ::fpclassify; +using ::fpclassify; // using ::isfinite; // using ::isgreater; // using ::isgreaterequal; @@ -482,11 +488,27 @@ _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif +#if defined(_WIN32) +__SYCL_DEVICE_C double _Cosh(double x, double y) { return cosh(x) * y; } +__SYCL_DEVICE_C float _FCosh(float x, float y) { return coshf(x) * y; } +__SYCL_DEVICE_C short _Dtest(double *p) { return fpclassify(*p); } +__SYCL_DEVICE_C short _FDtest(float *p) { return fpclassify(*p); } +__SYCL_DEVICE_C double _Sinh(double x, double y) { return sinh(x) * y; } +__SYCL_DEVICE_C float _FSinh(float x, float y) { return sinhf(x) * y; } +__SYCL_DEVICE_C short _Exp(double *px, double y, short eoff) { + return exp(*px) * ldexp(y, eoff); +} +__SYCL_DEVICE_C short _FExp(float *px, float y, short eoff) { + return exp(*px) * ldexp(y, eoff); +} +__SYCL_DEVICE_C float _hypotf(float x, float y) { return hypotf(x, y); } +#endif // defined(_WIN32) + #undef __SYCL_SPIRV_MAP_BINARY_C #undef __SYCL_SPIRV_MAP_BINARY_CXX #undef __SYCL_SPIRV_MAP_UNARY_C #undef __SYCL_SPIRV_MAP_UNARY_CXX #undef __SYCL_DEVICE_C #undef __SYCL_DEVICE -#endif -#endif +#endif // __SYCL_DEVICE_ONLY__ +#endif // __SYCL_CMATH_WRAPPER_IMPL_HPP__ diff --git a/sycl/include/sycl/stl_wrappers/math.h b/sycl/include/sycl/stl_wrappers/math.h new file mode 100644 index 0000000000000..8c7929586f7f1 --- /dev/null +++ b/sycl/include/sycl/stl_wrappers/math.h @@ -0,0 +1,35 @@ +//==- math.h -------------------------------------------------------------0-==// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#pragma once + +#if defined(__SYCL_DEVICE_ONLY__) && defined(_WIN32) +// Define _*dsign before including math.h because _*dsign is used by signbit defined +// in UCRT headers. +extern "C" __attribute__((sycl_device_only, always_inline)) +int _fdsign(float x) { + return __builtin_signbit(x); +} +extern "C" __attribute__((sycl_device_only, always_inline)) +int _dsign(double x) { + return __builtin_signbit(x); +} +#endif // __SYCL_DEVICE_ONLY__ && _WIN32 + +#if defined(__has_include_next) +// GCC/clang support go through this path. +#include_next +#else +// MSVC doesn't support "#include_next", so we have to be creative. +// Our header is located in "stl_wrappers/" directory so it won't be picked by +// the following include. MSVC's installation, on the other hand, has the layout +// where the following would result in the header we want. This is obviously +// hacky, but the best we can do... +#include <../include/math.h> +#endif + From 731492b27b522f9e66cbd23e11939c6f563f145e Mon Sep 17 00:00:00 2001 From: Alexey Bader Date: Tue, 5 Aug 2025 13:21:11 -0700 Subject: [PATCH 2/5] clang-format. --- sycl/include/sycl/stl_wrappers/math.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sycl/include/sycl/stl_wrappers/math.h b/sycl/include/sycl/stl_wrappers/math.h index 8c7929586f7f1..8a6626260d940 100644 --- a/sycl/include/sycl/stl_wrappers/math.h +++ b/sycl/include/sycl/stl_wrappers/math.h @@ -9,14 +9,14 @@ #pragma once #if defined(__SYCL_DEVICE_ONLY__) && defined(_WIN32) -// Define _*dsign before including math.h because _*dsign is used by signbit defined -// in UCRT headers. -extern "C" __attribute__((sycl_device_only, always_inline)) -int _fdsign(float x) { +// Define _*dsign before including math.h because _*dsign is used by signbit +// defined in UCRT headers. +extern "C" __attribute__((sycl_device_only, always_inline)) int +_fdsign(float x) { return __builtin_signbit(x); } -extern "C" __attribute__((sycl_device_only, always_inline)) -int _dsign(double x) { +extern "C" __attribute__((sycl_device_only, always_inline)) int +_dsign(double x) { return __builtin_signbit(x); } #endif // __SYCL_DEVICE_ONLY__ && _WIN32 @@ -32,4 +32,3 @@ int _dsign(double x) { // hacky, but the best we can do... #include <../include/math.h> #endif - From 60844a6fb0d94433399740c21683116286166b07 Mon Sep 17 00:00:00 2001 From: Alexey Bader Date: Tue, 5 Aug 2025 14:41:55 -0700 Subject: [PATCH 3/5] Move _dsign/_fdsign definitions to cmath header. --- sycl/include/sycl/stl_wrappers/cmath | 14 +++++++++++ sycl/include/sycl/stl_wrappers/math.h | 34 --------------------------- 2 files changed, 14 insertions(+), 34 deletions(-) delete mode 100644 sycl/include/sycl/stl_wrappers/math.h diff --git a/sycl/include/sycl/stl_wrappers/cmath b/sycl/include/sycl/stl_wrappers/cmath index 42b7e9cd3e642..10f6c84c381f4 100644 --- a/sycl/include/sycl/stl_wrappers/cmath +++ b/sycl/include/sycl/stl_wrappers/cmath @@ -8,6 +8,20 @@ #pragma once +#if defined(__SYCL_DEVICE_ONLY__) && defined(_WIN32) +// Define _*dsign before including cmath because _*dsign is used by signbit +// defined in UCRT headers. Using before adding device side declarations is +// illegal. +extern "C" __attribute__((sycl_device_only, always_inline)) int +_fdsign(float x) { + return __builtin_signbit(x); +} +extern "C" __attribute__((sycl_device_only, always_inline)) int +_dsign(double x) { + return __builtin_signbit(x); +} +#endif // __SYCL_DEVICE_ONLY__ && _WIN32 + // Include real STL header - the next one from the include search // directories. #if defined(__has_include_next) diff --git a/sycl/include/sycl/stl_wrappers/math.h b/sycl/include/sycl/stl_wrappers/math.h deleted file mode 100644 index 8a6626260d940..0000000000000 --- a/sycl/include/sycl/stl_wrappers/math.h +++ /dev/null @@ -1,34 +0,0 @@ -//==- math.h -------------------------------------------------------------0-==// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#pragma once - -#if defined(__SYCL_DEVICE_ONLY__) && defined(_WIN32) -// Define _*dsign before including math.h because _*dsign is used by signbit -// defined in UCRT headers. -extern "C" __attribute__((sycl_device_only, always_inline)) int -_fdsign(float x) { - return __builtin_signbit(x); -} -extern "C" __attribute__((sycl_device_only, always_inline)) int -_dsign(double x) { - return __builtin_signbit(x); -} -#endif // __SYCL_DEVICE_ONLY__ && _WIN32 - -#if defined(__has_include_next) -// GCC/clang support go through this path. -#include_next -#else -// MSVC doesn't support "#include_next", so we have to be creative. -// Our header is located in "stl_wrappers/" directory so it won't be picked by -// the following include. MSVC's installation, on the other hand, has the layout -// where the following would result in the header we want. This is obviously -// hacky, but the best we can do... -#include <../include/math.h> -#endif From aae9e8b70f029556d421e0764d725a01480958e7 Mon Sep 17 00:00:00 2001 From: Alexey Bader Date: Tue, 5 Aug 2025 17:36:01 -0700 Subject: [PATCH 4/5] Move _fdsign/_dsign definitions from cmath to __sycl_cmath_wrapper_impl.hpp to avoid re-definition. --- .../stl_wrappers/__sycl_cmath_wrapper_impl.hpp | 2 ++ sycl/include/sycl/stl_wrappers/cmath | 17 +++++++---------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/sycl/include/sycl/stl_wrappers/__sycl_cmath_wrapper_impl.hpp b/sycl/include/sycl/stl_wrappers/__sycl_cmath_wrapper_impl.hpp index 6fcea22496236..4dee54a8006c5 100644 --- a/sycl/include/sycl/stl_wrappers/__sycl_cmath_wrapper_impl.hpp +++ b/sycl/include/sycl/stl_wrappers/__sycl_cmath_wrapper_impl.hpp @@ -502,6 +502,8 @@ __SYCL_DEVICE_C short _FExp(float *px, float y, short eoff) { return exp(*px) * ldexp(y, eoff); } __SYCL_DEVICE_C float _hypotf(float x, float y) { return hypotf(x, y); } +__SYCL_DEVICE_C int _fdsign(float x) { return __builtin_signbit(x); } +__SYCL_DEVICE_C int _dsign(double x) { return __builtin_signbit(x); } #endif // defined(_WIN32) #undef __SYCL_SPIRV_MAP_BINARY_C diff --git a/sycl/include/sycl/stl_wrappers/cmath b/sycl/include/sycl/stl_wrappers/cmath index 10f6c84c381f4..b411eb7e81e81 100644 --- a/sycl/include/sycl/stl_wrappers/cmath +++ b/sycl/include/sycl/stl_wrappers/cmath @@ -9,18 +9,15 @@ #pragma once #if defined(__SYCL_DEVICE_ONLY__) && defined(_WIN32) -// Define _*dsign before including cmath because _*dsign is used by signbit -// defined in UCRT headers. Using before adding device side declarations is -// illegal. +#if defined(__NVPTX__) || defined(__AMDGCN__) +// Forward declare device _*dsign functions before including cmath to enable +// compilation of math functions defined in UCRT headers. extern "C" __attribute__((sycl_device_only, always_inline)) int -_fdsign(float x) { - return __builtin_signbit(x); -} +_fdsign(float x); extern "C" __attribute__((sycl_device_only, always_inline)) int -_dsign(double x) { - return __builtin_signbit(x); -} -#endif // __SYCL_DEVICE_ONLY__ && _WIN32 +_dsign(double x); +#endif // defined(__NVPTX__) || defined(__AMDGCN__) +#endif // defined(__SYCL_DEVICE_ONLY__) && defined(_WIN32) // Include real STL header - the next one from the include search // directories. From 6bd90ff92be4d7277bf08e8ea9c9b43b5bbf7e55 Mon Sep 17 00:00:00 2001 From: Alexey Bader Date: Tue, 5 Aug 2025 17:49:57 -0700 Subject: [PATCH 5/5] Mark __sycl_cmath_wrapper_impl.hpp as expected to fail. New version uses macro defined by cmath, which is expected to be included before using __sycl_cmath_wrapper_impl.hpp. --- sycl/test/self-contained-headers/lit.local.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sycl/test/self-contained-headers/lit.local.cfg b/sycl/test/self-contained-headers/lit.local.cfg index 30a1d3e1a195c..767afc0f1b74e 100644 --- a/sycl/test/self-contained-headers/lit.local.cfg +++ b/sycl/test/self-contained-headers/lit.local.cfg @@ -7,4 +7,8 @@ config.test_format = SYCLHeadersTest() # standalone. `os.path.join` is required here so the filtering works # cross-platform config.sycl_headers_xfail = [ + # FIXME: remove this rule when the header is moved to the clang project + os.path.join( + "sycl", "stl_wrappers", "__sycl_cmath_wrapper_impl.hpp" + ), ]