Skip to content

Commit a59cff5

Browse files
committed
Stop using PackedIndexOf on ARM
1 parent 178b1f8 commit a59cff5

File tree

8 files changed

+46
-52
lines changed

8 files changed

+46
-52
lines changed

src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan<char> source, ReadOnly
340340
// Do a quick search for the first element of "value".
341341
int relativeIndex = isLetter ?
342342
PackedSpanHelpers.PackedIndexOfIsSupported
343-
? PackedSpanHelpers.PackedIndexOfAny(ref Unsafe.Add(ref searchSpace, offset), valueCharU, valueCharL, searchSpaceLength)
343+
? PackedSpanHelpers.IndexOfAny(ref Unsafe.Add(ref searchSpace, offset), valueCharU, valueCharL, searchSpaceLength)
344344
: SpanHelpers.IndexOfAnyChar(ref Unsafe.Add(ref searchSpace, offset), valueCharU, valueCharL, searchSpaceLength) :
345345
SpanHelpers.IndexOfChar(ref Unsafe.Add(ref searchSpace, offset), valueChar, searchSpaceLength);
346346
if (relativeIndex < 0)

src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny1CharValue.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ internal override bool ContainsCore(char value) =>
2323
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2424
internal override int IndexOfAny(ReadOnlySpan<char> span) =>
2525
TShouldUsePacked.Value
26-
? PackedSpanHelpers.PackedIndexOf(ref MemoryMarshal.GetReference(span), _e0, span.Length)
26+
? PackedSpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), _e0, span.Length)
2727
: SpanHelpers.NonPackedIndexOfValueType<short, SpanHelpers.DontNegate<short>>(
2828
ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
2929
Unsafe.As<char, short>(ref _e0),
@@ -32,7 +32,7 @@ ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
3232
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3333
internal override int IndexOfAnyExcept(ReadOnlySpan<char> span) =>
3434
TShouldUsePacked.Value
35-
? PackedSpanHelpers.PackedIndexOfAnyExcept(ref MemoryMarshal.GetReference(span), _e0, span.Length)
35+
? PackedSpanHelpers.IndexOfAnyExcept(ref MemoryMarshal.GetReference(span), _e0, span.Length)
3636
: SpanHelpers.NonPackedIndexOfValueType<short, SpanHelpers.Negate<short>>(
3737
ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
3838
Unsafe.As<char, short>(ref _e0),

src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny2CharValues.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ internal override bool ContainsCore(char value) =>
2323
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2424
internal override int IndexOfAny(ReadOnlySpan<char> span) =>
2525
TShouldUsePacked.Value
26-
? PackedSpanHelpers.PackedIndexOfAny(ref MemoryMarshal.GetReference(span), _e0, _e1, span.Length)
26+
? PackedSpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), _e0, _e1, span.Length)
2727
: SpanHelpers.NonPackedIndexOfAnyValueType<short, SpanHelpers.DontNegate<short>>(
2828
ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
2929
Unsafe.As<char, short>(ref _e0),
@@ -33,7 +33,7 @@ ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
3333
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3434
internal override int IndexOfAnyExcept(ReadOnlySpan<char> span) =>
3535
TShouldUsePacked.Value
36-
? PackedSpanHelpers.PackedIndexOfAnyExcept(ref MemoryMarshal.GetReference(span), _e0, _e1, span.Length)
36+
? PackedSpanHelpers.IndexOfAnyExcept(ref MemoryMarshal.GetReference(span), _e0, _e1, span.Length)
3737
: SpanHelpers.NonPackedIndexOfAnyValueType<short, SpanHelpers.Negate<short>>(
3838
ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
3939
Unsafe.As<char, short>(ref _e0),

src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny3CharValues.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ internal override bool ContainsCore(char value) =>
2323
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2424
internal override int IndexOfAny(ReadOnlySpan<char> span) =>
2525
TShouldUsePacked.Value
26-
? PackedSpanHelpers.PackedIndexOfAny(ref MemoryMarshal.GetReference(span), _e0, _e1, _e2, span.Length)
26+
? PackedSpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), _e0, _e1, _e2, span.Length)
2727
: SpanHelpers.NonPackedIndexOfAnyValueType<short, SpanHelpers.DontNegate<short>>(
2828
ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
2929
Unsafe.As<char, short>(ref _e0),
@@ -34,7 +34,7 @@ ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
3434
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3535
internal override int IndexOfAnyExcept(ReadOnlySpan<char> span) =>
3636
TShouldUsePacked.Value
37-
? PackedSpanHelpers.PackedIndexOfAnyExcept(ref MemoryMarshal.GetReference(span), _e0, _e1, _e2, span.Length)
37+
? PackedSpanHelpers.IndexOfAnyExcept(ref MemoryMarshal.GetReference(span), _e0, _e1, _e2, span.Length)
3838
: SpanHelpers.NonPackedIndexOfAnyValueType<short, SpanHelpers.Negate<short>>(
3939
ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
4040
Unsafe.As<char, short>(ref _e0),

src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAnyCharValuesInRange.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ internal override bool ContainsCore(char value) =>
3939
[MethodImpl(MethodImplOptions.AggressiveInlining)]
4040
internal override int IndexOfAny(ReadOnlySpan<char> span) =>
4141
TShouldUsePacked.Value
42-
? PackedSpanHelpers.PackedIndexOfAnyInRange(ref MemoryMarshal.GetReference(span), _lowInclusive, _rangeInclusive, span.Length)
42+
? PackedSpanHelpers.IndexOfAnyInRange(ref MemoryMarshal.GetReference(span), _lowInclusive, _rangeInclusive, span.Length)
4343
: SpanHelpers.NonPackedIndexOfAnyInRangeUnsignedNumber<ushort, SpanHelpers.DontNegate<ushort>>(
4444
ref Unsafe.As<char, ushort>(ref MemoryMarshal.GetReference(span)),
4545
Unsafe.As<char, ushort>(ref _lowInclusive),
@@ -49,7 +49,7 @@ ref Unsafe.As<char, ushort>(ref MemoryMarshal.GetReference(span)),
4949
[MethodImpl(MethodImplOptions.AggressiveInlining)]
5050
internal override int IndexOfAnyExcept(ReadOnlySpan<char> span) =>
5151
TShouldUsePacked.Value
52-
? PackedSpanHelpers.PackedIndexOfAnyExceptInRange(ref MemoryMarshal.GetReference(span), _lowInclusive, _rangeInclusive, span.Length)
52+
? PackedSpanHelpers.IndexOfAnyExceptInRange(ref MemoryMarshal.GetReference(span), _lowInclusive, _rangeInclusive, span.Length)
5353
: SpanHelpers.NonPackedIndexOfAnyInRangeUnsignedNumber<ushort, SpanHelpers.Negate<ushort>>(
5454
ref Unsafe.As<char, ushort>(ref MemoryMarshal.GetReference(span)),
5555
Unsafe.As<char, ushort>(ref _lowInclusive),

src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Packed.cs

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using System.Numerics;
77
using System.Runtime.CompilerServices;
88
using System.Runtime.Intrinsics;
9-
using System.Runtime.Intrinsics.Arm;
109
using System.Runtime.Intrinsics.X86;
1110

1211
#pragma warning disable IDE0060 // https://github.com/dotnet/roslyn-analyzers/issues/6228
@@ -19,53 +18,51 @@ namespace System
1918
// included in this file which are specific to the packed implementation.
2019
internal static partial class PackedSpanHelpers
2120
{
22-
public static bool PackedIndexOfIsSupported => Sse2.IsSupported || AdvSimd.IsSupported;
21+
// We only do this optimization on X86 as the packing is noticeably more expensive on ARM in comparison.
22+
// While the impact on worst-case (match at the start) is minimal on X86, it's prohibitively large on ARM.
23+
public static bool PackedIndexOfIsSupported => Sse2.IsSupported;
2324

2425
// Not all values can benefit from packing the searchSpace. See comments in PackSources below.
25-
// On X86, the values must be in the [1, 254] range.
26-
// On ARM, the values must be in the [0, 254] range.
2726
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2827
public static unsafe bool CanUsePackedIndexOf<T>(T value) =>
2928
PackedIndexOfIsSupported &&
3029
RuntimeHelpers.IsBitwiseEquatable<T>() &&
3130
sizeof(T) == sizeof(ushort) &&
32-
(Sse2.IsSupported
33-
? *(ushort*)&value - 1u < 254u
34-
: *(ushort*)&value < 255u);
31+
*(ushort*)&value - 1u < 254u;
3532

3633
[MethodImpl(MethodImplOptions.AggressiveInlining)]
37-
public static int PackedIndexOf(ref char searchSpace, char value, int length) =>
38-
PackedIndexOf<SpanHelpers.DontNegate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)value, length);
34+
public static int IndexOf(ref char searchSpace, char value, int length) =>
35+
IndexOf<SpanHelpers.DontNegate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)value, length);
3936

4037
[MethodImpl(MethodImplOptions.AggressiveInlining)]
41-
public static int PackedIndexOfAnyExcept(ref char searchSpace, char value, int length) =>
42-
PackedIndexOf<SpanHelpers.Negate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)value, length);
38+
public static int IndexOfAnyExcept(ref char searchSpace, char value, int length) =>
39+
IndexOf<SpanHelpers.Negate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)value, length);
4340

