From 707e56c90f33390e0e9e72fbc51ad7c1246219fb Mon Sep 17 00:00:00 2001
From: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
Date: Fri, 22 Mar 2024 12:01:59 -0700
Subject: [PATCH 1/5] Add AnyMatches() to iSimdVector interface

---
 .../src/System/Runtime/Intrinsics/ISimdVector_2.cs          | 6 ++++++
 .../src/System/Runtime/Intrinsics/Vector128_1.cs            | 5 +++++
 .../src/System/Runtime/Intrinsics/Vector256_1.cs            | 5 +++++
 .../src/System/Runtime/Intrinsics/Vector512_1.cs            | 5 +++++
 .../src/System/Runtime/Intrinsics/Vector64_1.cs             | 5 +++++
 5 files changed, 26 insertions(+)

diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs
index a1d49045bb2acd..3dd8a7dc27cbab 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs
@@ -553,6 +553,12 @@ static virtual bool TryCopyTo(TSelf vector, Span<T> destination)
         // New Surface Area
         //
 
+        /// <summary>Checks if the MSB of any of the vector lanes is non zero.</summary>
+        /// <param name="vector">The vector to check MSB.</param>
+        /// <returns><c>true</c> if <paramref name="vector" /> has any lanes with a non-zero MSB otherwise, <c>false</c> if MSB is zero for all lanes />.</returns>
+        /// <exception cref="NotSupportedException">The type of the elements in the vector (<typeparamref name="T" />) is not supported.</exception>
+        static abstract bool AnyMatches(TSelf vector);
+
         static abstract int IndexOfLastMatch(TSelf vector);
     }
 }
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs
index 42bef9fe0ed941..0cad8c6e045460 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs
@@ -692,6 +692,11 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri
         // New Surface Area
         //
 
