diff --git a/src/System.Memory/src/System/SpanHelpers.cs b/src/System.Memory/src/System/SpanHelpers.cs index 46a43c391918..0e80ebb0f702 100644 --- a/src/System.Memory/src/System/SpanHelpers.cs +++ b/src/System.Memory/src/System/SpanHelpers.cs @@ -56,22 +56,35 @@ ref Unsafe.Add(ref srcBytes, (IntPtr)index), ? (uint)diff > (uint)-(int)dstByteCount : (ulong)diff > (ulong)-(long)dstByteCount; - if (srcGreaterThanDst) + int direction = srcGreaterThanDst ? 1 : -1; + int runCount = srcGreaterThanDst ? 0 : srcLength - 1; + + int loopCount = 0; + for (; loopCount < (srcLength & ~7); loopCount += 8) { - // Source address greater than destination address. Can do normal copy. - for (int i = 0; i < srcLength; i++) - { - Unsafe.Add(ref dst, i) = Unsafe.Add(ref src, i); - } + Unsafe.Add(ref dst, runCount + direction * 0) = Unsafe.Add(ref src, runCount + direction * 0); + Unsafe.Add(ref dst, runCount + direction * 1) = Unsafe.Add(ref src, runCount + direction * 1); + Unsafe.Add(ref dst, runCount + direction * 2) = Unsafe.Add(ref src, runCount + direction * 2); + Unsafe.Add(ref dst, runCount + direction * 3) = Unsafe.Add(ref src, runCount + direction * 3); + Unsafe.Add(ref dst, runCount + direction * 4) = Unsafe.Add(ref src, runCount + direction * 4); + Unsafe.Add(ref dst, runCount + direction * 5) = Unsafe.Add(ref src, runCount + direction * 5); + Unsafe.Add(ref dst, runCount + direction * 6) = Unsafe.Add(ref src, runCount + direction * 6); + Unsafe.Add(ref dst, runCount + direction * 7) = Unsafe.Add(ref src, runCount + direction * 7); + runCount += direction * 8; } - else + if (loopCount < (srcLength & ~3)) + { + Unsafe.Add(ref dst, runCount + direction * 0) = Unsafe.Add(ref src, runCount + direction * 0); + Unsafe.Add(ref dst, runCount + direction * 1) = Unsafe.Add(ref src, runCount + direction * 1); + Unsafe.Add(ref dst, runCount + direction * 2) = Unsafe.Add(ref src, runCount + direction * 2); + Unsafe.Add(ref dst, runCount + direction * 3) = Unsafe.Add(ref src, runCount + direction * 3); + runCount += direction * 4; + loopCount += 4; + } + for (; loopCount < srcLength; ++loopCount) { - // Source address less than or equal to destination address. Must do backward copy. - int i = srcLength; - while (i-- != 0) - { - Unsafe.Add(ref dst, i) = Unsafe.Add(ref src, i); - } + Unsafe.Add(ref dst, runCount) = Unsafe.Add(ref src, runCount); + runCount += direction; } } }