From 9e078ffab41899650419a5928832a4302b6881e0 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 27 Mar 2018 00:27:21 -0700 Subject: Vectorized SequenceCompareTo for Span (#17237) - This change makes the compare for very short Span strings a bit slower and for longer Span strings many times faster. - Switch several places where it was a clear benefit to use it. `String.CompareOrdinal(string,string)` is notable exception that I have left intact for now. It is fine tuned for current string layout, and replacing with a call of vectorized SequenceCompareTo gives mixed results. --- src/vm/ecalllist.h | 1 - src/vm/object.cpp | 162 ----------------------------------------------------- src/vm/object.h | 2 - 3 files changed, 165 deletions(-) (limited to 'src/vm') diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h index 7e96bc7798..92d75e3f90 100644 --- a/src/vm/ecalllist.h +++ b/src/vm/ecalllist.h @@ -110,7 +110,6 @@ FCFuncStart(gStringFuncs) FCIntrinsic("get_Length", COMString::Length, CORINFO_INTRINSIC_StringLength) FCIntrinsic("get_Chars", COMString::GetCharAt, CORINFO_INTRINSIC_StringGetChar) FCFuncElement("IsAscii", COMString::IsAscii) - FCFuncElement("CompareOrdinalHelper", COMString::CompareOrdinalEx) #ifdef FEATURE_COMINTEROP FCFuncElement("SetTrailByte", COMString::FCSetTrailByte) FCFuncElement("TryGetTrailByte", COMString::FCTryGetTrailByte) diff --git a/src/vm/object.cpp b/src/vm/object.cpp index 0282b6a6a4..83afcd2fe5 100644 --- a/src/vm/object.cpp +++ b/src/vm/object.cpp @@ -1148,168 +1148,6 @@ BOOL StringObject::CaseInsensitiveCompHelper(__in_ecount(aLength) WCHAR *strACha } -INT32 StringObject::FastCompareStringHelper(DWORD* strAChars, INT32 countA, DWORD* strBChars, INT32 countB) -{ - STATIC_CONTRACT_SO_TOLERANT; - - INT32 count = (countA < countB) ? countA : countB; - - PREFIX_ASSUME(count >= 0); - - ptrdiff_t diff = (char *)strAChars - (char *)strBChars; - -#if defined(_WIN64) || defined(ALIGN_ACCESS) - int alignmentA = ((SIZE_T)strAChars) & (sizeof(SIZE_T) - 1); - int alignmentB = ((SIZE_T)strBChars) & (sizeof(SIZE_T) - 1); -#endif // _WIN64 || ALIGN_ACCESS - -#if defined(_WIN64) - if (alignmentA == alignmentB) - { - if ((alignmentA == 2 || alignmentA == 6) && (count >= 1)) - { - LPWSTR ptr2 = (WCHAR *)strBChars; - - if (( *((WCHAR*)((char *)ptr2 + diff)) - *ptr2) != 0) - { - return ((int)*((WCHAR*)((char *)ptr2 + diff)) - (int)*ptr2); - } - strBChars = (DWORD*)(++ptr2); - count -= 1; - alignmentA = (alignmentA == 2 ? 4 : 0); - } - - if ((alignmentA == 4) && (count >= 2)) - { - DWORD* ptr2 = (DWORD*)strBChars; - - if (( *((DWORD*)((char *)ptr2 + diff)) - *ptr2) != 0) - { - LPWSTR chkptr1 = (WCHAR*)((char *)strBChars + diff); - LPWSTR chkptr2 = (WCHAR*)strBChars; - - if (*chkptr1 != *chkptr2) - { - return ((int)*chkptr1 - (int)*chkptr2); - } - return ((int)*(chkptr1+1) - (int)*(chkptr2+1)); - } - strBChars = ++ptr2; - count -= 2; - alignmentA = 0; - } - - if (alignmentA == 0) - { - while (count >= 4) - { - SIZE_T* ptr2 = (SIZE_T*)strBChars; - - if (( *((SIZE_T*)((char *)ptr2 + diff)) - *ptr2) != 0) - { - if (( *((DWORD*)((char *)ptr2 + diff)) - *(DWORD*)ptr2) != 0) - { - LPWSTR chkptr1 = (WCHAR*)((char *)strBChars + diff); - LPWSTR chkptr2 = (WCHAR*)strBChars; - - if (*chkptr1 != *chkptr2) - { - return ((int)*chkptr1 - (int)*chkptr2); - } - return ((int)*(chkptr1+1) - (int)*(chkptr2+1)); - } - else - { - LPWSTR chkptr1 = (WCHAR*)((DWORD*)((char *)strBChars + diff) + 1); - LPWSTR chkptr2 = (WCHAR*)((DWORD*)strBChars + 1); - - if (*chkptr1 != *chkptr2) - { - return ((int)*chkptr1 - (int)*chkptr2); - } - return ((int)*(chkptr1+1) - (int)*(chkptr2+1)); - } - } - strBChars = (DWORD*)(++ptr2); - count -= 4; - } - } - - LPWSTR ptr2 = (WCHAR*)strBChars; - while ((count -= 1) >= 0) - { - if (( *((WCHAR*)((char *)ptr2 + diff)) - *ptr2) != 0) - { - return ((int)*((WCHAR*)((char *)ptr2 + diff)) - (int)*ptr2); - } - ++ptr2; - } - } - else -#endif // _WIN64 -#if defined(ALIGN_ACCESS) - if ( ( !IS_ALIGNED((size_t)strAChars, sizeof(DWORD)) || - !IS_ALIGNED((size_t)strBChars, sizeof(DWORD)) ) && - (abs(alignmentA - alignmentB) != 4) ) - { - _ASSERTE(IS_ALIGNED((size_t)strAChars, sizeof(WCHAR))); - _ASSERTE(IS_ALIGNED((size_t)strBChars, sizeof(WCHAR))); - LPWSTR ptr2 = (WCHAR *)strBChars; - - while ((count -= 1) >= 0) - { - if (( *((WCHAR*)((char *)ptr2 + diff)) - *ptr2) != 0) - { - return ((int)*((WCHAR*)((char *)ptr2 + diff)) - (int)*ptr2); - } - ++ptr2; - } - } - else -#endif // ALIGN_ACCESS - { -#if defined(_WIN64) || defined(ALIGN_ACCESS) - if (abs(alignmentA - alignmentB) == 4) - { - if ((alignmentA == 2) || (alignmentB == 2)) - { - LPWSTR ptr2 = (WCHAR *)strBChars; - - if (( *((WCHAR*)((char *)ptr2 + diff)) - *ptr2) != 0) - { - return ((int)*((WCHAR*)((char *)ptr2 + diff)) - (int)*ptr2); - } - strBChars = (DWORD*)(++ptr2); - count -= 1; - } - } -#endif // WIN64 || ALIGN_ACCESS - - // Loop comparing a DWORD at a time. - while ((count -= 2) >= 0) - { - if ((*((DWORD* )((char *)strBChars + diff)) - *strBChars) != 0) - { - LPWSTR ptr1 = (WCHAR*)((char *)strBChars + diff); - LPWSTR ptr2 = (WCHAR*)strBChars; - if (*ptr1 != *ptr2) { - return ((int)*ptr1 - (int)*ptr2); - } - return ((int)*(ptr1+1) - (int)*(ptr2+1)); - } - ++strBChars; - } - - int c; - if (count == -1) - if ((c = *((WCHAR *) ((char *)strBChars + diff)) - *((WCHAR *) strBChars)) != 0) - return c; - } - - return countA - countB; -} - - /*=============================InternalHasHighChars============================= **Action: Checks if the string can be sorted quickly. The requirements are that ** the string contain no character greater than 0x80 and that the string not diff --git a/src/vm/object.h b/src/vm/object.h index b0125fa50e..4324fcac2e 100644 --- a/src/vm/object.h +++ b/src/vm/object.h @@ -1060,8 +1060,6 @@ class StringObject : public Object private: - static INT32 FastCompareStringHelper(DWORD* strAChars, INT32 countA, DWORD* strBChars, INT32 countB); - static STRINGREF* EmptyStringRefPtr; }; -- cgit v1.2.3