+        static bool ISimdVector<Vector128<T>, T>.AnyMatches(Vector128<T> vector)
+        {
+            return (vector != Vector128<T>.Zero);
+        }
+
         static int ISimdVector<Vector128<T>, T>.IndexOfLastMatch(Vector128<T> vector)
         {
             uint mask = vector.ExtractMostSignificantBits();
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs
index fd1e889e44f244..d840f756d4eaaf 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs
@@ -682,6 +682,11 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri
         // New Surface Area
         //
 
+        static bool ISimdVector<Vector256<T>, T>.AnyMatches(Vector256<T> vector)
+        {
+            return (vector != Vector256<T>.Zero);
+        }
+
         static int ISimdVector<Vector256<T>, T>.IndexOfLastMatch(Vector256<T> vector)
         {
             uint mask = vector.ExtractMostSignificantBits();
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs
index 5c3f6a593ebfec..83aa03d328763f 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs
@@ -682,6 +682,11 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri
         // New Surface Area
         //
 
+        static bool ISimdVector<Vector512<T>, T>.AnyMatches(Vector512<T> vector)
+        {
+            return (vector != Vector512<T>.Zero);
+        }
+
         static int ISimdVector<Vector512<T>, T>.IndexOfLastMatch(Vector512<T> vector)
         {
             ulong mask = vector.ExtractMostSignificantBits();
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs
index 3ec5a675e61bc8..7525a16fad5820 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs
@@ -757,6 +757,11 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri
         // New Surface Area
         //
 
+        static bool ISimdVector<Vector64<T>, T>.AnyMatches(Vector64<T> vector)
+        {
+            return (vector != Vector64<T>.Zero);
+        }
+
         static int ISimdVector<Vector64<T>, T>.IndexOfLastMatch(Vector64<T> vector)
         {
             uint mask = vector.ExtractMostSignificantBits();

From 4b4f15ff2c9174dcae94be5a43da092c98ea5787 Mon Sep 17 00:00:00 2001
From: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
Date: Fri, 22 Mar 2024 12:02:30 -0700
Subject: [PATCH 2/5] Switch to iSimdVector and Align WidenAsciiToUtf16.

---
 .../src/System/Text/Ascii.Utility.cs          | 152 ++++++++++--------
 1 file changed, 84 insertions(+), 68 deletions(-)

diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs
index ba07b985b67058..824c51e9a028be 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs
@@ -2038,79 +2038,17 @@ internal static unsafe nuint WidenAsciiToUtf16(byte* pAsciiBuffer, char* pUtf16B
 
             if (BitConverter.IsLittleEndian && Vector128.IsHardwareAccelerated && elementCount >= (uint)Vector128<byte>.Count)
             {
-                ushort* pCurrentWriteAddress = (ushort*)pUtf16Buffer;
-
-                if (Vector512.IsHardwareAccelerated && elementCount >= (uint)Vector512<byte>.Count)
+                if (Vector512.IsHardwareAccelerated && (elementCount - currentOffset) >= (uint)Vector512<byte>.Count)
                 {
-                    // Calculating the destination address outside the loop results in significant
-                    // perf wins vs. relying on the JIT to fold memory addressing logic into the
-                    // write instructions. See: https://github.com/dotnet/runtime/issues/33002
-                    nuint finalOffsetWhereCanRunLoop = elementCount - (uint)Vector512<byte>.Count;
-
-                    do
-                    {
-                        Vector512<byte> asciiVector = Vector512.Load(pAsciiBuffer + currentOffset);
-
-                        if (asciiVector.ExtractMostSignificantBits() != 0)
-                        {
-                            break;
-                        }
-
-                        (Vector512<ushort> utf16LowVector, Vector512<ushort> utf16HighVector) = Vector512.Widen(asciiVector);
-                        utf16LowVector.Store(pCurrentWriteAddress);
-                        utf16HighVector.Store(pCurrentWriteAddress + Vector512<ushort>.Count);
-
-                        currentOffset += (nuint)Vector512<byte>.Count;
-                        pCurrentWriteAddress += (nuint)Vector512<byte>.Count;
-                    } while (currentOffset <= finalOffsetWhereCanRunLoop);
+                    WidenAsciiToUtf1_Vector<Vector512<byte>, Vector512<ushort>>(pAsciiBuffer, pUtf16Buffer, ref currentOffset, elementCount);
                 }
-                else if (Vector256.IsHardwareAccelerated && elementCount >= (uint)Vector256<byte>.Count)
+                else if (Vector256.IsHardwareAccelerated && (elementCount - currentOffset) >= (uint)Vector256<byte>.Count)
                 {
-                    // Calculating the destination address outside the loop results in significant
-                    // perf wins vs. relying on the JIT to fold memory addressing logic into the
-                    // write instructions. See: https://github.com/dotnet/runtime/issues/33002
-                    nuint finalOffsetWhereCanRunLoop = elementCount - (uint)Vector256<byte>.Count;
-
-                    do
-                    {
-                        Vector256<byte> asciiVector = Vector256.Load(pAsciiBuffer + currentOffset);
-
-                        if (asciiVector.ExtractMostSignificantBits() != 0)
-                        {
-                            break;
-                        }
-
-                        (Vector256<ushort> utf16LowVector, Vector256<ushort> utf16HighVector) = Vector256.Widen(asciiVector);
-                        utf16LowVector.Store(pCurrentWriteAddress);
-                        utf16HighVector.Store(pCurrentWriteAddress + Vector256<ushort>.Count);
-
-                        currentOffset += (nuint)Vector256<byte>.Count;
-                        pCurrentWriteAddress += (nuint)Vector256<byte>.Count;
-                    } while (currentOffset <= finalOffsetWhereCanRunLoop);
+                    WidenAsciiToUtf1_Vector<Vector256<byte>, Vector256<ushort>>(pAsciiBuffer, pUtf16Buffer, ref currentOffset, elementCount);
                 }
-                else
+                else if (Vector128.IsHardwareAccelerated && (elementCount - currentOffset) >= (uint)Vector128<byte>.Count)
                 {
-                    // Calculating the destination address outside the loop results in significant
-                    // perf wins vs. relying on the JIT to fold memory addressing logic into the
-                    // write instructions. See: https://github.com/dotnet/runtime/issues/33002
-                    nuint finalOffsetWhereCanRunLoop = elementCount - (uint)Vector128<byte>.Count;
-
-                    do
-                    {
-                        Vector128<byte> asciiVector = Vector128.Load(pAsciiBuffer + currentOffset);
-
-                        if (VectorContainsNonAsciiChar(asciiVector))
-                        {
-                            break;
-                        }
-
-                        (Vector128<ushort> utf16LowVector, Vector128<ushort> utf16HighVector) = Vector128.Widen(asciiVector);
-                        utf16LowVector.Store(pCurrentWriteAddress);
-                        utf16HighVector.Store(pCurrentWriteAddress + Vector128<ushort>.Count);
-
-                        currentOffset += (nuint)Vector128<byte>.Count;
-                        pCurrentWriteAddress += (nuint)Vector128<byte>.Count;
-                    } while (currentOffset <= finalOffsetWhereCanRunLoop);
+                    WidenAsciiToUtf1_Vector<Vector128<byte>, Vector128<ushort>>(pAsciiBuffer, pUtf16Buffer, ref currentOffset, elementCount);
                 }
             }
 
@@ -2212,6 +2150,84 @@ internal static unsafe nuint WidenAsciiToUtf16(byte* pAsciiBuffer, char* pUtf16B
             goto Finish;
         }
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static unsafe void WidenAsciiToUtf1_Vector<TVectorByte, TVectorUShort>(byte* pAsciiBuffer, char* pUtf16Buffer, ref nuint currentOffset, nuint elementCount)
+            where TVectorByte : unmanaged, ISimdVector<TVectorByte, byte>
+            where TVectorUShort : unmanaged, ISimdVector<TVectorUShort, ushort>
+        {
+            ushort* pCurrentWriteAddress = (ushort*)pUtf16Buffer;
+            // Calculating the destination address outside the loop results in significant
+            // perf wins vs. relying on the JIT to fold memory addressing logic into the
+            // write instructions. See: https://github.com/dotnet/runtime/issues/33002
+            nuint finalOffsetWhereCanRunLoop = elementCount - (nuint)TVectorByte.Count;
+            TVectorByte asciiVector = TVectorByte.Load(pAsciiBuffer + currentOffset);
+            if (!HasMatch<TVectorByte>(asciiVector))
+            {
+                (TVectorUShort utf16LowVector, TVectorUShort utf16HighVector) = Widen<TVectorByte, TVectorUShort>(asciiVector);
+                utf16LowVector.Store(pCurrentWriteAddress);
+                utf16HighVector.Store(pCurrentWriteAddress + TVectorUShort.Count);
+                pCurrentWriteAddress += (nuint)(TVectorUShort.Count * 2);
+                if (((int)pCurrentWriteAddress & 1) == 0)
+                {
+                    // Bump write buffer up to the next aligned boundary
+                    pCurrentWriteAddress = (ushort*)((nuint)pCurrentWriteAddress & ~(nuint)(TVectorUShort.Alignment - 1));
+                    nuint numBytesWritten = (nuint)pCurrentWriteAddress - (nuint)pUtf16Buffer;
+                    currentOffset += (nuint)numBytesWritten / 2;
+                }
+                else
+                {
+                    // If input isn't char aligned, we won't be able to align it to a Vector
+                    currentOffset += (nuint)TVectorByte.Count;
+                }
+                while (currentOffset <= finalOffsetWhereCanRunLoop)
+                {
+                    asciiVector = TVectorByte.Load(pAsciiBuffer + currentOffset);
+                    if (HasMatch<TVectorByte>(asciiVector))
+                    {
+                        break;
+                    }
+                    (utf16LowVector, utf16HighVector) = Widen<TVectorByte, TVectorUShort>(asciiVector);
+                    utf16LowVector.StoreAligned(pCurrentWriteAddress);
+                    utf16HighVector.StoreAligned(pCurrentWriteAddress + TVectorUShort.Count);
+                    currentOffset += (nuint)TVectorByte.Count;
+                    pCurrentWriteAddress += (nuint)(TVectorUShort.Count * 2);
+                }
+            }
+            return;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static unsafe bool HasMatch<TVectorByte>(TVectorByte vector)
+            where TVectorByte : unmanaged, ISimdVector<TVectorByte, byte>
+        {
+            if (AdvSimd.IsSupported && typeof(TVectorByte) == typeof(Vector128<byte>))
+            {
+                return VectorContainsNonAsciiChar((Vector128<byte>)(object)vector);
+            }
+            return ((vector & TVectorByte.Create((byte)0b1000_0000)) != TVectorByte.Zero);
+        }
+
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static unsafe (TVectorUShort Lower, TVectorUShort Upper) Widen<TVectorByte, TVectorUShort>(TVectorByte vector)
+            where TVectorByte : unmanaged, ISimdVector<TVectorByte, byte>
+            where TVectorUShort : unmanaged, ISimdVector<TVectorUShort, ushort>
+        {
+            if (typeof(TVectorByte) == typeof(Vector256<byte>))
+            {
+                (Vector256<ushort> Lower256, Vector256<ushort> Upper256) = Vector256.Widen((Vector256<byte>)(object)vector);
+                return ((TVectorUShort)(object)Lower256, (TVectorUShort)(object)Upper256);
+            }
+            else if (typeof(TVectorByte) == typeof(Vector512<byte>))
+            {
+                (Vector512<ushort> Lower512, Vector512<ushort> Upper512) = Vector512.Widen((Vector512<byte>)(object)vector);
+                return ((TVectorUShort)(object)Lower512, (TVectorUShort)(object)Upper512);
+            }
+            (Vector128<ushort> Lower128, Vector128<ushort> Upper128) = Vector128.Widen((Vector128<byte>)(object)vector);
+            return ((TVectorUShort)(object)Lower128, (TVectorUShort)(object)Upper128);
+        }
+
+
         /// <summary>
         /// Given a DWORD which represents a buffer of 4 bytes, widens the buffer into 4 WORDs and
         /// writes them to the output buffer with machine endianness.

From 2c7d258859686eb5ec1ef42e0a4785bb02cc2e07 Mon Sep 17 00:00:00 2001
From: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
Date: Tue, 26 Mar 2024 10:13:57 -0700
Subject: [PATCH 3/5] Fixing perf

---
 .../System.Private.CoreLib/src/System/Text/Ascii.Utility.cs | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs
index 824c51e9a028be..2b97588e410ddb 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs
@@ -2200,11 +2200,7 @@ private static unsafe void WidenAsciiToUtf1_Vector<TVectorByte, TVectorUShort>(b
         private static unsafe bool HasMatch<TVectorByte>(TVectorByte vector)
             where TVectorByte : unmanaged, ISimdVector<TVectorByte, byte>
         {
-            if (AdvSimd.IsSupported && typeof(TVectorByte) == typeof(Vector128<byte>))
-            {
-                return VectorContainsNonAsciiChar((Vector128<byte>)(object)vector);
-            }
-            return ((vector & TVectorByte.Create((byte)0b1000_0000)) != TVectorByte.Zero);
+            return !(vector & TVectorByte.Create((byte)0x80)).Equals(TVectorByte.Zero);
         }
 
 

From 90c509224472ae81fb50da0c4774f7c463973105 Mon Sep 17 00:00:00 2001
From: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
Date: Wed, 27 Mar 2024 14:55:20 -0700
Subject: [PATCH 4/5] Addressing Review Comments.

---
 .../src/System/Text/Ascii.Utility.cs          | 39 +++++++++++--------
 1 file changed, 22 insertions(+), 17 deletions(-)

diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs
index 2b97588e410ddb..76d2701b0eaabc 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs
@@ -2151,9 +2151,9 @@ internal static unsafe nuint WidenAsciiToUtf16(byte* pAsciiBuffer, char* pUtf16B
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static unsafe void WidenAsciiToUtf1_Vector<TVectorByte, TVectorUShort>(byte* pAsciiBuffer, char* pUtf16Buffer, ref nuint currentOffset, nuint elementCount)
+        private static unsafe void WidenAsciiToUtf1_Vector<TVectorByte, TVectorUInt16>(byte* pAsciiBuffer, char* pUtf16Buffer, ref nuint currentOffset, nuint elementCount)
             where TVectorByte : unmanaged, ISimdVector<TVectorByte, byte>
-            where TVectorUShort : unmanaged, ISimdVector<TVectorUShort, ushort>
+            where TVectorUInt16 : unmanaged, ISimdVector<TVectorUInt16, ushort>
         {
             ushort* pCurrentWriteAddress = (ushort*)pUtf16Buffer;
             // Calculating the destination address outside the loop results in significant
@@ -2163,14 +2163,14 @@ private static unsafe void WidenAsciiToUtf1_Vector<TVectorByte, TVectorUShort>(b
             TVectorByte asciiVector = TVectorByte.Load(pAsciiBuffer + currentOffset);
             if (!HasMatch<TVectorByte>(asciiVector))
             {
-                (TVectorUShort utf16LowVector, TVectorUShort utf16HighVector) = Widen<TVectorByte, TVectorUShort>(asciiVector);
+                (TVectorUInt16 utf16LowVector, TVectorUInt16 utf16HighVector) = Widen<TVectorByte, TVectorUInt16>(asciiVector);
                 utf16LowVector.Store(pCurrentWriteAddress);
-                utf16HighVector.Store(pCurrentWriteAddress + TVectorUShort.Count);
-                pCurrentWriteAddress += (nuint)(TVectorUShort.Count * 2);
-                if (((int)pCurrentWriteAddress & 1) == 0)
+                utf16HighVector.Store(pCurrentWriteAddress + TVectorUInt16.Count);
+                pCurrentWriteAddress += (nuint)(TVectorUInt16.Count * 2);
+                if (((nuint)pCurrentWriteAddress % sizeof(char)) == 0)
                 {
                     // Bump write buffer up to the next aligned boundary
-                    pCurrentWriteAddress = (ushort*)((nuint)pCurrentWriteAddress & ~(nuint)(TVectorUShort.Alignment - 1));
+                    pCurrentWriteAddress = (ushort*)((nuint)pCurrentWriteAddress & ~(nuint)(TVectorUInt16.Alignment - 1));
                     nuint numBytesWritten = (nuint)pCurrentWriteAddress - (nuint)pUtf16Buffer;
                     currentOffset += (nuint)numBytesWritten / 2;
                 }
@@ -2186,11 +2186,12 @@ private static unsafe void WidenAsciiToUtf1_Vector<TVectorByte, TVectorUShort>(b
                     {
                         break;
                     }
-                    (utf16LowVector, utf16HighVector) = Widen<TVectorByte, TVectorUShort>(asciiVector);
-                    utf16LowVector.StoreAligned(pCurrentWriteAddress);
-                    utf16HighVector.StoreAligned(pCurrentWriteAddress + TVectorUShort.Count);
+                    (utf16LowVector, utf16HighVector) = Widen<TVectorByte, TVectorUInt16>(asciiVector);
+                    utf16LowVector.Store(pCurrentWriteAddress);
+                    utf16HighVector.Store(pCurrentWriteAddress + TVectorUInt16.Count);
+
                     currentOffset += (nuint)TVectorByte.Count;
-                    pCurrentWriteAddress += (nuint)(TVectorUShort.Count * 2);
+                    pCurrentWriteAddress += (nuint)(TVectorUInt16.Count * 2);
                 }
             }
             return;
@@ -2205,22 +2206,26 @@ private static unsafe bool HasMatch<TVectorByte>(TVectorByte vector)
 
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static unsafe (TVectorUShort Lower, TVectorUShort Upper) Widen<TVectorByte, TVectorUShort>(TVectorByte vector)
+        private static unsafe (TVectorUInt16 Lower, TVectorUInt16 Upper) Widen<TVectorByte, TVectorUInt16>(TVectorByte vector)
             where TVectorByte : unmanaged, ISimdVector<TVectorByte, byte>
-            where TVectorUShort : unmanaged, ISimdVector<TVectorUShort, ushort>
+            where TVectorUInt16 : unmanaged, ISimdVector<TVectorUInt16, ushort>
         {
             if (typeof(TVectorByte) == typeof(Vector256<byte>))
             {
                 (Vector256<ushort> Lower256, Vector256<ushort> Upper256) = Vector256.Widen((Vector256<byte>)(object)vector);
-                return ((TVectorUShort)(object)Lower256, (TVectorUShort)(object)Upper256);
+                return ((TVectorUInt16)(object)Lower256, (TVectorUInt16)(object)Upper256);
             }
             else if (typeof(TVectorByte) == typeof(Vector512<byte>))
             {
                 (Vector512<ushort> Lower512, Vector512<ushort> Upper512) = Vector512.Widen((Vector512<byte>)(object)vector);
-                return ((TVectorUShort)(object)Lower512, (TVectorUShort)(object)Upper512);
+                return ((TVectorUInt16)(object)Lower512, (TVectorUInt16)(object)Upper512);
+            }
+            else
+            {
+                Debug.Assert(typeof(TVectorByte) == typeof(Vector128<byte>));
+                (Vector128<ushort> Lower128, Vector128<ushort> Upper128) = Vector128.Widen((Vector128<byte>)(object)vector);
+                return ((TVectorUInt16)(object)Lower128, (TVectorUInt16)(object)Upper128);
             }
-            (Vector128<ushort> Lower128, Vector128<ushort> Upper128) = Vector128.Widen((Vector128<byte>)(object)vector);
-            return ((TVectorUShort)(object)Lower128, (TVectorUShort)(object)Upper128);
         }
 
 

From 424c52af68cf302338dcb8aadf2ce21506df5ad3 Mon Sep 17 00:00:00 2001
From: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
Date: Thu, 4 Apr 2024 17:42:02 -0700
Subject: [PATCH 5/5] Mirroring API change :
 https://github.com/dotnet/runtime/issues/98055#issuecomment-2032720254

---
 .../System/Runtime/Intrinsics/ISimdVector_2.cs    | 15 +++++++++++----
 .../src/System/Runtime/Intrinsics/Vector128_1.cs  |  9 +++++++--
 .../src/System/Runtime/Intrinsics/Vector256_1.cs  |  9 +++++++--
 .../src/System/Runtime/Intrinsics/Vector512_1.cs  |  9 +++++++--
 .../src/System/Runtime/Intrinsics/Vector64_1.cs   |  9 +++++++--
 5 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs
index 3dd8a7dc27cbab..a88b5f0dec6a1e 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs
@@ -553,11 +553,18 @@ static virtual bool TryCopyTo(TSelf vector, Span<T> destination)
         // New Surface Area
         //
 
-        /// <summary>Checks if the MSB of any of the vector lanes is non zero.</summary>
-        /// <param name="vector">The vector to check MSB.</param>
-        /// <returns><c>true</c> if <paramref name="vector" /> has any lanes with a non-zero MSB otherwise, <c>false</c> if MSB is zero for all lanes />.</returns>
+        /// <summary>Checks if any of the vector lanes are equivalent to value.</summary>
+        /// <param name="vector">The Vector.</param>
+        /// <param name="value">The Value to check.</param>
+        /// <returns><c>true</c> if <paramref name="vector" /> has any lanes equivalent to <paramref name="value" /> otherwise, <c>false</c> if none of the lanes are equivalent to <paramref name="value" /> />.</returns>
         /// <exception cref="NotSupportedException">The type of the elements in the vector (<typeparamref name="T" />) is not supported.</exception>
-        static abstract bool AnyMatches(TSelf vector);
+        static abstract bool Any(TSelf vector, T value);
+
+        /// <summary>Checks if any of the vector lanes have All Bits set.</summary>
+        /// <param name="vector">The Vector to check.</param>
+        /// <returns><c>true</c> if <paramref name="vector" /> has any lanes with All Bits set otherwise, <c>false</c> if none of the lanes have All Bits set />.</returns>
+        /// <exception cref="NotSupportedException">The type of the elements in the vector (<typeparamref name="T" />) is not supported.</exception>
+        static abstract bool AnyWhereAllBitsSet(TSelf vector);
 
         static abstract int IndexOfLastMatch(TSelf vector);
     }
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs
index 0cad8c6e045460..efa2f1f148b929 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs
@@ -692,9 +692,14 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri
         // New Surface Area
         //
 
-        static bool ISimdVector<Vector128<T>, T>.AnyMatches(Vector128<T> vector)
+        static bool ISimdVector<Vector128<T>, T>.AnyWhereAllBitsSet(Vector128<T> vector)
         {
-            return (vector != Vector128<T>.Zero);
+            return (Vector128.EqualsAny(vector, Vector128<T>.AllBitsSet));
+        }
+
+        static bool ISimdVector<Vector128<T>, T>.Any(Vector128<T> vector, T value)
+        {
+            return (Vector128.EqualsAny(vector, Vector128.Create((T)value)));
         }
 
         static int ISimdVector<Vector128<T>, T>.IndexOfLastMatch(Vector128<T> vector)
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs
index d840f756d4eaaf..af789a873535c3 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs
@@ -682,9 +682,14 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri
         // New Surface Area
         //
 
-        static bool ISimdVector<Vector256<T>, T>.AnyMatches(Vector256<T> vector)
+        static bool ISimdVector<Vector256<T>, T>.AnyWhereAllBitsSet(Vector256<T> vector)
         {
-            return (vector != Vector256<T>.Zero);
+            return (Vector256.EqualsAny(vector, Vector256<T>.AllBitsSet));
+        }
+
+        static bool ISimdVector<Vector256<T>, T>.Any(Vector256<T> vector, T value)
+        {
+            return (Vector256.EqualsAny(vector, Vector256.Create((T)value)));
         }
 
         static int ISimdVector<Vector256<T>, T>.IndexOfLastMatch(Vector256<T> vector)
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs
index 83aa03d328763f..c6e42c63c44f52 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs
@@ -682,9 +682,14 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri
         // New Surface Area
         //
 
-        static bool ISimdVector<Vector512<T>, T>.AnyMatches(Vector512<T> vector)
+        static bool ISimdVector<Vector512<T>, T>.AnyWhereAllBitsSet(Vector512<T> vector)
         {
-            return (vector != Vector512<T>.Zero);
+            return (Vector512.EqualsAny(vector, Vector512<T>.AllBitsSet));
+        }
+
+        static bool ISimdVector<Vector512<T>, T>.Any(Vector512<T> vector, T value)
+        {
+            return (Vector512.EqualsAny(vector, Vector512.Create((T)value)));
         }
 
         static int ISimdVector<Vector512<T>, T>.IndexOfLastMatch(Vector512<T> vector)
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs
index 7525a16fad5820..241a2c294e4e33 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs
@@ -757,9 +757,14 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri
         // New Surface Area
         //
 
-        static bool ISimdVector<Vector64<T>, T>.AnyMatches(Vector64<T> vector)
+        static bool ISimdVector<Vector64<T>, T>.AnyWhereAllBitsSet(Vector64<T> vector)
         {
-            return (vector != Vector64<T>.Zero);
+            return (Vector64.EqualsAny(vector, Vector64<T>.AllBitsSet));
+        }
+
+        static bool ISimdVector<Vector64<T>, T>.Any(Vector64<T> vector, T value)
+        {
+            return (Vector64.EqualsAny(vector, Vector64.Create((T)value)));
         }
 
         static int ISimdVector<Vector64<T>, T>.IndexOfLastMatch(Vector64<T> vector)
