From 4e50a40dd7903006c02460935d8a50edf518542c Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 8 Apr 2022 01:38:21 +0300 Subject: [PATCH 01/12] Fast path for OrdinalIgnoreCase IndexOf --- .../src/System/Globalization/Ordinal.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs index 60e6f3647c2cc..ad5ebdfb08c81 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Text.Unicode; using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; namespace System.Globalization { @@ -236,6 +237,33 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly return CompareInfo.NlsIndexOfOrdinalCore(source, value, ignoreCase: true, fromBeginning: true); } + if (Vector128.IsHardwareAccelerated && (source.Length > Vector128.Count)) + { + char c = value[0]; + if (char.IsAscii(c)) + { + int candidatePos; + if (char.IsInRange(c, 'a', 'z')) + { + // Search for the first occurrence of c or its ToUpper + candidatePos = source.IndexOfAny(c, (char)(c & ~0x20)); + } + else if (char.IsInRange(c, 'A', 'Z')) + { + // Search for the first occurrence of c or its ToLower + candidatePos = source.IndexOfAny(c, (char)(c | 0x20)); + } + else + { + // Search for first occurrence of c only + candidatePos = source.IndexOf(c); + } + if (candidatePos == -1) + return candidatePos; + return IndexOfOrdinalIgnoreCase(source.Slice(candidatePos), value); + } + } + return OrdinalCasing.IndexOf(source, value); } From 60d29aa5442989dc8884bc3a2f900ce5441a0049 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 8 Apr 2022 16:30:45 +0300 Subject: [PATCH 02/12] Better version --- .../src/System/Globalization/Ordinal.cs | 63 +++++++++++-------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs index ad5ebdfb08c81..db28757e4a19a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Text.Unicode; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Runtime.Intrinsics; namespace System.Globalization @@ -224,7 +225,7 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly // target strings can never be found inside small search spaces. This check also // handles empty 'source' spans. - return -1; + goto NOT_FOUND; } if (GlobalizationMode.Invariant) @@ -237,34 +238,46 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly return CompareInfo.NlsIndexOfOrdinalCore(source, value, ignoreCase: true, fromBeginning: true); } - if (Vector128.IsHardwareAccelerated && (source.Length > Vector128.Count)) + // if value starts with an ASCII char we can use a vectorized path + ref char valueRef = ref MemoryMarshal.GetReference(value); + char valueChar = valueRef; + + if (!char.IsAscii(valueChar)) { - char c = value[0]; - if (char.IsAscii(c)) + // Fallback to a more non-ASCII friendly version + return OrdinalCasing.IndexOf(source, value); + } + + ref char searchSpace = ref MemoryMarshal.GetReference(source); + int valueLength = value.Length; + int searchSpaceLength = source.Length; + + do + { + // if val is either [a..z] or [A..Z] - search for its lower and upper counter parts using IndexOfAny + // otherwise use just plain IndexOf + int candidatePos = (uint)((valueChar | 0x20) - 'a') <= 'z' - 'a' ? + SpanHelpers.IndexOfAny(ref searchSpace, (char)(valueChar & ~0x20), (char)(valueChar | 0x20), searchSpaceLength) : + SpanHelpers.IndexOf(ref searchSpace, valueChar, searchSpaceLength); + + if (candidatePos == -1) { - int candidatePos; - if (char.IsInRange(c, 'a', 'z')) - { - // Search for the first occurrence of c or its ToUpper - candidatePos = source.IndexOfAny(c, (char)(c & ~0x20)); - } - else if (char.IsInRange(c, 'A', 'Z')) - { - // Search for the first occurrence of c or its ToLower - candidatePos = source.IndexOfAny(c, (char)(c | 0x20)); - } - else - { - // Search for first occurrence of c only - candidatePos = source.IndexOf(c); - } - if (candidatePos == -1) - return candidatePos; - return IndexOfOrdinalIgnoreCase(source.Slice(candidatePos), value); + // the whole input doesn't contain the first char + goto NOT_FOUND; } - } - return OrdinalCasing.IndexOf(source, value); + // Do ASCII and non-ASCII friendly compare for the current candidate + if (EqualsIgnoreCase(ref searchSpace, ref valueRef, valueLength)) + { + return source.Length - searchSpaceLength; + } + + searchSpace = Unsafe.Add(ref searchSpace, (nuint)(candidatePos + valueLength)); + searchSpaceLength -= candidatePos + valueLength; + } while (searchSpaceLength >= valueLength); + + NOT_FOUND: + return -1; } internal static int LastIndexOf(string source, string value, int startIndex, int count) From 6f53de3dbdf96614753a9123c1a4793ff6862d5c Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 8 Apr 2022 16:47:19 +0300 Subject: [PATCH 03/12] Address feedback --- .../src/System/Globalization/Ordinal.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs index db28757e4a19a..885ad3bcb1d97 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs @@ -267,7 +267,11 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly } // Do ASCII and non-ASCII friendly compare for the current candidate - if (EqualsIgnoreCase(ref searchSpace, ref valueRef, valueLength)) + // Since we already know first chars match we ignore them and inspect valueLength - 1 + if (EqualsIgnoreCase( + ref Unsafe.Add(ref searchSpace, (nuint)(candidatePos + 1)), + ref Unsafe.Add(ref valueRef, (nuint)1), + valueLength - 1)) { return source.Length - searchSpaceLength; } From a465788d8689039a23ead9b854731eb037a80425 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 8 Apr 2022 16:59:16 +0300 Subject: [PATCH 04/12] Address feedback --- .../src/System/Globalization/Ordinal.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs index 885ad3bcb1d97..6ba659132a016 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs @@ -260,9 +260,10 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly SpanHelpers.IndexOfAny(ref searchSpace, (char)(valueChar & ~0x20), (char)(valueChar | 0x20), searchSpaceLength) : SpanHelpers.IndexOf(ref searchSpace, valueChar, searchSpaceLength); - if (candidatePos == -1) + if ((candidatePos == -1) || (searchSpaceLength - candidatePos) < valueLength) { - // the whole input doesn't contain the first char + // the whole input doesn't contain the first char or it does + // but there is no room left to fit the value goto NOT_FOUND; } From 0fc51cf0b7def43759e62e10ff9e6f55aea6e553 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 8 Apr 2022 17:23:21 +0300 Subject: [PATCH 05/12] fix final position --- .../System.Private.CoreLib/src/System/Globalization/Ordinal.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs index 6ba659132a016..1d63cfae405d6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs @@ -274,7 +274,7 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly ref Unsafe.Add(ref valueRef, (nuint)1), valueLength - 1)) { - return source.Length - searchSpaceLength; + return source.Length - searchSpaceLength + candidatePos; } searchSpace = Unsafe.Add(ref searchSpace, (nuint)(candidatePos + valueLength)); From 58bf3967e6ddc163c749eb12816fb778f17e2094 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 8 Apr 2022 19:30:24 +0300 Subject: [PATCH 06/12] Rewrite based on https://github.com/dotnet/runtime/blob/20c4bde6b1b8b7afb173abf730a10eb10c6be55e/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Char.cs#L41-L66 --- .../src/System/Globalization/Ordinal.cs | 76 +++++++++++++------ 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs index 1d63cfae405d6..f77e2fa680cff 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs @@ -224,8 +224,7 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly // A non-linguistic search compares chars directly against one another, so large // target strings can never be found inside small search spaces. This check also // handles empty 'source' spans. - - goto NOT_FOUND; + return -1; } if (GlobalizationMode.Invariant) @@ -248,40 +247,69 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly return OrdinalCasing.IndexOf(source, value); } + + int valueTailLength = value.Length - 1; + ref char valueTail = ref Unsafe.Add(ref valueRef, 1); ref char searchSpace = ref MemoryMarshal.GetReference(source); - int valueLength = value.Length; - int searchSpaceLength = source.Length; + int remainingSearchSpaceLength = source.Length - valueTailLength; + + // hoist some expressions from the loop + char valueCharU = default; + char valueCharL = default; + bool isLetter = false; + nint offset = 0; - do + if ((uint)((valueChar | 0x20) - 'a') <= 'z' - 'a') { - // if val is either [a..z] or [A..Z] - search for its lower and upper counter parts using IndexOfAny - // otherwise use just plain IndexOf - int candidatePos = (uint)((valueChar | 0x20) - 'a') <= 'z' - 'a' ? - SpanHelpers.IndexOfAny(ref searchSpace, (char)(valueChar & ~0x20), (char)(valueChar | 0x20), searchSpaceLength) : - SpanHelpers.IndexOf(ref searchSpace, valueChar, searchSpaceLength); + valueCharU = (char)(valueChar & ~0x20); + valueCharL = (char)(valueChar | 0x20); + isLetter = true; + } - if ((candidatePos == -1) || (searchSpaceLength - candidatePos) < valueLength) + while (remainingSearchSpaceLength > 0) + { + int relativeIndex; + if (isLetter) { - // the whole input doesn't contain the first char or it does - // but there is no room left to fit the value - goto NOT_FOUND; + relativeIndex = + SpanHelpers.IndexOfAny( + ref Unsafe.Add(ref searchSpace, offset), + valueCharU, + valueCharL, + remainingSearchSpaceLength); } + else + { + relativeIndex = + SpanHelpers.IndexOf( + ref Unsafe.Add(ref searchSpace, offset), + valueChar, + remainingSearchSpaceLength); + } + + // Do a quick search for the first element of "value". + if (relativeIndex < 0) + break; - // Do ASCII and non-ASCII friendly compare for the current candidate - // Since we already know first chars match we ignore them and inspect valueLength - 1 + remainingSearchSpaceLength -= relativeIndex; + offset += relativeIndex; + + if (remainingSearchSpaceLength <= 0) + break; // The unsearched portion is now shorter than the sequence we're looking for. So it can't be there. + + // Found the first element of "value". See if the tail matches. if (EqualsIgnoreCase( - ref Unsafe.Add(ref searchSpace, (nuint)(candidatePos + 1)), - ref Unsafe.Add(ref valueRef, (nuint)1), - valueLength - 1)) + ref Unsafe.Add(ref searchSpace, (nuint)(offset + 1)), + ref valueTail, + valueTailLength)) { - return source.Length - searchSpaceLength + candidatePos; + return (int)offset; // The tail matched. Return a successful find. } - searchSpace = Unsafe.Add(ref searchSpace, (nuint)(candidatePos + valueLength)); - searchSpaceLength -= candidatePos + valueLength; - } while (searchSpaceLength >= valueLength); + remainingSearchSpaceLength--; + offset++; + } - NOT_FOUND: return -1; } From 489b5d1d3b165aca5029c0da3ce792ecc8a627bd Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 8 Apr 2022 19:40:59 +0300 Subject: [PATCH 07/12] clean up --- .../src/System/Globalization/Ordinal.cs | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs index f77e2fa680cff..a6c51f904b3a5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs @@ -247,17 +247,15 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly return OrdinalCasing.IndexOf(source, value); } - + // hoist some expressions from the loop int valueTailLength = value.Length - 1; + int remainingSearchSpaceLength = source.Length - valueTailLength; ref char valueTail = ref Unsafe.Add(ref valueRef, 1); ref char searchSpace = ref MemoryMarshal.GetReference(source); - int remainingSearchSpaceLength = source.Length - valueTailLength; - - // hoist some expressions from the loop char valueCharU = default; char valueCharL = default; - bool isLetter = false; nint offset = 0; + bool isLetter = false; if ((uint)((valueChar | 0x20) - 'a') <= 'z' - 'a') { @@ -266,42 +264,36 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly isLetter = true; } - while (remainingSearchSpaceLength > 0) + do { int relativeIndex; if (isLetter) { - relativeIndex = - SpanHelpers.IndexOfAny( - ref Unsafe.Add(ref searchSpace, offset), - valueCharU, - valueCharL, - remainingSearchSpaceLength); + relativeIndex = SpanHelpers.IndexOfAny(ref Unsafe.Add(ref searchSpace, offset), + valueCharU, valueCharL, remainingSearchSpaceLength); } else { - relativeIndex = - SpanHelpers.IndexOf( - ref Unsafe.Add(ref searchSpace, offset), - valueChar, - remainingSearchSpaceLength); + relativeIndex = SpanHelpers.IndexOf(ref Unsafe.Add(ref searchSpace, offset), + valueChar, remainingSearchSpaceLength); } // Do a quick search for the first element of "value". if (relativeIndex < 0) + { break; + } remainingSearchSpaceLength -= relativeIndex; offset += relativeIndex; if (remainingSearchSpaceLength <= 0) - break; // The unsearched portion is now shorter than the sequence we're looking for. So it can't be there. + { + break; + } // Found the first element of "value". See if the tail matches. - if (EqualsIgnoreCase( - ref Unsafe.Add(ref searchSpace, (nuint)(offset + 1)), - ref valueTail, - valueTailLength)) + if (EqualsIgnoreCase(ref Unsafe.Add(ref searchSpace, (nuint)(offset + 1)), ref valueTail, valueTailLength)) { return (int)offset; // The tail matched. Return a successful find. } @@ -309,6 +301,7 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly remainingSearchSpaceLength--; offset++; } + while (remainingSearchSpaceLength > 0); return -1; } From 4a478c06524937f31f6bae8a66674234d7b5b875 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 8 Apr 2022 19:49:23 +0300 Subject: [PATCH 08/12] Clean up --- .../src/System/Globalization/Ordinal.cs | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs index a6c51f904b3a5..791c5d32803be 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs @@ -248,9 +248,7 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly } // hoist some expressions from the loop - int valueTailLength = value.Length - 1; - int remainingSearchSpaceLength = source.Length - valueTailLength; - ref char valueTail = ref Unsafe.Add(ref valueRef, 1); + int searchSpaceLength = source.Length - value.Length - 1; ref char searchSpace = ref MemoryMarshal.GetReference(source); char valueCharU = default; char valueCharL = default; @@ -266,17 +264,9 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly do { - int relativeIndex; - if (isLetter) - { - relativeIndex = SpanHelpers.IndexOfAny(ref Unsafe.Add(ref searchSpace, offset), - valueCharU, valueCharL, remainingSearchSpaceLength); - } - else - { - relativeIndex = SpanHelpers.IndexOf(ref Unsafe.Add(ref searchSpace, offset), - valueChar, remainingSearchSpaceLength); - } + int relativeIndex = isLetter ? + SpanHelpers.IndexOfAny(ref Unsafe.Add(ref searchSpace, offset), valueCharU, valueCharL, searchSpaceLength) : + SpanHelpers.IndexOf(ref Unsafe.Add(ref searchSpace, offset), valueChar, searchSpaceLength); // Do a quick search for the first element of "value". if (relativeIndex < 0) @@ -284,24 +274,26 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly break; } - remainingSearchSpaceLength -= relativeIndex; + searchSpaceLength -= relativeIndex; offset += relativeIndex; - if (remainingSearchSpaceLength <= 0) + if (searchSpaceLength <= 0) { break; } // Found the first element of "value". See if the tail matches. - if (EqualsIgnoreCase(ref Unsafe.Add(ref searchSpace, (nuint)(offset + 1)), ref valueTail, valueTailLength)) + if (EqualsIgnoreCase( + ref Unsafe.Add(ref searchSpace, (nuint)(offset + 1)), + ref Unsafe.Add(ref valueRef, 1), value.Length - 1)) { return (int)offset; // The tail matched. Return a successful find. } - remainingSearchSpaceLength--; + searchSpaceLength--; offset++; } - while (remainingSearchSpaceLength > 0); + while (searchSpaceLength > 0); return -1; } From 373caf4de31c934dca92975ab9e2ba6692aaff99 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 8 Apr 2022 21:14:22 +0300 Subject: [PATCH 09/12] fix bug introduced during clean up --- .../System.Private.CoreLib/src/System/Globalization/Ordinal.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs index 791c5d32803be..22bf491d79ba7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs @@ -248,7 +248,7 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly } // hoist some expressions from the loop - int searchSpaceLength = source.Length - value.Length - 1; + int searchSpaceLength = source.Length - (value.Length - 1); ref char searchSpace = ref MemoryMarshal.GetReference(source); char valueCharU = default; char valueCharL = default; From 9dc2f0035716197e5a098415e5e62dd8c6b27140 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 9 Apr 2022 00:01:15 +0300 Subject: [PATCH 10/12] Address feedback --- .../src/System/Globalization/Ordinal.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs index 22bf491d79ba7..bc9141b2a283e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs @@ -248,7 +248,8 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly } // hoist some expressions from the loop - int searchSpaceLength = source.Length - (value.Length - 1); + int valueTailLength = value.Length - 1; + int searchSpaceLength = source.Length - valueTailLength; ref char searchSpace = ref MemoryMarshal.GetReference(source); char valueCharU = default; char valueCharL = default; @@ -275,17 +276,17 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly } searchSpaceLength -= relativeIndex; - offset += relativeIndex; - if (searchSpaceLength <= 0) { break; } + offset += relativeIndex; // Found the first element of "value". See if the tail matches. - if (EqualsIgnoreCase( + if (valueTailLength == 0 || // for single-char values we already matched first chars + EqualsIgnoreCase( ref Unsafe.Add(ref searchSpace, (nuint)(offset + 1)), - ref Unsafe.Add(ref valueRef, 1), value.Length - 1)) + ref Unsafe.Add(ref valueRef, 1), valueTailLength)) { return (int)offset; // The tail matched. Return a successful find. } From 03f9bea0ce89d66915e3598b83291992f7362b5f Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 9 Apr 2022 00:02:54 +0300 Subject: [PATCH 11/12] clean up --- .../System.Private.CoreLib/src/System/Globalization/Ordinal.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs index bc9141b2a283e..cbc937fa543a8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs @@ -5,7 +5,6 @@ using System.Text.Unicode; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Runtime.Intrinsics; namespace System.Globalization { @@ -224,6 +223,7 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly // A non-linguistic search compares chars directly against one another, so large // target strings can never be found inside small search spaces. This check also // handles empty 'source' spans. + return -1; } From 2361ae7040273e435bd1f1cf1dffe294a0700550 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Sat, 9 Apr 2022 01:21:18 +0300 Subject: [PATCH 12/12] Apply suggestions from code review Co-authored-by: Stephen Toub --- .../src/System/Globalization/Ordinal.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs index cbc937fa543a8..133330d4acf19 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs @@ -237,7 +237,7 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly return CompareInfo.NlsIndexOfOrdinalCore(source, value, ignoreCase: true, fromBeginning: true); } - // if value starts with an ASCII char we can use a vectorized path + // If value starts with an ASCII char, we can use a vectorized path ref char valueRef = ref MemoryMarshal.GetReference(value); char valueChar = valueRef; @@ -247,7 +247,7 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly return OrdinalCasing.IndexOf(source, value); } - // hoist some expressions from the loop + // Hoist some expressions from the loop int valueTailLength = value.Length - 1; int searchSpaceLength = source.Length - valueTailLength; ref char searchSpace = ref MemoryMarshal.GetReference(source); @@ -265,11 +265,10 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly do { + // Do a quick search for the first element of "value". int relativeIndex = isLetter ? SpanHelpers.IndexOfAny(ref Unsafe.Add(ref searchSpace, offset), valueCharU, valueCharL, searchSpaceLength) : SpanHelpers.IndexOf(ref Unsafe.Add(ref searchSpace, offset), valueChar, searchSpaceLength); - - // Do a quick search for the first element of "value". if (relativeIndex < 0) { break;