4441
[MethodImpl(MethodImplOptions.AggressiveInlining)]
45-
public static int PackedIndexOfAny(ref char searchSpace, char value0, char value1, int length) =>
46-
PackedIndexOfAny<SpanHelpers.DontNegate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)value0, (short)value1, length);
42+
public static int IndexOfAny(ref char searchSpace, char value0, char value1, int length) =>
43+
IndexOfAny<SpanHelpers.DontNegate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)value0, (short)value1, length);
4744

4845
[MethodImpl(MethodImplOptions.AggressiveInlining)]
49-
public static int PackedIndexOfAnyExcept(ref char searchSpace, char value0, char value1, int length) =>
50-
PackedIndexOfAny<SpanHelpers.Negate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)value0, (short)value1, length);
46+
public static int IndexOfAnyExcept(ref char searchSpace, char value0, char value1, int length) =>
47+
IndexOfAny<SpanHelpers.Negate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)value0, (short)value1, length);
5148

5249
[MethodImpl(MethodImplOptions.AggressiveInlining)]
53-
public static int PackedIndexOfAny(ref char searchSpace, char value0, char value1, char value2, int length) =>
54-
PackedIndexOfAny<SpanHelpers.DontNegate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)value0, (short)value1, (short)value2, length);
50+
public static int IndexOfAny(ref char searchSpace, char value0, char value1, char value2, int length) =>
51+
IndexOfAny<SpanHelpers.DontNegate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)value0, (short)value1, (short)value2, length);
5552

