Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 467d45e

Browse files
dschindestephentoub
authored andcommitted
Improve pref of Array.IndexOf() for certain T. (dotnet/coreclr#24293)
Applies changes to `Array.IndexOf()` and `Array.LastIndexOf()` similar to the changes made in #20855, so that types other than `byte` and `char` can use use the fast vectorized path. Also allows 32-bit and 64-bit types for which `RuntimeHelpers.IsBitwiseEquatable<T>()` returns `true` to use the faster implementation of `IndexOf` and `LastIndexOf` from `MemoryExtensions`. Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
1 parent 0759a6c commit 467d45e

File tree

1 file changed

+73
-33
lines changed

1 file changed

+73
-33
lines changed

src/Common/src/CoreLib/System/Array.cs

Lines changed: 73 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Collections.ObjectModel;
88
using System.Diagnostics;
99
using System.Runtime.CompilerServices;
10+
using System.Runtime.InteropServices;
1011
using Internal.Runtime.CompilerServices;
1112

1213
#nullable enable
@@ -1016,24 +1017,40 @@ public static int IndexOf<T>(T[] array, T value, int startIndex, int count)
10161017

10171018
// Hits a code generation bug on ProjectN
10181019
#if !PROJECTN
1019-
if (typeof(T) == typeof(byte))
1020+
if (RuntimeHelpers.IsBitwiseEquatable<T>())
10201021
{
1021-
int result = SpanHelpers.IndexOf(
1022-
ref Unsafe.Add(ref array.GetRawSzArrayData(), startIndex),
1023-
Unsafe.As<T, byte>(ref value),
1024-
count);
1025-
1026-
return (result >= 0 ? startIndex : 0) + result;
1027-
}
1028-
1029-
if (typeof(T) == typeof(char))
1030-
{
1031-
int result = SpanHelpers.IndexOf(
1032-
ref Unsafe.Add(ref Unsafe.As<byte, char>(ref array.GetRawSzArrayData()), startIndex),
1033-
Unsafe.As<T, char>(ref value),
1034-
count);
1035-
1036-
return (result >= 0 ? startIndex : 0) + result;
1022+
if (Unsafe.SizeOf<T>() == sizeof(byte))
1023+
{
1024+
int result = SpanHelpers.IndexOf(
1025+
ref Unsafe.Add(ref array.GetRawSzArrayData(), startIndex),
1026+
Unsafe.As<T, byte>(ref value),
1027+
count);
1028+
return (result >= 0 ? startIndex : 0) + result;
1029+
}
1030+
else if (Unsafe.SizeOf<T>() == sizeof(char))
1031+
{
1032+
int result = SpanHelpers.IndexOf(
1033+
ref Unsafe.Add(ref Unsafe.As<byte, char>(ref array.GetRawSzArrayData()), startIndex),
1034+
Unsafe.As<T, char>(ref value),
1035+
count);
1036+
return (result >= 0 ? startIndex : 0) + result;
1037+
}
1038+
else if (Unsafe.SizeOf<T>() == sizeof(int))
1039+
{
1040+
int result = SpanHelpers.IndexOf(
1041+
ref Unsafe.Add(ref Unsafe.As<byte, int>(ref array.GetRawSzArrayData()), startIndex),
1042+
Unsafe.As<T, int>(ref value),
1043+
count);
1044+
return (result >= 0 ? startIndex : 0) + result;
1045+
}
1046+
else if (Unsafe.SizeOf<T>() == sizeof(long))
1047+
{
1048+
int result = SpanHelpers.IndexOf(
1049+
ref Unsafe.Add(ref Unsafe.As<byte, long>(ref array.GetRawSzArrayData()), startIndex),
1050+
Unsafe.As<T, long>(ref value),
1051+
count);
1052+
return (result >= 0 ? startIndex : 0) + result;
1053+
}
10371054
}
10381055
#endif
10391056

@@ -1204,27 +1221,50 @@ public static int LastIndexOf<T>(T[] array, T value, int startIndex, int count)
12041221

12051222
// Hits a code generation bug on ProjectN
12061223
#if !PROJECTN
1207-
if (typeof(T) == typeof(byte))
1224+
if (RuntimeHelpers.IsBitwiseEquatable<T>())
12081225
{
1209-
int endIndex = startIndex - count + 1;
1210-
int result = SpanHelpers.LastIndexOf(
1211-
ref Unsafe.Add(ref array.GetRawSzArrayData(), endIndex),
1212-
Unsafe.As<T, byte>(ref value),
1213-
count);
1226+
if (Unsafe.SizeOf<T>() == sizeof(byte))
1227+
{
1228+
int endIndex = startIndex - count + 1;
1229+
int result = SpanHelpers.LastIndexOf(
1230+
ref Unsafe.Add(ref array.GetRawSzArrayData(), endIndex),
1231+
Unsafe.As<T, byte>(ref value),
1232+
count);
12141233

1215-
return (result >= 0 ? endIndex : 0) + result;
1216-
}
1234+
return (result >= 0 ? endIndex : 0) + result;
1235+
}
1236+
else if (Unsafe.SizeOf<T>() == sizeof(char))
1237+
{
1238+
int endIndex = startIndex - count + 1;
1239+
int result = SpanHelpers.LastIndexOf(
1240+
ref Unsafe.Add(ref Unsafe.As<byte, char>(ref array.GetRawSzArrayData()), endIndex),
1241+
Unsafe.As<T, char>(ref value),
1242+
count);
12171243

1218-
if (typeof(T) == typeof(char))
1219-
{
1220-
int endIndex = startIndex - count + 1;
1221-
int result = SpanHelpers.LastIndexOf(
1222-
ref Unsafe.Add(ref Unsafe.As<byte, char>(ref array.GetRawSzArrayData()), endIndex),
1223-
Unsafe.As<T, char>(ref value),
1224-
count);
1244+
return (result >= 0 ? endIndex : 0) + result;
1245+
}
1246+
else if (Unsafe.SizeOf<T>() == sizeof(int))
1247+
{
1248+
int endIndex = startIndex - count + 1;
1249+
int result = SpanHelpers.LastIndexOf(
1250+
ref Unsafe.Add(ref Unsafe.As<byte, int>(ref array.GetRawSzArrayData()), endIndex),
1251+
Unsafe.As<T, int>(ref value),
1252+
count);
1253+
1254+
return (result >= 0 ? endIndex : 0) + result;
1255+
}
1256+
else if (Unsafe.SizeOf<T>() == sizeof(long))
1257+
{
1258+
int endIndex = startIndex - count + 1;
1259+
int result = SpanHelpers.LastIndexOf(
1260+
ref Unsafe.Add(ref Unsafe.As<byte, long>(ref array.GetRawSzArrayData()), endIndex),
1261+
Unsafe.As<T, long>(ref value),
1262+
count);
12251263

1226-
return (result >= 0 ? endIndex : 0) + result;
1264+
return (result >= 0 ? endIndex : 0) + result;
1265+
}
12271266
}
1267+
12281268
#endif
12291269

12301270
#if CORECLR

0 commit comments

Comments
 (0)