Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 43 additions & 13 deletions src/System.Memory/src/System/SpanHelpers.T.cs
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ public static int LastIndexOfAny<T>(ref T searchSpace, int searchSpaceLength, re
return index;
}

#nullable enable
public static bool SequenceEqual<T>(ref T first, ref T second, int length)
where T : IEquatable<T>
{
Expand All @@ -604,25 +605,43 @@ public static bool SequenceEqual<T>(ref T first, ref T second, int length)
goto Equal;

IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
T lookUp0;
T lookUp1;
while (length >= 8)
{
length -= 8;

if (!Unsafe.Add(ref first, index).Equals(Unsafe.Add(ref second, index)))
lookUp0 = Unsafe.Add(ref first, index);
lookUp1 = Unsafe.Add(ref second, index);
if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 1).Equals(Unsafe.Add(ref second, index + 1)))
lookUp0 = Unsafe.Add(ref first, index + 1);
lookUp1 = Unsafe.Add(ref second, index + 1);
if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 2).Equals(Unsafe.Add(ref second, index + 2)))
lookUp0 = Unsafe.Add(ref first, index + 2);
lookUp1 = Unsafe.Add(ref second, index + 2);
if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 3).Equals(Unsafe.Add(ref second, index + 3)))
lookUp0 = Unsafe.Add(ref first, index + 3);
lookUp1 = Unsafe.Add(ref second, index + 3);
if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 4).Equals(Unsafe.Add(ref second, index + 4)))
lookUp0 = Unsafe.Add(ref first, index + 4);
lookUp1 = Unsafe.Add(ref second, index + 4);
if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 5).Equals(Unsafe.Add(ref second, index + 5)))
lookUp0 = Unsafe.Add(ref first, index + 5);
lookUp1 = Unsafe.Add(ref second, index + 5);
if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 6).Equals(Unsafe.Add(ref second, index + 6)))
lookUp0 = Unsafe.Add(ref first, index + 6);
lookUp1 = Unsafe.Add(ref second, index + 6);
if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 7).Equals(Unsafe.Add(ref second, index + 7)))
lookUp0 = Unsafe.Add(ref first, index + 7);
lookUp1 = Unsafe.Add(ref second, index + 7);
if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null))
goto NotEqual;

index += 8;
Expand All @@ -632,21 +651,31 @@ public static bool SequenceEqual<T>(ref T first, ref T second, int length)
{
length -= 4;

if (!Unsafe.Add(ref first, index).Equals(Unsafe.Add(ref second, index)))
lookUp0 = Unsafe.Add(ref first, index);
lookUp1 = Unsafe.Add(ref second, index);
if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 1).Equals(Unsafe.Add(ref second, index + 1)))
lookUp0 = Unsafe.Add(ref first, index + 1);
lookUp1 = Unsafe.Add(ref second, index + 1);
if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 2).Equals(Unsafe.Add(ref second, index + 2)))
lookUp0 = Unsafe.Add(ref first, index + 2);
lookUp1 = Unsafe.Add(ref second, index + 2);
if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 3).Equals(Unsafe.Add(ref second, index + 3)))
lookUp0 = Unsafe.Add(ref first, index + 3);
lookUp1 = Unsafe.Add(ref second, index + 3);
if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null))
goto NotEqual;

index += 4;
}

while (length > 0)
{
if (!Unsafe.Add(ref first, index).Equals(Unsafe.Add(ref second, index)))
lookUp0 = Unsafe.Add(ref first, index);
lookUp1 = Unsafe.Add(ref second, index);
if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null))
goto NotEqual;
index += 1;
length--;
Expand All @@ -658,6 +687,7 @@ public static bool SequenceEqual<T>(ref T first, ref T second, int length)
NotEqual: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return false;
}
#nullable restore

public static int SequenceCompareTo<T>(ref T first, int firstLength, ref T second, int secondLength)
where T : IComparable<T>
Expand Down