From 35d3376190a48023e176ade9f2d5da1e945bf125 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Wed, 20 Mar 2019 23:54:41 -0700 Subject: [PATCH] Hoist calls to IsBitwiseEquatable (#23381) Smaller IL is easier for JIT --- .../shared/System/MemoryExtensions.cs | 631 +++++++++++---------- 1 file 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 2b7861f..4f7cab1 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(this Span span, T value) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.Contains( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + return SpanHelpers.Contains( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); - if (Unsafe.SizeOf() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.Contains( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), - span.Length); + if (Unsafe.SizeOf() == sizeof(char)) + return SpanHelpers.Contains( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + } return SpanHelpers.Contains(ref MemoryMarshal.GetReference(span), value, span.Length); } @@ -70,17 +73,20 @@ namespace System public static bool Contains(this ReadOnlySpan span, T value) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.Contains( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + return SpanHelpers.Contains( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); - if (Unsafe.SizeOf() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.Contains( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), - span.Length); + if (Unsafe.SizeOf() == sizeof(char)) + return SpanHelpers.Contains( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + } return SpanHelpers.Contains(ref MemoryMarshal.GetReference(span), value, span.Length); } @@ -94,17 +100,20 @@ namespace System public static int IndexOf(this Span span, T value) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + return SpanHelpers.IndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); - if (Unsafe.SizeOf() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), - span.Length); + if (Unsafe.SizeOf() == sizeof(char)) + return SpanHelpers.IndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + } return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } @@ -118,18 +127,22 @@ namespace System public static int IndexOf(this Span span, ReadOnlySpan value) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - span.Length, - ref Unsafe.As(ref MemoryMarshal.GetReference(value)), - value.Length); - if (Unsafe.SizeOf() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - span.Length, - ref Unsafe.As(ref MemoryMarshal.GetReference(value)), - value.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + return SpanHelpers.IndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + span.Length, + ref Unsafe.As(ref MemoryMarshal.GetReference(value)), + value.Length); + + if (Unsafe.SizeOf() == sizeof(char)) + return SpanHelpers.IndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + span.Length, + ref Unsafe.As(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(this Span span, T value) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.LastIndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + return SpanHelpers.LastIndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); - if (Unsafe.SizeOf() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.LastIndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), - span.Length); + if (Unsafe.SizeOf() == sizeof(char)) + return SpanHelpers.LastIndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + } return SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } @@ -234,17 +250,20 @@ namespace System public static int IndexOf(this ReadOnlySpan span, T value) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + return SpanHelpers.IndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); - if (Unsafe.SizeOf() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), - span.Length); + if (Unsafe.SizeOf() == sizeof(char)) + return SpanHelpers.IndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + } return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } @@ -258,18 +277,22 @@ namespace System public static int IndexOf(this ReadOnlySpan span, ReadOnlySpan value) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - span.Length, - ref Unsafe.As(ref MemoryMarshal.GetReference(value)), - value.Length); - if (Unsafe.SizeOf() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - span.Length, - ref Unsafe.As(ref MemoryMarshal.GetReference(value)), - value.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + return SpanHelpers.IndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + span.Length, + ref Unsafe.As(ref MemoryMarshal.GetReference(value)), + value.Length); + + if (Unsafe.SizeOf() == sizeof(char)) + return SpanHelpers.IndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + span.Length, + ref Unsafe.As(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(this ReadOnlySpan span, T value) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.LastIndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), - span.Length); - - if (Unsafe.SizeOf() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.LastIndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + return SpanHelpers.LastIndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + + if (Unsafe.SizeOf() == sizeof(char)) + return SpanHelpers.LastIndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + } return SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } @@ -327,18 +353,22 @@ namespace System public static int IndexOfAny(this Span span, T value0, T value1) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - span.Length); - if (Unsafe.SizeOf() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + span.Length); + + if (Unsafe.SizeOf() == sizeof(char)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(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(this Span span, T value0, T value1, T value2) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), - span.Length); - if (Unsafe.SizeOf() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), + span.Length); + + if (Unsafe.SizeOf() == sizeof(char)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(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(this Span span, ReadOnlySpan values) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - { - ref byte valueRef = ref Unsafe.As(ref MemoryMarshal.GetReference(values)); - if (values.Length == 2) - { - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - span.Length); - } - else if (values.Length == 3) - { - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - Unsafe.Add(ref valueRef, 2), - span.Length); - } - else - { - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - span.Length, - ref valueRef, - values.Length); - } - } - if (Unsafe.SizeOf() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable()) + if (RuntimeHelpers.IsBitwiseEquatable()) { - ref var valueRef = ref Unsafe.As(ref MemoryMarshal.GetReference(values)); - if (values.Length == 5) + if (Unsafe.SizeOf() == 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(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(ref MemoryMarshal.GetReference(values)); + if (values.Length == 2) + { + return SpanHelpers.IndexOfAny( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + span.Length); + } + else if (values.Length == 3) + { + return SpanHelpers.IndexOfAny( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + span.Length); + } + else + { + return SpanHelpers.IndexOfAny( + ref Unsafe.As(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(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(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(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() == 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(ref MemoryMarshal.GetReference(span)), - valueRef, - span.Length); + ref var valueRef = ref Unsafe.As(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(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(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(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(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(ref MemoryMarshal.GetReference(span)), + valueRef, + span.Length); + } } } @@ -478,18 +516,22 @@ namespace System public static int IndexOfAny(this ReadOnlySpan span, T value0, T value1) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - span.Length); - if (Unsafe.SizeOf() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + span.Length); + + if (Unsafe.SizeOf() == sizeof(char)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(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(this ReadOnlySpan span, T value0, T value1, T value2) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), - span.Length); - if (Unsafe.SizeOf() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), + span.Length); + + if (Unsafe.SizeOf() == sizeof(char)) + return SpanHelpers.IndexOfAny( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(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(this ReadOnlySpan span, ReadOnlySpan values) where T : IEquatable { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) + if (RuntimeHelpers.IsBitwiseEquatable()) { - ref byte valueRef = ref Unsafe.As(ref MemoryMarshal.GetReference(values)); - if (values.Length == 2) + if (Unsafe.SizeOf() == sizeof(byte)) { - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - span.Length); + ref byte valueRef = ref Unsafe.As(ref MemoryMarshal.GetReference(values)); + if (values.Length == 2) + { + return SpanHelpers.IndexOfAny( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + span.Length); + } + else if (values.Length == 3) + { + return SpanHelpers.IndexOfAny( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + span.Length); + } + else + { + return SpanHelpers.IndexOfAny( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + span.Length, + ref valueRef, + values.Length); + } } - else if (values.Length == 3) - { - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - Unsafe.Add(ref valueRef, 2), - span.Length); - } - else - { - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - span.Length, - ref valueRef, - values.Length); - } - } - if (Unsafe.SizeOf() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable()) - { - ref var valueRef = ref Unsafe.As(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(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() == sizeof(char)) { - // Length 2 is a common length for simple wildcards (*, ?), directory separators (/, \), quotes (", '), brackets, etc - return SpanHelpers.IndexOfAny( - ref Unsafe.As(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(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(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(ref MemoryMarshal.GetReference(span)), - valueRef, - span.Length); + ref var valueRef = ref Unsafe.As(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(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(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(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(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(ref MemoryMarshal.GetReference(span)), + valueRef, + span.Length); + } } } -- 2.7.4