Skip to content

Commit b53f646

Browse files
authored
[SYCL][NFCI] Move abs and div to cstdlib header (#19671)
The C++ specification defines that `abs(<integer>)` and `div` functions are provided by `cstdlib`. Whether they're available or not after `#include <cmath>` is an implementation detail of the underlying C++ standard library implementation. With this change we move the definition to the correct wrapper file aligned with the C++ specification.
1 parent dbe6a50 commit b53f646

File tree

12 files changed

+97
-110
lines changed

12 files changed

+97
-110
lines changed

libdevice/cmath_wrapper.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,6 @@
1010

1111
#if defined(__SPIR__) || defined(__SPIRV__)
1212

13-
DEVICE_EXTERN_C_INLINE
14-
int abs(int x) { return __devicelib_abs(x); }
15-
16-
DEVICE_EXTERN_C_INLINE
17-
long int labs(long int x) { return __devicelib_labs(x); }
18-
19-
DEVICE_EXTERN_C_INLINE
20-
long long int llabs(long long int x) { return __devicelib_llabs(x); }
21-
2213
DEVICE_EXTERN_C_INLINE
2314
float fabsf(float x) { return __devicelib_fabsf(x); }
2415

@@ -51,15 +42,6 @@ float rsqrtf(float x) { return __devicelib_rsqrtf(x); }
5142
DEVICE_EXTERN_C_INLINE
5243
float exp10f(float x) { return __devicelib_exp10f(x); }
5344

54-
DEVICE_EXTERN_C_INLINE
55-
div_t div(int x, int y) { return __devicelib_div(x, y); }
56-
57-
DEVICE_EXTERN_C_INLINE
58-
ldiv_t ldiv(long x, long y) { return __devicelib_ldiv(x, y); }
59-
60-
DEVICE_EXTERN_C_INLINE
61-
lldiv_t lldiv(long long x, long long y) { return __devicelib_lldiv(x, y); }
62-
6345
DEVICE_EXTERN_C_INLINE
6446
float roundf(float x) { return __devicelib_roundf(x); }
6547

libdevice/device_math.h

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,6 @@
1414
defined(__AMDGCN__)
1515
#include <cstdint>
1616

17-
typedef struct {
18-
int32_t quot;
19-
int32_t rem;
20-
} __devicelib_div_t_32;
21-
22-
typedef struct {
23-
int64_t quot;
24-
int64_t rem;
25-
} __devicelib_div_t_64;
26-
27-
typedef __devicelib_div_t_32 div_t;
28-
#ifdef _WIN32
29-
typedef __devicelib_div_t_32 ldiv_t;
30-
#else
31-
typedef __devicelib_div_t_64 ldiv_t;
32-
#endif
33-
typedef __devicelib_div_t_64 lldiv_t;
34-
35-
DEVICE_EXTERN_C
36-
int __devicelib_abs(int x);
37-
38-
DEVICE_EXTERN_C
39-
long int __devicelib_labs(long int x);
40-
41-
DEVICE_EXTERN_C
42-
long long int __devicelib_llabs(long long int x);
43-
4417
DEVICE_EXTERN_C
4518
float __devicelib_fabsf(float x);
4619

@@ -107,15 +80,6 @@ double __devicelib_exp10(double x);
10780
DEVICE_EXTERN_C
10881
float __devicelib_exp10f(float x);
10982

110-
DEVICE_EXTERN_C
111-
div_t __devicelib_div(int x, int y);
112-
113-
DEVICE_EXTERN_C
114-
ldiv_t __devicelib_ldiv(long int x, long int y);
115-
116-
DEVICE_EXTERN_C
117-
lldiv_t __devicelib_lldiv(long long int x, long long int y);
118-
11983
DEVICE_EXTERN_C
12084
double __devicelib_round(double x);
12185

libdevice/fallback-cmath.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,6 @@
1616
// TODO: generate the DeviceLibFuncMap in sycl-post-link.cpp automatically
1717
// during the build based on libdevice to avoid manually sync.
1818

19-
DEVICE_EXTERN_C_INLINE
20-
int __devicelib_abs(int x) { return x < 0 ? -x : x; }
21-
22-
DEVICE_EXTERN_C_INLINE
23-
long int __devicelib_labs(long int x) { return x < 0 ? -x : x; }
24-
25-
DEVICE_EXTERN_C_INLINE
26-
long long int __devicelib_llabs(long long int x) { return x < 0 ? -x : x; }
27-
2819
DEVICE_EXTERN_C_INLINE
2920
float __devicelib_fabsf(float x) { return x < 0 ? -x : x; }
3021

@@ -62,15 +53,6 @@ float __devicelib_rsqrtf(float x) { return __spirv_ocl_rsqrt(x); }
6253
DEVICE_EXTERN_C_INLINE
6354
float __devicelib_exp10f(float x) { return __spirv_ocl_exp10(x); }
6455

65-
DEVICE_EXTERN_C_INLINE
66-
div_t __devicelib_div(int x, int y) { return {x / y, x % y}; }
67-
68-
DEVICE_EXTERN_C_INLINE
69-
ldiv_t __devicelib_ldiv(long x, long y) { return {x / y, x % y}; }
70-
71-
DEVICE_EXTERN_C_INLINE
72-
lldiv_t __devicelib_lldiv(long long x, long long y) { return {x / y, x % y}; }
73-
7456
DEVICE_EXTERN_C_INLINE
7557
float __devicelib_scalbnf(float x, int n) { return __spirv_ocl_ldexp(x, n); }
7658

sycl/include/sycl/stl_wrappers/__sycl_cmath_wrapper_impl.hpp

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -112,19 +112,6 @@ using __sycl_promote_t =
112112
return __spirv_ocl_##NAME((type)x, (type)y); \
113113
}
114114

