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..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; @@ -1055,63 +1056,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)