5653
[MethodImpl(MethodImplOptions.AggressiveInlining)]
57-
public static int PackedIndexOfAnyExcept(ref char searchSpace, char value0, char value1, char value2, int length) =>
58-
PackedIndexOfAny<SpanHelpers.Negate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)value0, (short)value1, (short)value2, length);
54+
public static int IndexOfAnyExcept(ref char searchSpace, char value0, char value1, char value2, int length) =>
55+
IndexOfAny<SpanHelpers.Negate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)value0, (short)value1, (short)value2, length);
5956

6057
[MethodImpl(MethodImplOptions.AggressiveInlining)]
61-
public static int PackedIndexOfAnyInRange(ref char searchSpace, char lowInclusive, char rangeInclusive, int length) =>
62-
PackedIndexOfAnyInRange<SpanHelpers.DontNegate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)lowInclusive, (short)rangeInclusive, length);
58+
public static int IndexOfAnyInRange(ref char searchSpace, char lowInclusive, char rangeInclusive, int length) =>
59+
IndexOfAnyInRange<SpanHelpers.DontNegate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)lowInclusive, (short)rangeInclusive, length);
6360

6461
[MethodImpl(MethodImplOptions.AggressiveInlining)]
65-
public static int PackedIndexOfAnyExceptInRange(ref char searchSpace, char lowInclusive, char rangeInclusive, int length) =>
66-
PackedIndexOfAnyInRange<SpanHelpers.Negate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)lowInclusive, (short)rangeInclusive, length);
62+
public static int IndexOfAnyExceptInRange(ref char searchSpace, char lowInclusive, char rangeInclusive, int length) =>
63+
IndexOfAnyInRange<SpanHelpers.Negate<short>>(ref Unsafe.As<char, short>(ref searchSpace), (short)lowInclusive, (short)rangeInclusive, length);
6764