115-
/// <cstdlib>
116-
// FIXME: Move this to a cstdlib fallback header.
117-
118-
__SYCL_DEVICE_C div_t div(int x, int y) { return {x / y, x % y}; }
119-
__SYCL_DEVICE_C ldiv_t ldiv(long x, long y) { return {x / y, x % y}; }
120-
__SYCL_DEVICE_C lldiv_t lldiv(long long x, long long y) {
121-
return {x / y, x % y};
122-
}
123-
124-
__SYCL_DEVICE int abs(int n) { return n < 0 ? -n : n; }
125-
__SYCL_DEVICE_C long labs(long n) { return n < 0 ? -n : n; }
126-
__SYCL_DEVICE_C long long llabs(long long n) { return n < 0 ? -n : n; }
127-
128115
/// Basic operations
129116
//
130117

@@ -299,20 +286,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
299286
#endif
300287
#endif
301288

302-
// <cstdlib>
303-
using ::abs;
304-
__SYCL_DEVICE long abs(long n) { return n < 0 ? -n : n; }
305-
__SYCL_DEVICE long long abs(long long n) { return n < 0 ? -n : n; }
306-
307-
using ::div;
308-
__SYCL_DEVICE ldiv_t div(long x, long y) { return {x / y, x % y}; }
309-
__SYCL_DEVICE lldiv_t div(long long x, long long y) { return {x / y, x % y}; }
310-
311-
using ::labs;
312-
using ::ldiv;
313-
using ::llabs;
314-
using ::lldiv;
315-
316289
// Basic operations
317290
// using ::abs is already pulled in above
318291
__SYCL_DEVICE float abs(float x) { return x < 0 ? -x : x; }

sycl/include/sycl/stl_wrappers/cmath

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,6 @@
3232

