diff --git a/sdk/lib/ucrt/inc/corecrt_internal_simd.h b/sdk/lib/ucrt/inc/corecrt_internal_simd.h index 01a92229438..4b5421f4f6e 100644 --- a/sdk/lib/ucrt/inc/corecrt_internal_simd.h +++ b/sdk/lib/ucrt/inc/corecrt_internal_simd.h @@ -19,22 +19,27 @@ #if defined _CRT_SIMD_SUPPORT_AVAILABLE #if defined(__clang__) -#define _UCRT_ENABLE_EXTENDED_ISA \ +#define _UCRT_ENABLE_SSE2 \ + _Pragma("clang attribute push(__attribute__((target(\"sse2\"))), apply_to=function)") +#define _UCRT_ENABLE_AVX2 \ _Pragma("clang attribute push(__attribute__((target(\"sse2,avx,avx2\"))), apply_to=function)") #define _UCRT_RESTORE_DEFAULT_ISA \ _Pragma("clang attribute pop") #elif defined(__GNUC__) -#define _UCRT_ENABLE_EXTENDED_ISA \ +#define _UCRT_ENABLE_SSE2 \ + _Pragma("GCC push_options") \ + _Pragma("GCC target(\"sse2\")") +#define _UCRT_ENABLE_AVX2 \ _Pragma("GCC push_options") \ _Pragma("GCC target(\"avx2\")") #define _UCRT_RESTORE_DEFAULT_ISA \ _Pragma("GCC pop_options") #else -#define _UCRT_ENABLE_EXTENDED_ISA +#define _UCRT_ENABLE_SSE2 +#define _UCRT_ENABLE_AVX2 #define _UCRT_RESTORE_DEFAULT_ISA #endif -_UCRT_ENABLE_EXTENDED_ISA extern "C" int __isa_available; @@ -70,6 +75,7 @@ _UCRT_ENABLE_EXTENDED_ISA }; +_UCRT_ENABLE_SSE2 template <> struct __crt_simd_cleanup_guard<__crt_simd_isa::sse2> @@ -120,7 +126,9 @@ _UCRT_ENABLE_EXTENDED_ISA } }; +_UCRT_RESTORE_DEFAULT_ISA +_UCRT_ENABLE_AVX2 template <> struct __crt_simd_cleanup_guard<__crt_simd_isa::avx2> diff --git a/sdk/lib/ucrt/string/string.cmake b/sdk/lib/ucrt/string/string.cmake index afd2ec57db6..6c80430c68c 100644 --- a/sdk/lib/ucrt/string/string.cmake +++ b/sdk/lib/ucrt/string/string.cmake @@ -57,6 +57,17 @@ list(APPEND UCRT_STRING_SOURCES string/wmemmove_s.cpp ) +# Special handling for GCC and Clang +if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + list(APPEND UCRT_STRING_SOURCES + string/strnlen-avx2.cpp + string/strnlen-sse2.cpp + ) + + set_source_files_properties(string/strnlen-sse2.cpp PROPERTIES COMPILE_OPTIONS "-msse2") + set_source_files_properties(string/strnlen-avx2.cpp PROPERTIES COMPILE_OPTIONS "-mavx2") +endif() + if(${ARCH} STREQUAL "i386") list(APPEND UCRT_STRING_ASM_SOURCES string/i386/_memicmp.s diff --git a/sdk/lib/ucrt/string/strnlen-avx2.cpp b/sdk/lib/ucrt/string/strnlen-avx2.cpp new file mode 100644 index 00000000000..4b94794d167 --- /dev/null +++ b/sdk/lib/ucrt/string/strnlen-avx2.cpp @@ -0,0 +1,29 @@ +// +// strnlen-avx2.cpp +// +// Copyright (c) Timo Kreuzer +// +// Explicit template instantiations for AVX2 str(n)len code +// + +#pragma GCC target("avx2") +#define _UCRT_BUILD_AVX2 +#include "strnlen.cpp" + +template +size_t __cdecl common_strnlen_simd( + uint8_t const* const string, + size_t const maximum_count + ) throw(); + +template +size_t __cdecl common_strnlen_simd( + uint16_t const* const string, + size_t const maximum_count + ) throw(); + +template +size_t __cdecl common_strnlen_simd( + uint16_t const* const string, + size_t const maximum_count + ) throw(); diff --git a/sdk/lib/ucrt/string/strnlen-sse2.cpp b/sdk/lib/ucrt/string/strnlen-sse2.cpp new file mode 100644 index 00000000000..8258bade2f9 --- /dev/null +++ b/sdk/lib/ucrt/string/strnlen-sse2.cpp @@ -0,0 +1,29 @@ +// +// strnlen-sse2.cpp +// +// Copyright (c) Timo Kreuzer +// +// Explicit template instantiations for SSE2 str(n)len code +// + +#pragma GCC target("sse2") +#define _UCRT_BUILD_SSE2 +#include "strnlen.cpp" + +template +size_t __cdecl common_strnlen_simd( + uint8_t const* const string, + size_t const maximum_count + ) throw(); + +template +size_t __cdecl common_strnlen_simd( + uint16_t const* const string, + size_t const maximum_count + ) throw(); + +template +size_t __cdecl common_strnlen_simd( + uint16_t const* const string, + size_t const maximum_count + ) throw(); diff --git a/sdk/lib/ucrt/string/strnlen.cpp b/sdk/lib/ucrt/string/strnlen.cpp index 302086cb9f9..024f98e9a42 100644 --- a/sdk/lib/ucrt/string/strnlen.cpp +++ b/sdk/lib/ucrt/string/strnlen.cpp @@ -21,14 +21,14 @@ -namespace -{ +//namespace // clang doesn't like this! +//{ enum strnlen_mode { bounded, // strnlen mode; maximum_count is respected unbounded, // strlen mode; maximum_count is ignored }; -} +//} // This function returns true if we have reached the end of the range to be // searched for a terminator. For the bounded strnlen functions, we must @@ -78,16 +78,18 @@ static __forceinline size_t __cdecl common_strnlen_c( #ifdef _CRT_SIMD_SUPPORT_AVAILABLE -_UCRT_ENABLE_EXTENDED_ISA template _Check_return_ _When_(maximum_count > _String_length_(string), _Post_satisfies_(return == _String_length_(string))) _When_(maximum_count <= _String_length_(string), _Post_satisfies_(return == maximum_count)) - static __inline size_t __cdecl common_strnlen_simd( + size_t __cdecl common_strnlen_simd( Element const* const string, size_t const maximum_count ) throw() +#if (defined(__GNUC__) || defined(__clang__)) && !defined(_UCRT_BUILD_SSE2) && !defined(_UCRT_BUILD_AVX2) + ; +#else { using traits = __crt_simd_traits; @@ -170,10 +172,12 @@ _UCRT_ENABLE_EXTENDED_ISA return static_cast(it - string); } -_UCRT_RESTORE_DEFAULT_ISA +#endif // (defined(__GNUC__) || defined(__clang__)) && !defined(_UCRT_BUILD_SSE2) && !defined(_UCRT_BUILD_AVX2) #endif // _CRT_SIMD_SUPPORT_AVAILABLE +#if !defined(_UCRT_BUILD_SSE2) && !defined(_UCRT_BUILD_AVX2) + template _Check_return_ _When_(maximum_count > _String_length_(string), _Post_satisfies_(return == _String_length_(string))) @@ -225,3 +229,4 @@ extern "C" size_t __cdecl wcslen( } #endif // _M_ARM64 +#endif // !defined(_UCRT_BUILD_SSE2) && !defined(_UCRT_BUILD_AVX2)