Hoist calls to IsBitwiseEquatable (#23381)
authorJan Kotas <jkotas@microsoft.com>
Thu, 21 Mar 2019 06:54:41 +0000 (23:54 -0700)
committerGitHub <noreply@github.com>
Thu, 21 Mar 2019 06:54:41 +0000 (23:54 -0700)
Smaller IL is easier for JIT

src/System.Private.CoreLib/shared/System/MemoryExtensions.cs

index 2b7861f..4f7cab1 100644 (file)
@@ -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);
+                    }
                 }
             }