3333
#ifdef __SYCL_DEVICE_ONLY__
3434
extern "C" {
35-
extern __DPCPP_SYCL_EXTERNAL_LIBC int abs(int x);
36-
extern __DPCPP_SYCL_EXTERNAL_LIBC long int labs(long int x);
37-
extern __DPCPP_SYCL_EXTERNAL_LIBC long long int llabs(long long int x);
38-
39-
extern __DPCPP_SYCL_EXTERNAL_LIBC div_t div(int x, int y);
40-
extern __DPCPP_SYCL_EXTERNAL_LIBC ldiv_t ldiv(long int x, long int y);
41-
extern __DPCPP_SYCL_EXTERNAL_LIBC lldiv_t lldiv(long long int x, long long int y);
4235
extern __DPCPP_SYCL_EXTERNAL_LIBC float scalbnf(float x, int n);
4336
extern __DPCPP_SYCL_EXTERNAL_LIBC double scalbn(double x, int n);
4437
extern __DPCPP_SYCL_EXTERNAL_LIBC float logf(float x);
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//==- cstdlib --------------------------------------------------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#pragma once
10+
11+
// Include real STL <cstdlib> header - the next one from the include search
12+
// directories.
13+
#if defined(__has_include_next)
14+
// GCC/clang support go through this path.
15+
#include_next <cstdlib>
16+
#else
17+
// MSVC doesn't support "#include_next", so we have to be creative.
18+
// Our header is located in "stl_wrappers/cstdlib" so it won't be picked by the
19+
// following include. MSVC's installation, on the other hand, has the layout
20+
// where the following would result in the <cstdlib> we want. This is obviously
21+
// hacky, but the best we can do...
22+
#include <../include/cstdlib>
23+
#endif
24+
25+
#ifdef __SYCL_DEVICE_ONLY__
26+
extern "C" {
27+
[[clang::sycl_device_only, clang::always_inline]] div_t div(int x, int y) { return {x / y, x % y}; }
28+
[[clang::sycl_device_only, clang::always_inline]] ldiv_t ldiv(long x, long y) { return {x / y, x % y}; }
29+
[[clang::sycl_device_only, clang::always_inline]] lldiv_t lldiv(long long x, long long y) { return {x / y, x % y}; }
30+
31+
[[clang::sycl_device_only, clang::always_inline]] int abs(int n) { return n < 0 ? -n : n; }
32+
[[clang::sycl_device_only, clang::always_inline]] long labs(long n) { return n < 0 ? -n : n; }
33+
[[clang::sycl_device_only, clang::always_inline]] long long llabs(long long n) { return n < 0 ? -n : n; }
34+
}
35+
36+
#ifdef _LIBCPP_BEGIN_NAMESPACE_STD
37+
_LIBCPP_BEGIN_NAMESPACE_STD
38+
#else
39+
namespace std {
40+
#ifdef _GLIBCXX_BEGIN_NAMESPACE_VERSION
41+
_GLIBCXX_BEGIN_NAMESPACE_VERSION
42+
#endif
43+
#endif
44+
45+
using ::div;
46+
[[clang::sycl_device_only, clang::always_inline]] ldiv_t div(long x, long y) { return {x / y, x % y}; }
47+
[[clang::sycl_device_only, clang::always_inline]] lldiv_t div(long long x, long long y) { return {x / y, x % y}; }
48+
using ::ldiv;
49+
using ::lldiv;
50+
51+
using ::abs;
52+
[[clang::sycl_device_only, clang::always_inline]] long abs(long n) { return n < 0 ? -n : n; }
53+
[[clang::sycl_device_only, clang::always_inline]] long long abs(long long n) { return n < 0 ? -n : n; }
54+
using ::labs;
55+
using ::llabs;
56+
57+
#ifdef _LIBCPP_END_NAMESPACE_STD
58+
_LIBCPP_END_NAMESPACE_STD
59+
#else
60+
#ifdef _GLIBCXX_BEGIN_NAMESPACE_VERSION
61+
_GLIBCXX_END_NAMESPACE_VERSION
62+
#endif
63+
} // namespace std
64+
#endif
65+
#endif // __SYCL_DEVICE_ONLY__

sycl/test-e2e/DeviceLib/cmath_test.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "math_utils.hpp"
1616
#include <cmath>
1717
#include <cstdint>
18+
#include <cstdlib>
1819
#include <iostream>
1920
#include <std/experimental/simd.hpp>
2021
#include <sycl/detail/core.hpp>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %clangxx -fsycl -fsyntax-only %s
2+
3+
#include <type_traits>
4+
5+
#include <cstdlib>
6+
7+
int i = 1;
8+
long l = 1;
9+
long long ll = 1;
10+
11+
// Unqualified calls should resolve to the `int` overloads
12+
static_assert(std::is_same_v<decltype(abs(i)), int>);
13+
static_assert(std::is_same_v<decltype(div(i, i)), div_t>);
14+
// NOTE: Windows Universal C Runtime defines C++ overloads for `long` and
15+
// `long long` types in global name space. See
16+
// https://github.com/huangqinjin/ucrt/blob/d6e817a4cc90f6f1fe54f8a0aa4af4fff0bb647d/include/stdlib.h#L360-L383.
17+
#ifndef _WIN32
18+
static_assert(std::is_same_v<decltype(abs(l)), int>);
19+
static_assert(std::is_same_v<decltype(abs(ll)), int>);
20+
static_assert(std::is_same_v<decltype(div(i, l)), div_t>);
21+
static_assert(std::is_same_v<decltype(div(i, ll)), div_t>);
22+
static_assert(std::is_same_v<decltype(div(l, i)), div_t>);
23+
static_assert(std::is_same_v<decltype(div(l, l)), div_t>);
24+
static_assert(std::is_same_v<decltype(div(l, ll)), div_t>);
25+
static_assert(std::is_same_v<decltype(div(ll, i)), div_t>);
26+
static_assert(std::is_same_v<decltype(div(ll, l)), div_t>);
27+
static_assert(std::is_same_v<decltype(div(ll, ll)), div_t>);
28+
#endif // _WIN32

sycl/test/include_deps/sycl_accessor.hpp.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// CHECK-NEXT: detail/defines_elementary.hpp
1010
// CHECK-NEXT: buffer.hpp
1111
// CHECK-NEXT: backend_types.hpp
12+
// CHECK-NEXT: stl_wrappers/cstdlib
1213
// CHECK-NEXT: detail/array.hpp
1314
// CHECK-NEXT: exception.hpp
1415
// CHECK-NEXT: detail/export.hpp

sycl/test/include_deps/sycl_buffer.hpp.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// CHECK-NEXT: access/access.hpp
99
// CHECK-NEXT: detail/defines_elementary.hpp
1010
// CHECK-NEXT: backend_types.hpp
11+
// CHECK-NEXT: stl_wrappers/cstdlib
1112
// CHECK-NEXT: detail/array.hpp
1213
// CHECK-NEXT: exception.hpp
1314
// CHECK-NEXT: detail/export.hpp

0 commit comments

Comments
 (0)