diff --git a/libdevice/crt_wrapper.cpp b/libdevice/crt_wrapper.cpp index 230d6dc2d9754..34b710fe94bc0 100644 --- a/libdevice/crt_wrapper.cpp +++ b/libdevice/crt_wrapper.cpp @@ -13,6 +13,17 @@ DEVICE_EXTERN_C void *memcpy(void *dest, const void *src, size_t n) { return __devicelib_memcpy(dest, src, n); } + +DEVICE_EXTERN_C +void *memset(void *dest, int c, size_t n) { + return __devicelib_memset(dest, c, n); +} + +DEVICE_EXTERN_C +int memcmp(const void *s1, const void *s2, size_t n) { + return __devicelib_memcmp(s1, s2, n); +} + #if defined(_WIN32) // Truncates a wide (16 or 32 bit) string (wstr) into an ASCII string (str). // Any non-ASCII characters are replaced by question mark '?'. diff --git a/libdevice/fallback-cstring.cpp b/libdevice/fallback-cstring.cpp index 2c54b3f63fe83..e2d16c0622741 100644 --- a/libdevice/fallback-cstring.cpp +++ b/libdevice/fallback-cstring.cpp @@ -7,9 +7,83 @@ //===----------------------------------------------------------------------===// #include "wrapper.h" +#include #ifdef __SPIR__ +DEVICE_EXTERN_C void *__devicelib_memcpy(void *dest, const void *src, size_t n) { return __builtin_memcpy(dest, src, n); } + +DEVICE_EXTERN_C +void *__devicelib_memset(void *dest, int c, size_t n) { + return __builtin_memset(dest, c, n); +} + +static int __devicelib_memcmp_uint8_aligned(const void *s1, const void *s2, + size_t n) { + const uint8_t *s1_uint8_ptr = reinterpret_cast(s1); + const uint8_t *s2_uint8_ptr = reinterpret_cast(s2); + while (n > 0) { + if (*s1_uint8_ptr == *s2_uint8_ptr) { + s1_uint8_ptr++; + s2_uint8_ptr++; + n--; + } else { + return *s1_uint8_ptr - *s2_uint8_ptr; + } + } + + return 0; +} + +static int __devicelib_memcmp_uint32_aligned(const void *s1, const void *s2, + size_t n) { + const uint32_t *s1_uint32_ptr = reinterpret_cast(s1); + const uint32_t *s2_uint32_ptr = reinterpret_cast(s2); + while (n >= sizeof(uint32_t)) { + if (*s1_uint32_ptr == *s2_uint32_ptr) { + s1_uint32_ptr++; + s2_uint32_ptr++; + n -= sizeof(uint32_t); + } else { + n = sizeof(uint32_t); + break; + } + } + + return (n == 0) ? 0 + : __devicelib_memcmp_uint8_aligned(s1_uint32_ptr, + s2_uint32_ptr, n); +} + +DEVICE_EXTERN_C +int __devicelib_memcmp(const void *s1, const void *s2, size_t n) { + if (s1 == s2 || n == 0) + return 0; + + size_t s1_uint32_mod = + reinterpret_cast(s1) % alignof(uint32_t); + size_t s2_uint32_mod = + reinterpret_cast(s2) % alignof(uint32_t); + + if (s1_uint32_mod != s2_uint32_mod) + return __devicelib_memcmp_uint8_aligned(s1, s2, n); + + if (s1_uint32_mod == 0) + return __devicelib_memcmp_uint32_aligned(s1, s2, n); + + size_t head_ua_len = sizeof(uint32_t) - s1_uint32_mod; + int head_cmp = __devicelib_memcmp_uint8_aligned(s1, s2, head_ua_len); + if (head_cmp == 0) { + const uint8_t *s1_aligned_ptr = reinterpret_cast(s1); + const uint8_t *s2_aligned_ptr = reinterpret_cast(s2); + s1_aligned_ptr += head_ua_len; + s2_aligned_ptr += head_ua_len; + return __devicelib_memcmp_uint32_aligned(s1_aligned_ptr, s2_aligned_ptr, + n - head_ua_len); + } + + return head_cmp; +} #endif // __SPIR__ diff --git a/libdevice/wrapper.h b/libdevice/wrapper.h index cd143c08bc395..75d47f7f98afb 100644 --- a/libdevice/wrapper.h +++ b/libdevice/wrapper.h @@ -21,6 +21,10 @@ DEVICE_EXTERN_C void *__devicelib_memcpy(void *dest, const void *src, size_t n); DEVICE_EXTERN_C +void *__devicelib_memset(void *dest, int c, size_t n); +DEVICE_EXTERN_C +int __devicelib_memcmp(const void *s1, const void *s2, size_t n); +DEVICE_EXTERN_C void __devicelib_assert_fail(const char *expr, const char *file, int32_t line, const char *func, uint64_t gid0, uint64_t gid1, uint64_t gid2, uint64_t lid0, uint64_t lid1, diff --git a/llvm/tools/sycl-post-link/SYCLDeviceLibReqMask.cpp b/llvm/tools/sycl-post-link/SYCLDeviceLibReqMask.cpp index 80f197ff8d022..c53324a63c625 100644 --- a/llvm/tools/sycl-post-link/SYCLDeviceLibReqMask.cpp +++ b/llvm/tools/sycl-post-link/SYCLDeviceLibReqMask.cpp @@ -159,6 +159,8 @@ SYCLDeviceLibFuncMap SDLMap = { {"__devicelib_ctan", DeviceLibExt::cl_intel_devicelib_complex_fp64}, {"__devicelib_ctanh", DeviceLibExt::cl_intel_devicelib_complex_fp64}, {"__devicelib_memcpy", DeviceLibExt::cl_intel_devicelib_cstring}, + {"__devicelib_memset", DeviceLibExt::cl_intel_devicelib_cstring}, + {"__devicelib_memcmp", DeviceLibExt::cl_intel_devicelib_cstring}, }; // Each fallback device library corresponds to one bit in "require mask" which diff --git a/sycl/doc/extensions/C-CXX-StandardLibrary/C-CXX-StandardLibrary.rst b/sycl/doc/extensions/C-CXX-StandardLibrary/C-CXX-StandardLibrary.rst index 9e127541f4761..621e2bf52ec58 100644 --- a/sycl/doc/extensions/C-CXX-StandardLibrary/C-CXX-StandardLibrary.rst +++ b/sycl/doc/extensions/C-CXX-StandardLibrary/C-CXX-StandardLibrary.rst @@ -78,6 +78,9 @@ List of supported functions from C standard library: - casinf, casin (from ) - cacosf, cacos (from ) - catanf, catan (from ) + - memcpy (from ) + - memset (from ) + - memcmp (from ) All functions are grouped into different device libraries based on functionalities. C and C++ standard library groups functions and diff --git a/sycl/doc/extensions/C-CXX-StandardLibrary/DeviceLibExtensions.rst b/sycl/doc/extensions/C-CXX-StandardLibrary/DeviceLibExtensions.rst index b411710b773bd..5e50f9a0676b2 100644 --- a/sycl/doc/extensions/C-CXX-StandardLibrary/DeviceLibExtensions.rst +++ b/sycl/doc/extensions/C-CXX-StandardLibrary/DeviceLibExtensions.rst @@ -229,3 +229,19 @@ Those __devicelib_* functions have the same argument type and return type as cor complex math functions from , please refer to ISO/IEC 14882:2011 for details. The "double __complex__" type is C99 complex type and it is an alias to "struct {double, double}" in LLVM IR and SPIR-V. + +cl_intel_devicelib_cstring +========================== + +.. code: + void *__devicelib_memcpy(void *dest, const void *src, size_t n); + void *__devicelib_memset(void *dest, int c, size_t n); + int __devicelib_memcmp(const void *s1, const void *s2, size_t n); + +Semantic: +Those __devicelib_* functions perform the same operation as the corresponding C string +library functions. + +Arguments: +Those __devicelib_* functions have the same argument type and return type as corresponding +string functions from , please refer to ISO/IEC 14882:2011 for details. diff --git a/sycl/include/CL/sycl/builtins.hpp b/sycl/include/CL/sycl/builtins.hpp index 5b794b8a986e6..c82433c61c091 100644 --- a/sycl/include/CL/sycl/builtins.hpp +++ b/sycl/include/CL/sycl/builtins.hpp @@ -1638,6 +1638,8 @@ extern SYCL_EXTERNAL double ldexp(double x, int exp); extern SYCL_EXTERNAL double hypot(double x, double y); extern SYCL_EXTERNAL void *memcpy(void *dest, const void *src, size_t n); +extern SYCL_EXTERNAL void *memset(void *dest, int c, size_t n); +extern SYCL_EXTERNAL int memcmp(const void *s1, const void *s2, size_t n); } #ifdef __GLIBC__ extern "C" {