From f81f0e5abbd52705116901237b9f6c694e2fbc8f Mon Sep 17 00:00:00 2001 From: Nicolas Miller Date: Wed, 16 Jul 2025 17:26:36 +0100 Subject: [PATCH 1/2] [SYCL] Refactor cmath wrapper templates * Include ``, this was working because `` pulls it in but this is cleaner. * Use C++14 and C++17 `_v` and `_t` helpers. * Switch to variadic template for `__sycl_promote`, using C++17 fold expressions. With this patch the header now require C++17 support to compile. Which is fine since it's the minimum requirement for SYCL 2020, and this header is only compiled on the device side which is always handled by clang, so there shouldn't be any support issues. --- .../__sycl_cmath_wrapper_impl.hpp | 75 +++++++------------ 1 file changed, 29 insertions(+), 46 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 31bdaf236d9b6..741ffbc089800 100644 --- a/sycl/include/sycl/stl_wrappers/__sycl_cmath_wrapper_impl.hpp +++ b/sycl/include/sycl/stl_wrappers/__sycl_cmath_wrapper_impl.hpp @@ -19,25 +19,27 @@ #define __SYCL_DEVICE_C \ extern "C" __attribute__((sycl_device_only, always_inline)) +// For std::enable_if, std::is_integral, std::is_floating_point, std::is_same, +// and std::conjunction +#include + // Promotion templates: the C++ standard library provides overloads that allow // arguments of math functions to be promoted. Any floating-point argument is // allowed to accept any integer type, which should then be promoted to double. // When multiple floating point arguments are available passing arguments with // different precision should promote to the larger type. The template helpers // below provide the machinery to define these promoting overloads. -template ::value || - std::is_floating_point::value)> +template || std::is_floating_point_v)> struct __sycl_promote { private: // Integer types are promoted to double. template - static typename std::enable_if::value, double>::type - test(); + static std::enable_if_t, double> test(); // Floating point types are used as-is. template - static typename std::enable_if::value, U>::type - test(); + static std::enable_if_t, U> test(); public: // We rely on dummy templated methods and decltype to select the right type @@ -48,29 +50,17 @@ struct __sycl_promote { // Variant without ::type to allow SFINAE for non-promotable types. template struct __sycl_promote {}; -// With a single paramter we only need to promote integers. -template -using __sycl_promote_1 = std::enable_if::value, double>; - // With two or three parameters we need to promote integers and possibly // floating point types. We rely on operator+ with decltype to deduce the // overall promotion type. This is only needed if at least one of the parameter // is an integer, or if there's multiple different floating point types. -template -using __sycl_promote_2 = - std::enable_if::value || std::is_integral::value || - std::is_integral::value, - decltype(typename __sycl_promote::type(0) + - typename __sycl_promote::type(0))>; - -template -using __sycl_promote_3 = - std::enable_if::value && std::is_same::value) || - std::is_integral::value || - std::is_integral::value || std::is_integral::value, - decltype(typename __sycl_promote::type(0) + - typename __sycl_promote::type(0) + - typename __sycl_promote::type(0))>; +template +using __sycl_promote_t = + std::enable_if_t...> || + std::is_integral_v || + (std::is_integral_v || ...), + decltype((typename __sycl_promote::type(0) + ... + + typename __sycl_promote::type(0)))>; // For each math built-in we need to define float and double overloads, an // extern "C" float variant with the 'f' suffix, and a version that promotes @@ -85,8 +75,7 @@ using __sycl_promote_3 = __SYCL_DEVICE_C float NAME##f(float x) { return __spirv_ocl_##NAME(x); } \ __SYCL_DEVICE float NAME(float x) { return __spirv_ocl_##NAME(x); } \ __SYCL_DEVICE double NAME(double x) { return __spirv_ocl_##NAME(x); } \ - template \ - __SYCL_DEVICE typename __sycl_promote_1::type NAME(T x) { \ + template __SYCL_DEVICE __sycl_promote_t NAME(T x) { \ return __spirv_ocl_##NAME((double)x); \ } @@ -101,8 +90,8 @@ using __sycl_promote_3 = return __spirv_ocl_##NAME(x, y); \ } \ template \ - __SYCL_DEVICE __sycl_promote_2::type NAME(T x, U y) { \ - typedef typename __sycl_promote_2::type type; \ + __SYCL_DEVICE __sycl_promote_t NAME(T x, U y) { \ + typedef __sycl_promote_t type; \ return __spirv_ocl_##NAME((type)x, (type)y); \ } @@ -127,8 +116,7 @@ __SYCL_DEVICE double abs(double x) { return x < 0 ? -x : x; } __SYCL_DEVICE float fabs(float x) { return x < 0 ? -x : x; } __SYCL_DEVICE_C float fabsf(float x) { return x < 0 ? -x : x; } __SYCL_DEVICE double fabs(double x) { return x < 0 ? -x : x; } -template -__SYCL_DEVICE typename __sycl_promote_1::type fabs(T x) { +template __SYCL_DEVICE __sycl_promote_t fabs(T x) { return x < 0 ? -x : x; } @@ -145,8 +133,8 @@ __SYCL_DEVICE double remquo(double x, double y, int *q) { return __spirv_ocl_remquo(x, y, q); } template -__SYCL_DEVICE typename __sycl_promote_2::type remquo(T x, U y, int *q) { - typedef typename __sycl_promote_2::type type; +__SYCL_DEVICE __sycl_promote_t remquo(T x, U y, int *q) { + typedef __sycl_promote_t type; return __spirv_ocl_remquo((type)x, (type)y, q); } @@ -160,8 +148,8 @@ __SYCL_DEVICE double fma(double x, double y, double z) { return __spirv_ocl_fma(x, y, z); } template -__SYCL_DEVICE typename __sycl_promote_3::type fma(T x, U y, V z) { - typedef typename __sycl_promote_3::type type; +__SYCL_DEVICE __sycl_promote_t fma(T x, U y, V z) { + typedef __sycl_promote_t type; return __spirv_ocl_fma((type)x, (type)y, (type)z); } @@ -256,8 +244,7 @@ __SYCL_DEVICE float frexp(float x, int *exp) { __SYCL_DEVICE double frexp(double x, int *exp) { return __spirv_ocl_frexp(x, exp); } -template -__SYCL_DEVICE typename __sycl_promote_1::type frexp(T x, int *exp) { +template __SYCL_DEVICE __sycl_promote_t frexp(T x, int *exp) { return __spirv_ocl_frexp((double)x, exp); } @@ -270,8 +257,7 @@ __SYCL_DEVICE float ldexp(float x, int exp) { __SYCL_DEVICE double ldexp(double x, int exp) { return __spirv_ocl_ldexp(x, exp); } -template -__SYCL_DEVICE typename __sycl_promote_1::type ldexp(T x, int exp) { +template __SYCL_DEVICE __sycl_promote_t ldexp(T x, int exp) { return __spirv_ocl_ldexp((double)x, exp); } @@ -286,7 +272,7 @@ __SYCL_DEVICE double modf(double x, double *intpart) { } // modf only supports integer x when the intpart is double. template -__SYCL_DEVICE typename __sycl_promote_1::type modf(T x, double *intpart) { +__SYCL_DEVICE __sycl_promote_t modf(T x, double *intpart) { return __spirv_ocl_modf((double)x, intpart); } @@ -299,8 +285,7 @@ __SYCL_DEVICE float scalbn(float x, int exp) { __SYCL_DEVICE double scalbn(double x, int exp) { return __spirv_ocl_ldexp(x, exp); } -template -__SYCL_DEVICE typename __sycl_promote_1::type scalbn(T x, int exp) { +template __SYCL_DEVICE __sycl_promote_t scalbn(T x, int exp) { return __spirv_ocl_ldexp((double)x, exp); } @@ -313,8 +298,7 @@ __SYCL_DEVICE float scalbln(float x, long exp) { __SYCL_DEVICE double scalbln(double x, long exp) { return __spirv_ocl_ldexp(x, (int)exp); } -template -__SYCL_DEVICE typename __sycl_promote_1::type scalbln(T x, long exp) { +template __SYCL_DEVICE __sycl_promote_t scalbln(T x, long exp) { return __spirv_ocl_ldexp((double)x, (int)exp); } @@ -323,8 +307,7 @@ __SYCL_DEVICE int ilogb(float x) { return __spirv_ocl_ilogb(x); } __SYCL_DEVICE int ilogb(double x) { return __spirv_ocl_ilogb(x); } // ilogb needs a special template since its signature doesn't include the // promoted type anywhere, so it needs to be specialized differently. -template ::value, - bool>::type = true> +template , bool> = true> __SYCL_DEVICE int ilogb(T x) { return __spirv_ocl_ilogb((double)x); } From 26b2401b95733d0f11bb9f333bee9ebe27387e40 Mon Sep 17 00:00:00 2001 From: Nicolas Miller Date: Wed, 16 Jul 2025 18:05:45 +0100 Subject: [PATCH 2/2] [SYCL] Switch from typedef to using in cmath wrapper --- .../include/sycl/stl_wrappers/__sycl_cmath_wrapper_impl.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 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 741ffbc089800..a888058bd3715 100644 --- a/sycl/include/sycl/stl_wrappers/__sycl_cmath_wrapper_impl.hpp +++ b/sycl/include/sycl/stl_wrappers/__sycl_cmath_wrapper_impl.hpp @@ -91,7 +91,7 @@ using __sycl_promote_t = } \ template \ __SYCL_DEVICE __sycl_promote_t NAME(T x, U y) { \ - typedef __sycl_promote_t type; \ + using type = __sycl_promote_t; \ return __spirv_ocl_##NAME((type)x, (type)y); \ } @@ -134,7 +134,7 @@ __SYCL_DEVICE double remquo(double x, double y, int *q) { } template __SYCL_DEVICE __sycl_promote_t remquo(T x, U y, int *q) { - typedef __sycl_promote_t type; + using type = __sycl_promote_t; return __spirv_ocl_remquo((type)x, (type)y, q); } @@ -149,7 +149,7 @@ __SYCL_DEVICE double fma(double x, double y, double z) { } template __SYCL_DEVICE __sycl_promote_t fma(T x, U y, V z) { - typedef __sycl_promote_t type; + using type = __sycl_promote_t; return __spirv_ocl_fma((type)x, (type)y, (type)z); }