|
5 | 5 | using System.Text.Unicode;
|
6 | 6 | using System.Runtime.CompilerServices;
|
7 | 7 | using System.Runtime.InteropServices;
|
| 8 | +using System.Runtime.Intrinsics; |
8 | 9 |
|
9 | 10 | namespace System.Globalization
|
10 | 11 | {
|
@@ -75,7 +76,62 @@ internal static int CompareStringIgnoreCaseNonAscii(ref char strA, int lengthA,
|
75 | 76 | return OrdinalCasing.CompareStringIgnoreCase(ref strA, lengthA, ref strB, lengthB);
|
76 | 77 | }
|
77 | 78 |
|
| 79 | + private static bool EqualsIgnoreCase_Vector128(ref char charA, ref char charB, int length) |
| 80 | + { |
| 81 | + Debug.Assert(length >= Vector128<ushort>.Count); |
| 82 | + Debug.Assert(Vector128.IsHardwareAccelerated); |
| 83 | + |
| 84 | + nuint lengthU = (nuint)length; |
| 85 | + nuint lengthToExamine = lengthU - (nuint)Vector128<ushort>.Count; |
| 86 | + nuint i = 0; |
| 87 | + Vector128<ushort> vec1; |
| 88 | + Vector128<ushort> vec2; |
| 89 | + do |
| 90 | + { |
| 91 | + vec1 = Vector128.LoadUnsafe(ref Unsafe.As<char, ushort>(ref charA), i); |
| 92 | + vec2 = Vector128.LoadUnsafe(ref Unsafe.As<char, ushort>(ref charB), i); |
| 93 | + |
| 94 | + if (!Utf16Utility.AllCharsInVector128AreAscii(vec1 | vec2)) |
| 95 | + { |
| 96 | + goto NON_ASCII; |
| 97 | + } |
| 98 | + |
| 99 | + if (!Utf16Utility.Vector128OrdinalIgnoreCaseAscii(vec1, vec2)) |
| 100 | + { |
| 101 | + return false; |
| 102 | + } |
| 103 | + |
| 104 | + i += (nuint)Vector128<ushort>.Count; |
| 105 | + } while (i <= lengthToExamine); |
| 106 | + |
| 107 | + // Use scalar path for trailing elements |
| 108 | + return i == lengthU || EqualsIgnoreCase(ref Unsafe.Add(ref charA, i), ref Unsafe.Add(ref charB, i), (int)(lengthU - i)); |
| 109 | + |
| 110 | + NON_ASCII: |
| 111 | + if (Utf16Utility.AllCharsInVector128AreAscii(vec1) || Utf16Utility.AllCharsInVector128AreAscii(vec2)) |
| 112 | + { |
| 113 | + // No need to use the fallback if one of the inputs is full-ASCII |
| 114 | + return false; |
| 115 | + } |
| 116 | + |
| 117 | + // Fallback for Non-ASCII inputs |
| 118 | + return CompareStringIgnoreCase( |
| 119 | + ref Unsafe.Add(ref charA, i), (int)(lengthU - i), |
| 120 | + ref Unsafe.Add(ref charB, i), (int)(lengthU - i)) == 0; |
| 121 | + } |
| 122 | + |
| 123 | + [MethodImpl(MethodImplOptions.AggressiveInlining)] |
78 | 124 | internal static bool EqualsIgnoreCase(ref char charA, ref char charB, int length)
|
| 125 | + { |
| 126 | + if (!Vector128.IsHardwareAccelerated || length < Vector128<ushort>.Count) |
| 127 | + { |
| 128 | + return EqualsIgnoreCase_Scalar(ref charA, ref charB, length); |
| 129 | + } |
| 130 | + |
| 131 | + return EqualsIgnoreCase_Vector128(ref charA, ref charB, length); |
| 132 | + } |
| 133 | + |
| 134 | + internal static bool EqualsIgnoreCase_Scalar(ref char charA, ref char charB, int length) |
79 | 135 | {
|
80 | 136 | IntPtr byteOffset = IntPtr.Zero;
|
81 | 137 |
|
|
0 commit comments