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

Commit eebbd2f

Browse files
committed
Optimize .IndexOfAny(4,5) for short lengths
1 parent 6ac7daf commit eebbd2f

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,13 +1024,20 @@ public static int IndexOfAny(ref char searchSpace, char value0, char value1, cha
10241024
Vector128<ushort> values1 = Vector128.Create(value1);
10251025
Vector128<ushort> values2 = Vector128.Create(value2);
10261026
Vector128<ushort> values3 = Vector128.Create(value3);
1027+
10271028
Vector128<ushort> search = LoadVector128(ref searchSpace, offset);
10281029

1030+
// We can do the ORs in vectors here as we don't need to keep the values as we are not looping
1031+
Vector128<ushort> matches0 = Sse2.CompareEqual(values0, search);
1032+
Vector128<ushort> matches1 = Sse2.CompareEqual(values1, search);
1033+
Vector128<ushort> matches2 = Sse2.CompareEqual(values2, search);
1034+
Vector128<ushort> matches3 = Sse2.CompareEqual(values3, search);
1035+
1036+
Vector128<ushort> matches01 = Sse2.Or(matches0, matches1);
1037+
Vector128<ushort> matches23 = Sse2.Or(matches2, matches3);
1038+
10291039
// Same method as above
1030-
int matches = Sse2.MoveMask(Sse2.CompareEqual(values0, search).AsByte());
1031-
matches |= Sse2.MoveMask(Sse2.CompareEqual(values1, search).AsByte());
1032-
matches |= Sse2.MoveMask(Sse2.CompareEqual(values2, search).AsByte());
1033-
matches |= Sse2.MoveMask(Sse2.CompareEqual(values3, search).AsByte());
1040+
int matches = Sse2.MoveMask(Sse2.Or(matches01, matches23).AsByte());
10341041
if (matches == 0)
10351042
{
10361043
// Zero flags set so no matches
@@ -1241,14 +1248,21 @@ public static int IndexOfAny(ref char searchSpace, char value0, char value1, cha
12411248
Vector128<ushort> values2 = Vector128.Create(value2);
12421249
Vector128<ushort> values3 = Vector128.Create(value3);
12431250
Vector128<ushort> values4 = Vector128.Create(value4);
1251+
12441252
Vector128<ushort> search = LoadVector128(ref searchSpace, offset);
12451253

1254+
// We can do the ORs in vectors here as we don't need to keep the values as we are not looping
1255+
Vector128<ushort> matches0 = Sse2.CompareEqual(values0, search);
1256+
Vector128<ushort> matches1 = Sse2.CompareEqual(values1, search);
1257+
Vector128<ushort> matches2 = Sse2.CompareEqual(values2, search);
1258+
Vector128<ushort> matches3 = Sse2.CompareEqual(values3, search);
1259+
Vector128<ushort> matches4 = Sse2.CompareEqual(values4, search);
1260+
1261+
Vector128<ushort> matches01 = Sse2.Or(matches0, matches1);
1262+
Vector128<ushort> matches23 = Sse2.Or(matches2, matches3);
1263+
12461264
// Same method as above
1247-
int matches = Sse2.MoveMask(Sse2.CompareEqual(values0, search).AsByte());
1248-
matches |= Sse2.MoveMask(Sse2.CompareEqual(values1, search).AsByte());
1249-
matches |= Sse2.MoveMask(Sse2.CompareEqual(values2, search).AsByte());
1250-
matches |= Sse2.MoveMask(Sse2.CompareEqual(values3, search).AsByte());
1251-
matches |= Sse2.MoveMask(Sse2.CompareEqual(values4, search).AsByte());
1265+
int matches = Sse2.MoveMask(Sse2.Or(Sse2.Or(matches01, matches4), matches23).AsByte());
12521266
if (matches == 0)
12531267
{
12541268
// Zero flags set so no matches

0 commit comments

Comments
 (0)