From 47f108c9f09602e8a672dc17bd60ef7d58f10c42 Mon Sep 17 00:00:00 2001 From: Gnbrkm41 Date: Tue, 26 Nov 2019 19:58:43 +0900 Subject: [PATCH 1/2] Vectorise string.Replace(char, char) * Previously https://github.com/dotnet/coreclr/pull/27798 --- .../src/System/String.Manipulation.cs | 86 +++++++++---------- 1 file changed, 39 insertions(+), 47 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs index 4d703da082e8c..6b2b7484020a2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs @@ -1055,63 +1055,55 @@ public string Replace(char oldChar, char newChar) if (oldChar == newChar) return this; - unsafe - { - int remainingLength = Length; - - fixed (char* pChars = &_firstChar) - { - char* pSrc = pChars; + int firstIndex = IndexOf(oldChar); - while (remainingLength > 0) - { - if (*pSrc == oldChar) - { - break; - } + if (firstIndex < 0) + return this; - remainingLength--; - pSrc++; - } - } + int remainingLength = Length - firstIndex; + string result = FastAllocateString(Length); - if (remainingLength == 0) - return this; + int copyLength = firstIndex; - string result = FastAllocateString(Length); - - fixed (char* pChars = &_firstChar) - { - fixed (char* pResult = &result._firstChar) - { - int copyLength = Length - remainingLength; + // Copy the characters already proven not to match. + if (copyLength > 0) + { + Buffer.Memmove(ref result._firstChar, ref _firstChar, (uint)copyLength); + } - // Copy the characters already proven not to match. - if (copyLength > 0) - { - wstrcpy(pResult, pChars, copyLength); - } + // Copy the remaining characters, doing the replacement as we go. + ref ushort pSrc = ref Unsafe.Add(ref Unsafe.As(ref _firstChar), copyLength); + ref ushort pDst = ref Unsafe.Add(ref Unsafe.As(ref result._firstChar), copyLength); - // Copy the remaining characters, doing the replacement as we go. - char* pSrc = pChars + copyLength; - char* pDst = pResult + copyLength; + if (Vector.IsHardwareAccelerated && remainingLength >= Vector.Count) + { + Vector oldChars = new Vector(oldChar); + Vector newChars = new Vector(newChar); - do - { - char currentChar = *pSrc; - if (currentChar == oldChar) - currentChar = newChar; - *pDst = currentChar; - - remainingLength--; - pSrc++; - pDst++; - } while (remainingLength > 0); - } + do + { + Vector original = Unsafe.ReadUnaligned>(ref Unsafe.As(ref pSrc)); + Vector equals = Vector.Equals(original, oldChars); + Vector results = Vector.ConditionalSelect(equals, newChars, original); + Unsafe.WriteUnaligned(ref Unsafe.As(ref pDst), results); + + pSrc = ref Unsafe.Add(ref pSrc, Vector.Count); + pDst = ref Unsafe.Add(ref pDst, Vector.Count); + remainingLength -= Vector.Count; } + while (remainingLength >= Vector.Count); + } - return result; + for (; remainingLength > 0; remainingLength--) + { + ushort currentChar = pSrc; + pDst = currentChar == oldChar ? newChar : currentChar; + + pSrc = ref Unsafe.Add(ref pSrc, 1); + pDst = ref Unsafe.Add(ref pDst, 1); } + + return result; } public string Replace(string oldValue, string? newValue) From 97b17ec06513d27a2a0feaef32fc3ff3d58bfe08 Mon Sep 17 00:00:00 2001 From: Gnbrkm41 Date: Tue, 26 Nov 2019 20:13:30 +0900 Subject: [PATCH 2/2] Add missing using for System.Numerics --- .../System.Private.CoreLib/src/System/String.Manipulation.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs index 6b2b7484020a2..8e51249f5e50b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; +using System.Numerics; using System.Text; using Internal.Runtime.CompilerServices;