summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2019-03-20 23:54:41 -0700
committerGitHub <noreply@github.com>2019-03-20 23:54:41 -0700
commit35d3376190a48023e176ade9f2d5da1e945bf125 (patch)
tree62a4b1ef5ebadea4a1bb4b4e5d2d69c71c8fef5d
parentea10aaccb09fe30f0444b821fd8d90d9257dd402 (diff)
downloadcoreclr-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.cs631
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);
+ }
}
}