68-
public static bool PackedContains(ref short searchSpace, short value, int length)
65+
public static bool Contains(ref short searchSpace, short value, int length)
6966
{
7067
Debug.Assert(CanUsePackedIndexOf(value));
7168

@@ -207,7 +204,7 @@ public static bool PackedContains(ref short searchSpace, short value, int length
207204
return false;
208205
}
209206

210-
private static int PackedIndexOf<TNegator>(ref short searchSpace, short value, int length)
207+
private static int IndexOf<TNegator>(ref short searchSpace, short value, int length)
211208
where TNegator : struct, SpanHelpers.INegator<short>
212209
{
213210
Debug.Assert(CanUsePackedIndexOf(value));
@@ -348,7 +345,7 @@ private static int PackedIndexOf<TNegator>(ref short searchSpace, short value, i
348345
return -1;
349346
}
350347

351-
private static int PackedIndexOfAny<TNegator>(ref short searchSpace, short value0, short value1, int length)
348+
private static int IndexOfAny<TNegator>(ref short searchSpace, short value0, short value1, int length)
352349
where TNegator : struct, SpanHelpers.INegator<short>
353350
{
354351
Debug.Assert(CanUsePackedIndexOf(value0));
@@ -498,7 +495,7 @@ private static int PackedIndexOfAny<TNegator>(ref short searchSpace, short value
498495
return -1;
499496
}
500497

501-
private static int PackedIndexOfAny<TNegator>(ref short searchSpace, short value0, short value1, short value2, int length)
498+
private static int IndexOfAny<TNegator>(ref short searchSpace, short value0, short value1, short value2, int length)
502499
where TNegator : struct, SpanHelpers.INegator<short>
503500
{
504501
Debug.Assert(CanUsePackedIndexOf(value0));
@@ -651,7 +648,7 @@ private static int PackedIndexOfAny<TNegator>(ref short searchSpace, short value
651648
return -1;
652649
}
653650

654-
private static int PackedIndexOfAnyInRange<TNegator>(ref short searchSpace, short lowInclusive, short rangeInclusive, int length)
651+
private static int IndexOfAnyInRange<TNegator>(ref short searchSpace, short lowInclusive, short rangeInclusive, int length)
655652
where TNegator : struct, SpanHelpers.INegator<short>
656653
{
657654
Debug.Assert(CanUsePackedIndexOf(lowInclusive));
@@ -798,15 +795,12 @@ private static Vector256<byte> PackSources(Vector256<short> source0, Vector256<s
798795
[MethodImpl(MethodImplOptions.AggressiveInlining)]
799796
private static Vector128<byte> PackSources(Vector128<short> source0, Vector128<short> source1)
800797
{
798+
Debug.Assert(Sse2.IsSupported);
801799
// Pack two vectors of characters into bytes. While the type is Vector128<short>, these are really UInt16 characters.
802800
// X86: Downcast every character using saturation.
803801
// - Values <= 32767 result in min(value, 255).
804802
// - Values > 32767 result in 0. Because of this we can't accept needles that contain 0.
805-
// ARM64: Do narrowing saturation over unsigned values.
806-
// - All values result in min(value, 255)
807-
return Sse2.IsSupported
808-
? Sse2.PackUnsignedSaturate(source0, source1).AsByte()
809-
: AdvSimd.ExtractNarrowingSaturateUpper(AdvSimd.ExtractNarrowingSaturateLower(source0.AsUInt16()), source1.AsUInt16());
803+
return Sse2.PackUnsignedSaturate(source0, source1).AsByte();
810804
}
811805

812806
[MethodImpl(MethodImplOptions.AggressiveInlining)]

0 commit comments

Comments
 (0)