Skip to content

Commit 5ebf7d4

Browse files
authored
Simplify IndexOfAnyAsciiByteValues for needles with 0 on X86 (#82866)
1 parent 6e422d6 commit 5ebf7d4

File tree

4 files changed

+18
-62
lines changed

4 files changed

+18
-62
lines changed

src/libraries/System.Memory/tests/Span/IndexOfAnyValues.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -496,8 +496,8 @@ private static ReadOnlySpan<T> GetRandomSlice<T>(Random rng, ReadOnlySpan<T> spa
496496
private static void AssertionFailed<T>(ReadOnlySpan<T> haystack, ReadOnlySpan<T> needle, int expected, int actual, string approach)
497497
where T : INumber<T>
498498
{
499-
string readableHaystack = string.Join(", ", haystack.ToString().Select(c => int.CreateChecked(c)));
500-
string readableNeedle = string.Join(", ", needle.ToString().Select(c => int.CreateChecked(c)));
499+
string readableHaystack = string.Join(", ", haystack.ToArray().Select(c => int.CreateChecked(c)));
500+
string readableNeedle = string.Join(", ", needle.ToArray().Select(c => int.CreateChecked(c)));
501501

502502
Assert.True(false, $"Expected {expected}, got {approach}={actual} for needle='{readableNeedle}', haystack='{readableHaystack}'");
503503
}

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

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,13 @@
77

88
namespace System.Buffers
99
{
10-
internal sealed class IndexOfAnyAsciiByteValues<TOptimizations> : IndexOfAnyValues<byte>
11-
where TOptimizations : struct, IndexOfAnyAsciiSearcher.IOptimizations
10+
internal sealed class IndexOfAnyAsciiByteValues : IndexOfAnyValues<byte>
1211
{
1312
private readonly Vector128<byte> _bitmap;
1413
private readonly BitVector256 _lookup;
1514

16-
public IndexOfAnyAsciiByteValues(Vector128<byte> bitmap, BitVector256 lookup)
17-
{
18-
_bitmap = bitmap;
19-
_lookup = lookup;
20-
}
15+
public IndexOfAnyAsciiByteValues(ReadOnlySpan<byte> values) =>
16+
IndexOfAnyAsciiSearcher.ComputeBitmap(values, out _bitmap, out _lookup);
2117

2218
internal override byte[] GetValues() => _lookup.GetByteValues();
2319

@@ -46,7 +42,7 @@ private int IndexOfAny<TNegator>(ref byte searchSpace, int searchSpaceLength)
4642
where TNegator : struct, IndexOfAnyAsciiSearcher.INegator
4743
{
4844
return IndexOfAnyAsciiSearcher.IsVectorizationSupported && searchSpaceLength >= sizeof(ulong)
49-
? IndexOfAnyAsciiSearcher.IndexOfAnyVectorized<TNegator, TOptimizations>(ref searchSpace, searchSpaceLength, _bitmap)
45+
? IndexOfAnyAsciiSearcher.IndexOfAnyVectorized<TNegator>(ref searchSpace, searchSpaceLength, _bitmap)
5046
: IndexOfAnyScalar<TNegator>(ref searchSpace, searchSpaceLength);
5147
}
5248

@@ -55,7 +51,7 @@ private int LastIndexOfAny<TNegator>(ref byte searchSpace, int searchSpaceLength
5551
where TNegator : struct, IndexOfAnyAsciiSearcher.INegator
5652
{
5753
return IndexOfAnyAsciiSearcher.IsVectorizationSupported && searchSpaceLength >= sizeof(ulong)
58-
? IndexOfAnyAsciiSearcher.LastIndexOfAnyVectorized<TNegator, TOptimizations>(ref searchSpace, searchSpaceLength, _bitmap)
54+
? IndexOfAnyAsciiSearcher.LastIndexOfAnyVectorized<TNegator>(ref searchSpace, searchSpaceLength, _bitmap)
5955
: LastIndexOfAnyScalar<TNegator>(ref searchSpace, searchSpaceLength);
6056
}
6157

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

Lines changed: 10 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -384,9 +384,8 @@ internal static int LastIndexOfAnyVectorized<TNegator, TOptimizations>(ref short
384384
return -1;
385385
}
386386

387-
internal static int IndexOfAnyVectorized<TNegator, TOptimizations>(ref byte searchSpace, int searchSpaceLength, Vector128<byte> bitmap)
387+
internal static int IndexOfAnyVectorized<TNegator>(ref byte searchSpace, int searchSpaceLength, Vector128<byte> bitmap)
388388
where TNegator : struct, INegator
389-
where TOptimizations : struct, IOptimizations
390389
{
391390
ref byte currentSearchSpace = ref searchSpace;
392391

@@ -408,7 +407,7 @@ internal static int IndexOfAnyVectorized<TNegator, TOptimizations>(ref byte sear
408407
{
409408
Vector256<byte> source = Vector256.LoadUnsafe(ref currentSearchSpace);
410409

411-
Vector256<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap256);
410+
Vector256<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap256));
412411
if (result != Vector256<byte>.Zero)
413412
{
414413
return ComputeFirstIndex<byte, TNegator>(ref searchSpace, ref currentSearchSpace, result);
@@ -433,7 +432,7 @@ internal static int IndexOfAnyVectorized<TNegator, TOptimizations>(ref byte sear
433432
Vector128<byte> source1 = Vector128.LoadUnsafe(ref halfVectorAwayFromEnd);
434433
Vector256<byte> source = Vector256.Create(source0, source1);
435434

436-
Vector256<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap256);
435+
Vector256<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap256));
437436
if (result != Vector256<byte>.Zero)
438437
{
439438
return ComputeFirstIndexOverlapped<byte, TNegator>(ref searchSpace, ref firstVector, ref halfVectorAwayFromEnd, result);
@@ -454,7 +453,7 @@ internal static int IndexOfAnyVectorized<TNegator, TOptimizations>(ref byte sear
454453
{
455454
Vector128<byte> source = Vector128.LoadUnsafe(ref currentSearchSpace);
456455

457-
Vector128<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap);
456+
Vector128<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap));
458457
if (result != Vector128<byte>.Zero)
459458
{
460459
return ComputeFirstIndex<byte, TNegator>(ref searchSpace, ref currentSearchSpace, result);
@@ -480,7 +479,7 @@ internal static int IndexOfAnyVectorized<TNegator, TOptimizations>(ref byte sear
480479
ulong source1 = Unsafe.ReadUnaligned<ulong>(ref halfVectorAwayFromEnd);
481480
Vector128<byte> source = Vector128.Create(source0, source1).AsByte();
482481

483-
Vector128<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap);
482+
Vector128<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap));
484483
if (result != Vector128<byte>.Zero)
485484
{
486485
return ComputeFirstIndexOverlapped<byte, TNegator>(ref searchSpace, ref firstVector, ref halfVectorAwayFromEnd, result);
@@ -490,9 +489,8 @@ internal static int IndexOfAnyVectorized<TNegator, TOptimizations>(ref byte sear
490489
return -1;
491490
}
492491

493-
internal static int LastIndexOfAnyVectorized<TNegator, TOptimizations>(ref byte searchSpace, int searchSpaceLength, Vector128<byte> bitmap)
492+
internal static int LastIndexOfAnyVectorized<TNegator>(ref byte searchSpace, int searchSpaceLength, Vector128<byte> bitmap)
494493
where TNegator : struct, INegator
495-
where TOptimizations : struct, IOptimizations
496494
{
497495
ref byte currentSearchSpace = ref Unsafe.Add(ref searchSpace, searchSpaceLength);
498496

@@ -516,7 +514,7 @@ internal static int LastIndexOfAnyVectorized<TNegator, TOptimizations>(ref byte
516514

517515
Vector256<byte> source = Vector256.LoadUnsafe(ref currentSearchSpace);
518516

519-
Vector256<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap256);
517+
Vector256<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap256));
520518
if (result != Vector256<byte>.Zero)
521519
{
522520
return ComputeLastIndex<byte, TNegator>(ref searchSpace, ref currentSearchSpace, result);
@@ -539,7 +537,7 @@ internal static int LastIndexOfAnyVectorized<TNegator, TOptimizations>(ref byte
539537
Vector128<byte> source1 = Vector128.LoadUnsafe(ref secondVector);
540538
Vector256<byte> source = Vector256.Create(source0, source1);
541539

542-
Vector256<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap256);
540+
Vector256<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap256));
543541
if (result != Vector256<byte>.Zero)
544542
{
545543
return ComputeLastIndexOverlapped<byte, TNegator>(ref searchSpace, ref secondVector, result);
@@ -562,7 +560,7 @@ internal static int LastIndexOfAnyVectorized<TNegator, TOptimizations>(ref byte
562560

563561
Vector128<byte> source = Vector128.LoadUnsafe(ref currentSearchSpace);
564562

565-
Vector128<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap);
563+
Vector128<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap));
566564
if (result != Vector128<byte>.Zero)
567565
{
568566
return ComputeLastIndex<byte, TNegator>(ref searchSpace, ref currentSearchSpace, result);
@@ -586,7 +584,7 @@ internal static int LastIndexOfAnyVectorized<TNegator, TOptimizations>(ref byte
586584
ulong source1 = Unsafe.ReadUnaligned<ulong>(ref secondVector);
587585
Vector128<byte> source = Vector128.Create(source0, source1).AsByte();
588586

589-
Vector128<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap);
587+
Vector128<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap));
590588
if (result != Vector128<byte>.Zero)
591589
{
592590
return ComputeLastIndexOverlapped<byte, TNegator>(ref searchSpace, ref secondVector, result);
@@ -840,23 +838,6 @@ private static Vector128<byte> IndexOfAnyLookup<TNegator, TOptimizations>(Vector
840838
return TNegator.NegateIfNeeded(result);
841839
}
842840

843-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
844-
private static Vector128<byte> IndexOfAnyLookup<TNegator, TOptimizations>(Vector128<byte> source, Vector128<byte> bitmapLookup)
845-
where TNegator : struct, INegator
846-
where TOptimizations : struct, IOptimizations
847-
{
848-
Vector128<byte> result = IndexOfAnyLookupCore(source, bitmapLookup);
849-
850-
// On X86, values above 127 will map to 0. If 0 is present in the needle, we must clear the false positives.
851-
if (TOptimizations.NeedleContainsZero)
852-
{
853-
Vector128<byte> ascii = Vector128.LessThan(source, Vector128.Create((byte)128));
854-
result &= ascii;
855-
}
856-
857-
return TNegator.NegateIfNeeded(result);
858-
}
859-
860841
[MethodImpl(MethodImplOptions.AggressiveInlining)]
861842
private static Vector128<byte> IndexOfAnyLookupCore(Vector128<byte> source, Vector128<byte> bitmapLookup)
862843
{
@@ -903,23 +884,6 @@ private static Vector256<byte> IndexOfAnyLookup<TNegator, TOptimizations>(Vector
903884
return TNegator.NegateIfNeeded(result);
904885
}
905886

906-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
907-
private static Vector256<byte> IndexOfAnyLookup<TNegator, TOptimizations>(Vector256<byte> source, Vector256<byte> bitmapLookup)
908-
where TNegator : struct, INegator
909-
where TOptimizations : struct, IOptimizations
910-
{
911-
// See comments in IndexOfAnyLookup(Vector128<byte>) above for more details.
912-
Vector256<byte> result = IndexOfAnyLookupCore(source, bitmapLookup);
913-
914-
if (TOptimizations.NeedleContainsZero)
915-
{
916-
Vector256<byte> ascii = Vector256.LessThan(source, Vector256.Create((byte)128));
917-
result &= ascii;
918-
}
919-
920-
return TNegator.NegateIfNeeded(result);
921-
}
922-
923887
[MethodImpl(MethodImplOptions.AggressiveInlining)]
924888
private static Vector256<byte> IndexOfAnyLookupCore(Vector256<byte> source, Vector256<byte> bitmapLookup)
925889
{

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,7 @@ public static IndexOfAnyValues<byte> Create(ReadOnlySpan<byte> values)
5656

5757
if (IndexOfAnyAsciiSearcher.IsVectorizationSupported && maxInclusive < 128)
5858
{
59-
IndexOfAnyAsciiSearcher.ComputeBitmap(values, out Vector128<byte> bitmap, out BitVector256 lookup);
60-
61-
return Ssse3.IsSupported && lookup.Contains(0)
62-
? new IndexOfAnyAsciiByteValues<IndexOfAnyAsciiSearcher.Ssse3HandleZeroInNeedle>(bitmap, lookup)
63-
: new IndexOfAnyAsciiByteValues<IndexOfAnyAsciiSearcher.Default>(bitmap, lookup);
59+
return new IndexOfAnyAsciiByteValues(values);
6460
}
6561

6662
return new IndexOfAnyByteValues(values);

0 commit comments

Comments
 (0)