diff options
author | Jan Kotas <jkotas@microsoft.com> | 2019-03-20 23:54:41 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-20 23:54:41 -0700 |
commit | 35d3376190a48023e176ade9f2d5da1e945bf125 (patch) | |
tree | 62a4b1ef5ebadea4a1bb4b4e5d2d69c71c8fef5d | |
parent | ea10aaccb09fe30f0444b821fd8d90d9257dd402 (diff) | |
download | coreclr-35d3376190a48023e176ade9f2d5da1e945bf125.tar.gz coreclr-35d3376190a48023e176ade9f2d5da1e945bf125.tar.bz2 coreclr-35d3376190a48023e176ade9f2d5da1e945bf125.zip |
Hoist calls to IsBitwiseEquatable (#23381)
Smaller IL is easier for JIT
-rw-r--r-- | src/System.Private.CoreLib/shared/System/MemoryExtensions.cs | 631 |
1 files changed, 340 insertions, 291 deletions
diff --git a/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs b/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs index 2b7861f3f5..4f7cab10b6 100644 --- a/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs +++ b/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs @@ -45,17 +45,20 @@ namespace System public static bool Contains<T>(this Span<T> span, T value) where T : IEquatable<T> { - if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.Contains( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, byte>(ref value), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable<T>()) + { + if (Unsafe.SizeOf<T>() == sizeof(byte)) + return SpanHelpers.Contains( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, byte>(ref value), + span.Length); - if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.Contains( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, char>(ref value), - span.Length); + if (Unsafe.SizeOf<T>() == sizeof(char)) + return SpanHelpers.Contains( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, char>(ref value), + span.Length); + } return SpanHelpers.Contains(ref MemoryMarshal.GetReference(span), value, span.Length); } @@ -70,17 +73,20 @@ namespace System public static bool Contains<T>(this ReadOnlySpan<T> span, T value) where T : IEquatable<T> { - if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.Contains( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, byte>(ref value), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable<T>()) + { + if (Unsafe.SizeOf<T>() == sizeof(byte)) + return SpanHelpers.Contains( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, byte>(ref value), + span.Length); - if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.Contains( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, char>(ref value), - span.Length); + if (Unsafe.SizeOf<T>() == sizeof(char)) + return SpanHelpers.Contains( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, char>(ref value), + span.Length); + } return SpanHelpers.Contains(ref MemoryMarshal.GetReference(span), value, span.Length); } @@ -94,17 +100,20 @@ namespace System public static int IndexOf<T>(this Span<T> span, T value) where T : IEquatable<T> { - if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOf( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, byte>(ref value), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable<T>()) + { + if (Unsafe.SizeOf<T>() == sizeof(byte)) + return SpanHelpers.IndexOf( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, byte>(ref value), + span.Length); - if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOf( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, char>(ref value), - span.Length); + if (Unsafe.SizeOf<T>() == sizeof(char)) + return SpanHelpers.IndexOf( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, char>(ref value), + span.Length); + } return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } @@ -118,18 +127,22 @@ namespace System public static int IndexOf<T>(this Span<T> span, ReadOnlySpan<T> value) where T : IEquatable<T> { - if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOf( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - span.Length, - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), - value.Length); - if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOf( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - span.Length, - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(value)), - value.Length); + if (RuntimeHelpers.IsBitwiseEquatable<T>()) + { + if (Unsafe.SizeOf<T>() == sizeof(byte)) + return SpanHelpers.IndexOf( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + span.Length, + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), + value.Length); + + if (Unsafe.SizeOf<T>() == sizeof(char)) + return SpanHelpers.IndexOf( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + span.Length, + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(value)), + value.Length); + } return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); } @@ -143,17 +156,20 @@ namespace System public static int LastIndexOf<T>(this Span<T> span, T value) where T : IEquatable<T> { - if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.LastIndexOf( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, byte>(ref value), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable<T>()) + { + if (Unsafe.SizeOf<T>() == sizeof(byte)) + return SpanHelpers.LastIndexOf( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, byte>(ref value), + span.Length); - if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.LastIndexOf( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, char>(ref value), - span.Length); + if (Unsafe.SizeOf<T>() == sizeof(char)) + return SpanHelpers.LastIndexOf( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, char>(ref value), + span.Length); + } return SpanHelpers.LastIndexOf<T>(ref MemoryMarshal.GetReference(span), value, span.Length); } @@ -234,17 +250,20 @@ namespace System public static int IndexOf<T>(this ReadOnlySpan<T> span, T value) where T : IEquatable<T> { - if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOf( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, byte>(ref value), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable<T>()) + { + if (Unsafe.SizeOf<T>() == sizeof(byte)) + return SpanHelpers.IndexOf( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, byte>(ref value), + span.Length); - if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOf( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, char>(ref value), - span.Length); + if (Unsafe.SizeOf<T>() == sizeof(char)) + return SpanHelpers.IndexOf( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, char>(ref value), + span.Length); + } return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } @@ -258,18 +277,22 @@ namespace System public static int IndexOf<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> value) where T : IEquatable<T> { - if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOf( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - span.Length, - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), - value.Length); - if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOf( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - span.Length, - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(value)), - value.Length); + if (RuntimeHelpers.IsBitwiseEquatable<T>()) + { + if (Unsafe.SizeOf<T>() == sizeof(byte)) + return SpanHelpers.IndexOf( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + span.Length, + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), + value.Length); + + if (Unsafe.SizeOf<T>() == sizeof(char)) + return SpanHelpers.IndexOf( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + span.Length, + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(value)), + value.Length); + } return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); } @@ -283,17 +306,20 @@ namespace System public static int LastIndexOf<T>(this ReadOnlySpan<T> span, T value) where T : IEquatable<T> { - if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.LastIndexOf( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, byte>(ref value), - span.Length); - - if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.LastIndexOf( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, char>(ref value), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable<T>()) + { + if (Unsafe.SizeOf<T>() == sizeof(byte)) + return SpanHelpers.LastIndexOf( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, byte>(ref value), + span.Length); + + if (Unsafe.SizeOf<T>() == sizeof(char)) + return SpanHelpers.LastIndexOf( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, char>(ref value), + span.Length); + } return SpanHelpers.LastIndexOf<T>(ref MemoryMarshal.GetReference(span), value, span.Length); } @@ -327,18 +353,22 @@ namespace System public static int IndexOfAny<T>(this Span<T> span, T value0, T value1) where T : IEquatable<T> { - if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, byte>(ref value0), - Unsafe.As<T, byte>(ref value1), - span.Length); - if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, char>(ref value0), - Unsafe.As<T, char>(ref value1), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable<T>()) + { + if (Unsafe.SizeOf<T>() == sizeof(byte)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, byte>(ref value0), + Unsafe.As<T, byte>(ref value1), + span.Length); + + if (Unsafe.SizeOf<T>() == sizeof(char)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, char>(ref value0), + Unsafe.As<T, char>(ref value1), + span.Length); + } return SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); } @@ -354,20 +384,24 @@ namespace System public static int IndexOfAny<T>(this Span<T> span, T value0, T value1, T value2) where T : IEquatable<T> { - if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, byte>(ref value0), - Unsafe.As<T, byte>(ref value1), - Unsafe.As<T, byte>(ref value2), - span.Length); - if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, char>(ref value0), - Unsafe.As<T, char>(ref value1), - Unsafe.As<T, char>(ref value2), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable<T>()) + { + if (Unsafe.SizeOf<T>() == sizeof(byte)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, byte>(ref value0), + Unsafe.As<T, byte>(ref value1), + Unsafe.As<T, byte>(ref value2), + span.Length); + + if (Unsafe.SizeOf<T>() == sizeof(char)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, char>(ref value0), + Unsafe.As<T, char>(ref value1), + Unsafe.As<T, char>(ref value2), + span.Length); + } return SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); } @@ -381,87 +415,91 @@ namespace System public static int IndexOfAny<T>(this Span<T> span, ReadOnlySpan<T> values) where T : IEquatable<T> { - if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>()) - { - ref byte valueRef = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)); - if (values.Length == 2) - { - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - span.Length); - } - else if (values.Length == 3) - { - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - Unsafe.Add(ref valueRef, 2), - span.Length); - } - else - { - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - span.Length, - ref valueRef, - values.Length); - } - } - if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>()) + if (RuntimeHelpers.IsBitwiseEquatable<T>()) { - ref var valueRef = ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(values)); - if (values.Length == 5) + if (Unsafe.SizeOf<T>() == sizeof(byte)) { - // Length 5 is a common length for FileSystemName expression (", <, >, *, ?) and in preference to 2 as it has an explicit overload - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - Unsafe.Add(ref valueRef, 2), - Unsafe.Add(ref valueRef, 3), - Unsafe.Add(ref valueRef, 4), - span.Length); + ref byte valueRef = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)); + if (values.Length == 2) + { + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + span.Length); + } + else if (values.Length == 3) + { + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + span.Length); + } + else + { + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + span.Length, + ref valueRef, + values.Length); + } } - else if (values.Length == 2) - { - // Length 2 is a common length for simple wildcards (*, ?), directory separators (/, \), quotes (", '), brackets, etc - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - span.Length); - } - else if (values.Length == 4) - { - // Length 4 before 3 as 3 has an explicit overload - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - Unsafe.Add(ref valueRef, 2), - Unsafe.Add(ref valueRef, 3), - span.Length); - } - else if (values.Length == 3) - { - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - Unsafe.Add(ref valueRef, 2), - span.Length); - } - else if (values.Length == 1) + + if (Unsafe.SizeOf<T>() == sizeof(char)) { - // Length 1 last, as ctoring a ReadOnlySpan to call this overload for a single value - // is already throwing away a bunch of performance vs just calling IndexOf - return SpanHelpers.IndexOf( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - valueRef, - span.Length); + ref var valueRef = ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(values)); + if (values.Length == 5) + { + // Length 5 is a common length for FileSystemName expression (", <, >, *, ?) and in preference to 2 as it has an explicit overload + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + Unsafe.Add(ref valueRef, 3), + Unsafe.Add(ref valueRef, 4), + span.Length); + } + else if (values.Length == 2) + { + // Length 2 is a common length for simple wildcards (*, ?), directory separators (/, \), quotes (", '), brackets, etc + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + span.Length); + } + else if (values.Length == 4) + { + // Length 4 before 3 as 3 has an explicit overload + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + Unsafe.Add(ref valueRef, 3), + span.Length); + } + else if (values.Length == 3) + { + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + span.Length); + } + else if (values.Length == 1) + { + // Length 1 last, as ctoring a ReadOnlySpan to call this overload for a single value + // is already throwing away a bunch of performance vs just calling IndexOf + return SpanHelpers.IndexOf( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + valueRef, + span.Length); + } } } @@ -478,18 +516,22 @@ namespace System public static int IndexOfAny<T>(this ReadOnlySpan<T> span, T value0, T value1) where T : IEquatable<T> { - if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, byte>(ref value0), - Unsafe.As<T, byte>(ref value1), - span.Length); - if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, char>(ref value0), - Unsafe.As<T, char>(ref value1), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable<T>()) + { + if (Unsafe.SizeOf<T>() == sizeof(byte)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, byte>(ref value0), + Unsafe.As<T, byte>(ref value1), + span.Length); + + if (Unsafe.SizeOf<T>() == sizeof(char)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, char>(ref value0), + Unsafe.As<T, char>(ref value1), + span.Length); + } return SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); } @@ -505,20 +547,24 @@ namespace System public static int IndexOfAny<T>(this ReadOnlySpan<T> span, T value0, T value1, T value2) where T : IEquatable<T> { - if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, byte>(ref value0), - Unsafe.As<T, byte>(ref value1), - Unsafe.As<T, byte>(ref value2), - span.Length); - if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - Unsafe.As<T, char>(ref value0), - Unsafe.As<T, char>(ref value1), - Unsafe.As<T, char>(ref value2), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable<T>()) + { + if (Unsafe.SizeOf<T>() == sizeof(byte)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, byte>(ref value0), + Unsafe.As<T, byte>(ref value1), + Unsafe.As<T, byte>(ref value2), + span.Length); + + if (Unsafe.SizeOf<T>() == sizeof(char)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + Unsafe.As<T, char>(ref value0), + Unsafe.As<T, char>(ref value1), + Unsafe.As<T, char>(ref value2), + span.Length); + } return SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); } @@ -532,88 +578,91 @@ namespace System public static int IndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> values) where T : IEquatable<T> { - if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>()) + if (RuntimeHelpers.IsBitwiseEquatable<T>()) { - ref byte valueRef = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)); - if (values.Length == 2) + if (Unsafe.SizeOf<T>() == sizeof(byte)) { - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - span.Length); + ref byte valueRef = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)); + if (values.Length == 2) + { + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + span.Length); + } + else if (values.Length == 3) + { + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + span.Length); + } + else + { + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), + span.Length, + ref valueRef, + values.Length); + } } - else if (values.Length == 3) - { - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - Unsafe.Add(ref valueRef, 2), - span.Length); - } - else - { - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), - span.Length, - ref valueRef, - values.Length); - } - } - if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>()) - { - ref var valueRef = ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(values)); - if (values.Length == 5) - { - // Length 5 is a common length for FileSystemName expression (", <, >, *, ?) and in preference to 2 as it has an explicit overload - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - Unsafe.Add(ref valueRef, 2), - Unsafe.Add(ref valueRef, 3), - Unsafe.Add(ref valueRef, 4), - span.Length); - } - else if (values.Length == 2) + if (Unsafe.SizeOf<T>() == sizeof(char)) { - // Length 2 is a common length for simple wildcards (*, ?), directory separators (/, \), quotes (", '), brackets, etc - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - span.Length); - } - else if (values.Length == 4) - { - // Length 4 before 3 as 3 has an explicit overload - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - Unsafe.Add(ref valueRef, 2), - Unsafe.Add(ref valueRef, 3), - span.Length); - } - else if (values.Length == 3) - { - return SpanHelpers.IndexOfAny( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - Unsafe.Add(ref valueRef, 2), - span.Length); - } - else if (values.Length == 1) - { - // Length 1 last, as ctoring a ReadOnlySpan to call this overload for a single value - // is already throwing away a bunch of performance vs just calling IndexOf - return SpanHelpers.IndexOf( - ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), - valueRef, - span.Length); + ref var valueRef = ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(values)); + if (values.Length == 5) + { + // Length 5 is a common length for FileSystemName expression (", <, >, *, ?) and in preference to 2 as it has an explicit overload + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + Unsafe.Add(ref valueRef, 3), + Unsafe.Add(ref valueRef, 4), + span.Length); + } + else if (values.Length == 2) + { + // Length 2 is a common length for simple wildcards (*, ?), directory separators (/, \), quotes (", '), brackets, etc + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + span.Length); + } + else if (values.Length == 4) + { + // Length 4 before 3 as 3 has an explicit overload + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + Unsafe.Add(ref valueRef, 3), + span.Length); + } + else if (values.Length == 3) + { + return SpanHelpers.IndexOfAny( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + span.Length); + } + else if (values.Length == 1) + { + // Length 1 last, as ctoring a ReadOnlySpan to call this overload for a single value + // is already throwing away a bunch of performance vs just calling IndexOf + return SpanHelpers.IndexOf( + ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), + valueRef, + span.Length); + } } } |