SpanHelpers use nuint rather than byte* and IntPtr (#35765)
authorBen Adams <thundercat@illyriad.co.uk>
Sun, 3 May 2020 18:41:25 +0000 (19:41 +0100)
committerGitHub <noreply@github.com>
Sun, 3 May 2020 18:41:25 +0000 (11:41 -0700)
* SpanHelpers use nuint rather than byte* and IntPtr

* uint cast BitOperations

* Cast to uint before casting to nuint

src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs
src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Char.cs

index a657ceb..f965f98 100644 (file)
@@ -105,13 +105,13 @@ namespace System
 
         // Adapted from IndexOf(...)
         [MethodImpl(MethodImplOptions.AggressiveOptimization)]
-        public static unsafe bool Contains(ref byte searchSpace, byte value, int length)
+        public static bool Contains(ref byte searchSpace, byte value, int length)
         {
             Debug.Assert(length >= 0);
 
             uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions
-            IntPtr offset = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
-            IntPtr lengthToExamine = (IntPtr)length;
+            nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations
+            nuint lengthToExamine = (nuint)(uint)length;
 
             if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
             {
@@ -119,7 +119,7 @@ namespace System
             }
 
         SequentialScan:
-            while ((byte*)lengthToExamine >= (byte*)8)
+            while (lengthToExamine >= 8)
             {
                 lengthToExamine -= 8;
 
@@ -138,7 +138,7 @@ namespace System
                 offset += 8;
             }
 
-            if ((byte*)lengthToExamine >= (byte*)4)
+            if (lengthToExamine >= 4)
             {
                 lengthToExamine -= 4;
 
@@ -153,7 +153,7 @@ namespace System
                 offset += 4;
             }
 
-            while ((byte*)lengthToExamine > (byte*)0)
+            while (lengthToExamine > 0)
             {
                 lengthToExamine -= 1;
 
@@ -163,27 +163,27 @@ namespace System
                 offset += 1;
             }
 
-            if (Vector.IsHardwareAccelerated && ((int)(byte*)offset < length))
+            if (Vector.IsHardwareAccelerated && (offset < (nuint)(uint)length))
             {
-                lengthToExamine = (IntPtr)((length - (int)(byte*)offset) & ~(Vector<byte>.Count - 1));
+                lengthToExamine = (((nuint)(uint)length - offset) & (nuint)~(Vector<byte>.Count - 1));
 
                 Vector<byte> values = new Vector<byte>(value);
 
-                while ((byte*)lengthToExamine > (byte*)offset)
+                while (lengthToExamine > offset)
                 {
                     var matches = Vector.Equals(values, LoadVector(ref searchSpace, offset));
                     if (Vector<byte>.Zero.Equals(matches))
                     {
-                        offset += Vector<byte>.Count;
+                        offset += (nuint)Vector<byte>.Count;
                         continue;
                     }
 
                     goto Found;
                 }
 
-                if ((int)(byte*)offset < length)
+                if (offset < (nuint)(uint)length)
                 {
-                    lengthToExamine = (IntPtr)(length - (int)(byte*)offset);
+                    lengthToExamine = ((nuint)(uint)length - offset);
                     goto SequentialScan;
                 }
             }
@@ -200,8 +200,8 @@ namespace System
             Debug.Assert(length >= 0);
 
             uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions
-            IntPtr offset = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
-            IntPtr lengthToExamine = (IntPtr)length;
+            nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations
+            nuint lengthToExamine = (nuint)(uint)length;
 
             if (Avx2.IsSupported || Sse2.IsSupported)
             {
@@ -219,7 +219,7 @@ namespace System
                 }
             }
         SequentialScan:
-            while ((byte*)lengthToExamine >= (byte*)8)
+            while (lengthToExamine >= 8)
             {
                 lengthToExamine -= 8;
 
@@ -243,7 +243,7 @@ namespace System
                 offset += 8;
             }
 
-            if ((byte*)lengthToExamine >= (byte*)4)
+            if (lengthToExamine >= 4)
             {
                 lengthToExamine -= 4;
 
@@ -259,7 +259,7 @@ namespace System
                 offset += 4;
             }
 
-            while ((byte*)lengthToExamine > (byte*)0)
+            while (lengthToExamine > 0)
             {
                 lengthToExamine -= 1;
 
@@ -274,9 +274,9 @@ namespace System
             // have hardware accelerated. After processing Vector lengths we return to SequentialScan to finish any remaining.
             if (Avx2.IsSupported)
             {
-                if ((int)(byte*)offset < length)
+                if (offset < (nuint)(uint)length)
                 {
-                    if ((((nuint)Unsafe.AsPointer(ref searchSpace) + (nuint)offset) & (nuint)(Vector256<byte>.Count - 1)) != 0)
+                    if ((((nuint)(uint)Unsafe.AsPointer(ref searchSpace) + offset) & (nuint)(Vector256<byte>.Count - 1)) != 0)
                     {
                         // Not currently aligned to Vector256 (is aligned to Vector128); this can cause a problem for searches
                         // with no upper bound e.g. String.strlen.
@@ -290,17 +290,17 @@ namespace System
                         if (matches == 0)
                         {
                             // Zero flags set so no matches
-                            offset += Vector128<byte>.Count;
+                            offset += (nuint)Vector128<byte>.Count;
                         }
                         else
                         {
                             // Find bitflag offset of first match and add to current offset
-                            return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
+                            return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches));
                         }
                     }
 
                     lengthToExamine = GetByteVector256SpanLength(offset, length);
-                    if ((byte*)lengthToExamine > (byte*)offset)
+                    if (lengthToExamine > offset)
                     {
                         Vector256<byte> values = Vector256.Create(value);
                         do
@@ -312,17 +312,17 @@ namespace System
                             if (matches == 0)
                             {
                                 // Zero flags set so no matches
-                                offset += Vector256<byte>.Count;
+                                offset += (nuint)Vector256<byte>.Count;
                                 continue;
                             }
 
                             // Find bitflag offset of first match and add to current offset
-                            return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
-                        } while ((byte*)lengthToExamine > (byte*)offset);
+                            return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches));
+                        } while (lengthToExamine > offset);
                     }
 
                     lengthToExamine = GetByteVector128SpanLength(offset, length);
-                    if ((byte*)lengthToExamine > (byte*)offset)
+                    if (lengthToExamine > offset)
                     {
                         Vector128<byte> values = Vector128.Create(value);
                         Vector128<byte> search = LoadVector128(ref searchSpace, offset);
@@ -332,30 +332,30 @@ namespace System
                         if (matches == 0)
                         {
                             // Zero flags set so no matches
-                            offset += Vector128<byte>.Count;
+                            offset += (nuint)Vector128<byte>.Count;
                         }
                         else
                         {
                             // Find bitflag offset of first match and add to current offset
-                            return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
+                            return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches));
                         }
                     }
 
-                    if ((int)(byte*)offset < length)
+                    if (offset < (nuint)(uint)length)
                     {
-                        lengthToExamine = (IntPtr)(length - (int)(byte*)offset);
+                        lengthToExamine = ((nuint)(uint)length - offset);
                         goto SequentialScan;
                     }
                 }
             }
             else if (Sse2.IsSupported)
             {
-                if ((int)(byte*)offset < length)
+                if (offset < (nuint)(uint)length)
                 {
                     lengthToExamine = GetByteVector128SpanLength(offset, length);
 
                     Vector128<byte> values = Vector128.Create(value);
-                    while ((byte*)lengthToExamine > (byte*)offset)
+                    while (lengthToExamine > offset)
                     {
                         Vector128<byte> search = LoadVector128(ref searchSpace, offset);
 
@@ -364,66 +364,66 @@ namespace System
                         if (matches == 0)
                         {
                             // Zero flags set so no matches
-                            offset += Vector128<byte>.Count;
+                            offset += (nuint)Vector128<byte>.Count;
                             continue;
                         }
 
                         // Find bitflag offset of first match and add to current offset
-                        return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
+                        return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches));
                     }
 
-                    if ((int)(byte*)offset < length)
+                    if (offset < (nuint)(uint)length)
                     {
-                        lengthToExamine = (IntPtr)(length - (int)(byte*)offset);
+                        lengthToExamine = ((nuint)(uint)length - offset);
                         goto SequentialScan;
                     }
                 }
             }
             else if (Vector.IsHardwareAccelerated)
             {
-                if ((int)(byte*)offset < length)
+                if (offset < (nuint)(uint)length)
                 {
                     lengthToExamine = GetByteVectorSpanLength(offset, length);
 
                     Vector<byte> values = new Vector<byte>(value);
 
-                    while ((byte*)lengthToExamine > (byte*)offset)
+                    while (lengthToExamine > offset)
                     {
                         var matches = Vector.Equals(values, LoadVector(ref searchSpace, offset));
                         if (Vector<byte>.Zero.Equals(matches))
                         {
-                            offset += Vector<byte>.Count;
+                            offset += (nuint)Vector<byte>.Count;
                             continue;
                         }
 
                         // Find offset of first match and add to current offset
-                        return (int)(byte*)offset + LocateFirstFoundByte(matches);
+                        return (int)offset + LocateFirstFoundByte(matches);
                     }
 
-                    if ((int)(byte*)offset < length)
+                    if (offset < (nuint)(uint)length)
                     {
-                        lengthToExamine = (IntPtr)(length - (int)(byte*)offset);
+                        lengthToExamine = ((nuint)(uint)length - offset);
                         goto SequentialScan;
                     }
                 }
             }
             return -1;
         Found: // Workaround for https://github.com/dotnet/runtime/issues/8795
-            return (int)(byte*)offset;
+            return (int)offset;
         Found1:
-            return (int)(byte*)(offset + 1);
+            return (int)(offset + 1);
         Found2:
-            return (int)(byte*)(offset + 2);
+            return (int)(offset + 2);
         Found3:
-            return (int)(byte*)(offset + 3);
+            return (int)(offset + 3);
         Found4:
-            return (int)(byte*)(offset + 4);
+            return (int)(offset + 4);
         Found5:
-            return (int)(byte*)(offset + 5);
+            return (int)(offset + 5);
         Found6:
-            return (int)(byte*)(offset + 6);
+            return (int)(offset + 6);
         Found7:
-            return (int)(byte*)(offset + 7);
+            return (int)(offset + 7);
         }
 
         public static int LastIndexOf(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength)
@@ -452,7 +452,7 @@ namespace System
                     break;
 
                 // Found the first element of "value". See if the tail matches.
-                if (SequenceEqual(ref Unsafe.Add(ref searchSpace, relativeIndex + 1), ref valueTail, (nuint)valueTailLength))  // The (nunit)-cast is necessary to pick the correct overload
+                if (SequenceEqual(ref Unsafe.Add(ref searchSpace, relativeIndex + 1), ref valueTail, (nuint)(uint)valueTailLength))  // The (nunit)-cast is necessary to pick the correct overload
                     return relativeIndex;  // The tail matched. Return a successful find.
 
                 offset += remainingSearchSpaceLength - relativeIndex;
@@ -461,20 +461,20 @@ namespace System
         }
 
         [MethodImpl(MethodImplOptions.AggressiveOptimization)]
-        public static unsafe int LastIndexOf(ref byte searchSpace, byte value, int length)
+        public static int LastIndexOf(ref byte searchSpace, byte value, int length)
         {
             Debug.Assert(length >= 0);
 
             uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions
-            IntPtr offset = (IntPtr)length; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
-            IntPtr lengthToExamine = (IntPtr)length;
+            nuint offset = (nuint)(uint)length; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations
+            nuint lengthToExamine = (nuint)(uint)length;
 
             if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
             {
                 lengthToExamine = UnalignedCountVectorFromEnd(ref searchSpace, length);
             }
         SequentialScan:
-            while ((byte*)lengthToExamine >= (byte*)8)
+            while (lengthToExamine >= 8)
             {
                 lengthToExamine -= 8;
                 offset -= 8;
@@ -497,7 +497,7 @@ namespace System
                     goto Found;
             }
 
-            if ((byte*)lengthToExamine >= (byte*)4)
+            if (lengthToExamine >= 4)
             {
                 lengthToExamine -= 4;
                 offset -= 4;
@@ -512,7 +512,7 @@ namespace System
                     goto Found;
             }
 
-            while ((byte*)lengthToExamine > (byte*)0)
+            while (lengthToExamine > 0)
             {
                 lengthToExamine -= 1;
                 offset -= 1;
@@ -521,26 +521,26 @@ namespace System
                     goto Found;
             }
 
-            if (Vector.IsHardwareAccelerated && ((byte*)offset > (byte*)0))
+            if (Vector.IsHardwareAccelerated && (offset > 0))
             {
-                lengthToExamine = (IntPtr)((int)(byte*)offset & ~(Vector<byte>.Count - 1));
+                lengthToExamine = (offset & (nuint)~(Vector<byte>.Count - 1));
 
                 Vector<byte> values = new Vector<byte>(value);
 
-                while ((byte*)lengthToExamine > (byte*)(Vector<byte>.Count - 1))
+                while (lengthToExamine > (nuint)(Vector<byte>.Count - 1))
                 {
-                    var matches = Vector.Equals(values, LoadVector(ref searchSpace, offset - Vector<byte>.Count));
+                    var matches = Vector.Equals(values, LoadVector(ref searchSpace, offset - (nuint)Vector<byte>.Count));
                     if (Vector<byte>.Zero.Equals(matches))
                     {
-                        offset -= Vector<byte>.Count;
-                        lengthToExamine -= Vector<byte>.Count;
+                        offset -= (nuint)Vector<byte>.Count;
+                        lengthToExamine -= (nuint)Vector<byte>.Count;
                         continue;
                     }
 
                     // Find offset of first match and add to current offset
                     return (int)(offset) - Vector<byte>.Count + LocateLastFoundByte(matches);
                 }
-                if ((byte*)offset > (byte*)0)
+                if (offset > 0)
                 {
                     lengthToExamine = offset;
                     goto SequentialScan;
@@ -548,32 +548,32 @@ namespace System
             }
             return -1;
         Found: // Workaround for https://github.com/dotnet/runtime/issues/8795
-            return (int)(byte*)offset;
+            return (int)offset;
         Found1:
-            return (int)(byte*)(offset + 1);
+            return (int)(offset + 1);
         Found2:
-            return (int)(byte*)(offset + 2);
+            return (int)(offset + 2);
         Found3:
-            return (int)(byte*)(offset + 3);
+            return (int)(offset + 3);
         Found4:
-            return (int)(byte*)(offset + 4);
+            return (int)(offset + 4);
         Found5:
-            return (int)(byte*)(offset + 5);
+            return (int)(offset + 5);
         Found6:
-            return (int)(byte*)(offset + 6);
+            return (int)(offset + 6);
         Found7:
-            return (int)(byte*)(offset + 7);
+            return (int)(offset + 7);
         }
 
         [MethodImpl(MethodImplOptions.AggressiveOptimization)]
-        public static unsafe int IndexOfAny(ref byte searchSpace, byte value0, byte value1, int length)
+        public static int IndexOfAny(ref byte searchSpace, byte value0, byte value1, int length)
         {
             Debug.Assert(length >= 0);
 
             uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
             uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions
-            IntPtr offset = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
-            IntPtr lengthToExamine = (IntPtr)length;
+            nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations
+            nuint lengthToExamine = (nuint)(uint)length;
 
             if (Avx2.IsSupported || Sse2.IsSupported)
             {
@@ -592,7 +592,7 @@ namespace System
             }
         SequentialScan:
             uint lookUp;
-            while ((byte*)lengthToExamine >= (byte*)8)
+            while (lengthToExamine >= 8)
             {
                 lengthToExamine -= 8;
 
@@ -624,7 +624,7 @@ namespace System
                 offset += 8;
             }
 
-            if ((byte*)lengthToExamine >= (byte*)4)
+            if (lengthToExamine >= 4)
             {
                 lengthToExamine -= 4;
 
@@ -644,7 +644,7 @@ namespace System
                 offset += 4;
             }
 
-            while ((byte*)lengthToExamine > (byte*)0)
+            while (lengthToExamine > 0)
             {
                 lengthToExamine -= 1;
 
@@ -659,10 +659,10 @@ namespace System
             // the JIT to see that the code is unreachable and eliminate it when the platform does not have hardware accelerated.
             if (Avx2.IsSupported)
             {
-                if ((int)(byte*)offset < length)
+                if (offset < (nuint)(uint)length)
                 {
                     lengthToExamine = GetByteVector256SpanLength(offset, length);
-                    if ((byte*)lengthToExamine > (byte*)offset)
+                    if (lengthToExamine > offset)
                     {
                         Vector256<byte> values0 = Vector256.Create(value0);
                         Vector256<byte> values1 = Vector256.Create(value1);
@@ -679,17 +679,17 @@ namespace System
                             if (matches == 0)
                             {
                                 // Zero flags set so no matches
-                                offset += Vector256<byte>.Count;
+                                offset += (nuint)Vector256<byte>.Count;
                                 continue;
                             }
 
                             // Find bitflag offset of first match and add to current offset
-                            return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
-                        } while ((byte*)lengthToExamine > (byte*)offset);
+                            return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches));
+                        } while (lengthToExamine > offset);
                     }
 
                     lengthToExamine = GetByteVector128SpanLength(offset, length);
-                    if ((byte*)lengthToExamine > (byte*)offset)
+                    if (lengthToExamine > offset)
                     {
                         Vector128<byte> values0 = Vector128.Create(value0);
                         Vector128<byte> values1 = Vector128.Create(value1);
@@ -703,32 +703,32 @@ namespace System
                         if (matches == 0)
                         {
                             // Zero flags set so no matches
-                            offset += Vector128<byte>.Count;
+                            offset += (nuint)Vector128<byte>.Count;
                         }
                         else
                         {
                             // Find bitflag offset of first match and add to current offset
-                            return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
+                            return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches));
                         }
                     }
 
-                    if ((int)(byte*)offset < length)
+                    if (offset < (nuint)(uint)length)
                     {
-                        lengthToExamine = (IntPtr)(length - (int)(byte*)offset);
+                        lengthToExamine = ((nuint)(uint)length - offset);
                         goto SequentialScan;
                     }
                 }
             }
             else if (Sse2.IsSupported)
             {
-                if ((int)(byte*)offset < length)
+                if (offset < (nuint)(uint)length)
                 {
                     lengthToExamine = GetByteVector128SpanLength(offset, length);
 
                     Vector128<byte> values0 = Vector128.Create(value0);
                     Vector128<byte> values1 = Vector128.Create(value1);
 
-                    while ((byte*)lengthToExamine > (byte*)offset)
+                    while (lengthToExamine > offset)
                     {
                         Vector128<byte> search = LoadVector128(ref searchSpace, offset);
                         // Same method as above
@@ -739,31 +739,31 @@ namespace System
                         if (matches == 0)
                         {
                             // Zero flags set so no matches
-                            offset += Vector128<byte>.Count;
+                            offset += (nuint)Vector128<byte>.Count;
                             continue;
                         }
 
                         // Find bitflag offset of first match and add to current offset
-                        return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
+                        return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches));
                     }
 
-                    if ((int)(byte*)offset < length)
+                    if (offset < (nuint)(uint)length)
                     {
-                        lengthToExamine = (IntPtr)(length - (int)(byte*)offset);
+                        lengthToExamine = ((nuint)(uint)length - offset);
                         goto SequentialScan;
                     }
                 }
             }
             else if (Vector.IsHardwareAccelerated)
             {
-                if ((int)(byte*)offset < length)
+                if (offset < (nuint)(uint)length)
                 {
                     lengthToExamine = GetByteVectorSpanLength(offset, length);
 
                     Vector<byte> values0 = new Vector<byte>(value0);
                     Vector<byte> values1 = new Vector<byte>(value1);
 
-                    while ((byte*)lengthToExamine > (byte*)offset)
+                    while (lengthToExamine > offset)
                     {
                         Vector<byte> search = LoadVector(ref searchSpace, offset);
                         var matches = Vector.BitwiseOr(
@@ -771,50 +771,50 @@ namespace System
                                         Vector.Equals(search, values1));
                         if (Vector<byte>.Zero.Equals(matches))
                         {
-                            offset += Vector<byte>.Count;
+                            offset += (nuint)Vector<byte>.Count;
                             continue;
                         }
 
                         // Find offset of first match and add to current offset
-                        return (int)(byte*)offset + LocateFirstFoundByte(matches);
+                        return (int)offset + LocateFirstFoundByte(matches);
                     }
 
-                    if ((int)(byte*)offset < length)
+                    if (offset < (nuint)(uint)length)
                     {
-                        lengthToExamine = (IntPtr)(length - (int)(byte*)offset);
+                        lengthToExamine = ((nuint)(uint)length - offset);
                         goto SequentialScan;
                     }
                 }
             }
             return -1;
         Found: // Workaround for https://github.com/dotnet/runtime/issues/8795
-            return (int)(byte*)offset;
+            return (int)offset;
         Found1:
-            return (int)(byte*)(offset + 1);
+            return (int)(offset + 1);
         Found2:
-            return (int)(byte*)(offset + 2);
+            return (int)(offset + 2);
         Found3:
-            return (int)(byte*)(offset + 3);
+            return (int)(offset + 3);
         Found4:
-            return (int)(byte*)(offset + 4);
+            return (int)(offset + 4);
         Found5:
-            return (int)(byte*)(offset + 5);
+            return (int)(offset + 5);
         Found6:
-            return (int)(byte*)(offset + 6);
+            return (int)(offset + 6);
         Found7:
-            return (int)(byte*)(offset + 7);
+            return (int)(offset + 7);
         }
 
         [MethodImpl(MethodImplOptions.AggressiveOptimization)]
-        public static unsafe int IndexOfAny(ref byte searchSpace, byte value0, byte value1, byte value2, int length)
+        public static int IndexOfAny(ref byte searchSpace, byte value0, byte value1, byte value2, int length)
         {
             Debug.Assert(length >= 0);
 
             uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
             uint uValue1 = value1;
             uint uValue2 = value2;
-            IntPtr offset = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
-            IntPtr lengthToExamine = (IntPtr)length;
+            nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations
+            nuint lengthToExamine = (nuint)(uint)length;
 
             if (Avx2.IsSupported || Sse2.IsSupported)
             {
@@ -833,7 +833,7 @@ namespace System
             }
         SequentialScan:
             uint lookUp;
-            while ((byte*)lengthToExamine >= (byte*)8)
+            while (lengthToExamine >= 8)
             {
                 lengthToExamine -= 8;
 
@@ -865,7 +865,7 @@ namespace System
                 offset += 8;
             }
 
-            if ((byte*)lengthToExamine >= (byte*)4)
+            if (lengthToExamine >= 4)
             {
                 lengthToExamine -= 4;
 
@@ -885,7 +885,7 @@ namespace System
                 offset += 4;
             }
 
-            while ((byte*)lengthToExamine > (byte*)0)
+            while (lengthToExamine > 0)
             {
                 lengthToExamine -= 1;
 
@@ -898,10 +898,10 @@ namespace System
 
             if (Avx2.IsSupported)
             {
-                if ((int)(byte*)offset < length)
+                if (offset < (nuint)(uint)length)
                 {
                     lengthToExamine = GetByteVector256SpanLength(offset, length);
-                    if ((byte*)lengthToExamine > (byte*)offset)
+                    if (lengthToExamine > offset)
                     {
                         Vector256<byte> values0 = Vector256.Create(value0);
                         Vector256<byte> values1 = Vector256.Create(value1);
@@ -920,17 +920,17 @@ namespace System
                             if (matches == 0)
                             {
                                 // Zero flags set so no matches
-                                offset += Vector256<byte>.Count;
+                                offset += (nuint)Vector256<byte>.Count;
                                 continue;
                             }
 
                             // Find bitflag offset of first match and add to current offset
-                            return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
-                        } while ((byte*)lengthToExamine > (byte*)offset);
+                            return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches));
+                        } while (lengthToExamine > offset);
                     }
 
                     lengthToExamine = GetByteVector128SpanLength(offset, length);
-                    if ((byte*)lengthToExamine > (byte*)offset)
+                    if (lengthToExamine > offset)
                     {
                         Vector128<byte> values0 = Vector128.Create(value0);
                         Vector128<byte> values1 = Vector128.Create(value1);
@@ -946,25 +946,25 @@ namespace System
                         if (matches == 0)
                         {
                             // Zero flags set so no matches
-                            offset += Vector128<byte>.Count;
+                            offset += (nuint)Vector128<byte>.Count;
                         }
                         else
                         {
                             // Find bitflag offset of first match and add to current offset
-                            return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
+                            return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches));
                         }
                     }
 
-                    if ((int)(byte*)offset < length)
+                    if (offset < (nuint)(uint)length)
                     {
-                        lengthToExamine = (IntPtr)(length - (int)(byte*)offset);
+                        lengthToExamine = ((nuint)(uint)length - offset);
                         goto SequentialScan;
                     }
                 }
             }
             else if (Sse2.IsSupported)
             {
-                if ((int)(byte*)offset < length)
+                if (offset < (nuint)(uint)length)
                 {
                     lengthToExamine = GetByteVector128SpanLength(offset, length);
 
@@ -972,7 +972,7 @@ namespace System
                     Vector128<byte> values1 = Vector128.Create(value1);
                     Vector128<byte> values2 = Vector128.Create(value2);
 
-                    while ((byte*)lengthToExamine > (byte*)offset)
+                    while (lengthToExamine > offset)
                     {
                         Vector128<byte> search = LoadVector128(ref searchSpace, offset);
 
@@ -984,24 +984,24 @@ namespace System
                         if (matches == 0)
                         {
                             // Zero flags set so no matches
-                            offset += Vector128<byte>.Count;
+                            offset += (nuint)Vector128<byte>.Count;
                             continue;
                         }
 
                         // Find bitflag offset of first match and add to current offset
-                        return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
+                        return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches));
                     }
 
-                    if ((int)(byte*)offset < length)
+                    if (offset < (nuint)(uint)length)
                     {
-                        lengthToExamine = (IntPtr)(length - (int)(byte*)offset);
+                        lengthToExamine = ((nuint)(uint)length - offset);
                         goto SequentialScan;
                     }
                 }
             }
             else if (Vector.IsHardwareAccelerated)
             {
-                if ((int)(byte*)offset < length)
+                if (offset < (nuint)(uint)length)
                 {
                     lengthToExamine = GetByteVectorSpanLength(offset, length);
 
@@ -1009,7 +1009,7 @@ namespace System
                     Vector<byte> values1 = new Vector<byte>(value1);
                     Vector<byte> values2 = new Vector<byte>(value2);
 
-                    while ((byte*)lengthToExamine > (byte*)offset)
+                    while (lengthToExamine > offset)
                     {
                         Vector<byte> search = LoadVector(ref searchSpace, offset);
 
@@ -1021,48 +1021,48 @@ namespace System
 
                         if (Vector<byte>.Zero.Equals(matches))
                         {
-                            offset += Vector<byte>.Count;
+                            offset += (nuint)Vector<byte>.Count;
                             continue;
                         }
 
                         // Find offset of first match and add to current offset
-                        return (int)(byte*)offset + LocateFirstFoundByte(matches);
+                        return (int)offset + LocateFirstFoundByte(matches);
                     }
 
-                    if ((int)(byte*)offset < length)
+                    if (offset < (nuint)(uint)length)
                     {
-                        lengthToExamine = (IntPtr)(length - (int)(byte*)offset);
+                        lengthToExamine = ((nuint)(uint)length - offset);
                         goto SequentialScan;
                     }
                 }
             }
             return -1;
         Found: // Workaround for https://github.com/dotnet/runtime/issues/8795
-            return (int)(byte*)offset;
+            return (int)offset;
         Found1:
-            return (int)(byte*)(offset + 1);
+            return (int)(offset + 1);
         Found2:
-            return (int)(byte*)(offset + 2);
+            return (int)(offset + 2);
         Found3:
-            return (int)(byte*)(offset + 3);
+            return (int)(offset + 3);
         Found4:
-            return (int)(byte*)(offset + 4);
+            return (int)(offset + 4);
         Found5:
-            return (int)(byte*)(offset + 5);
+            return (int)(offset + 5);
         Found6:
-            return (int)(byte*)(offset + 6);
+            return (int)(offset + 6);
         Found7:
-            return (int)(byte*)(offset + 7);
+            return (int)(offset + 7);
         }
 
-        public static unsafe int LastIndexOfAny(ref byte searchSpace, byte value0, byte value1, int length)
+        public static int LastIndexOfAny(ref byte searchSpace, byte value0, byte value1, int length)
         {
             Debug.Assert(length >= 0);
 
             uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
             uint uValue1 = value1;
-            IntPtr offset = (IntPtr)length; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
-            IntPtr lengthToExamine = (IntPtr)length;
+            nuint offset = (nuint)(uint)length; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations
+            nuint lengthToExamine = (nuint)(uint)length;
 
             if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
             {
@@ -1070,7 +1070,7 @@ namespace System
             }
         SequentialScan:
             uint lookUp;
-            while ((byte*)lengthToExamine >= (byte*)8)
+            while (lengthToExamine >= 8)
             {
                 lengthToExamine -= 8;
                 offset -= 8;
@@ -1101,7 +1101,7 @@ namespace System
                     goto Found;
             }
 
-            if ((byte*)lengthToExamine >= (byte*)4)
+            if (lengthToExamine >= 4)
             {
                 lengthToExamine -= 4;
                 offset -= 4;
@@ -1120,7 +1120,7 @@ namespace System
                     goto Found;
             }
 
-            while ((byte*)lengthToExamine > (byte*)0)
+            while (lengthToExamine > 0)
             {
                 lengthToExamine -= 1;
                 offset -= 1;
@@ -1130,23 +1130,23 @@ namespace System
                     goto Found;
             }
 
-            if (Vector.IsHardwareAccelerated && ((byte*)offset > (byte*)0))
+            if (Vector.IsHardwareAccelerated && (offset > 0))
             {
-                lengthToExamine = (IntPtr)((int)(byte*)offset & ~(Vector<byte>.Count - 1));
+                lengthToExamine = (offset & (nuint)~(Vector<byte>.Count - 1));
 
                 Vector<byte> values0 = new Vector<byte>(value0);
                 Vector<byte> values1 = new Vector<byte>(value1);
 
-                while ((byte*)lengthToExamine > (byte*)(Vector<byte>.Count - 1))
+                while (lengthToExamine > (nuint)(Vector<byte>.Count - 1))
                 {
-                    Vector<byte> search = LoadVector(ref searchSpace, offset - Vector<byte>.Count);
+                    Vector<byte> search = LoadVector(ref searchSpace, offset - (nuint)Vector<byte>.Count);
                     var matches = Vector.BitwiseOr(
                                     Vector.Equals(search, values0),
                                     Vector.Equals(search, values1));
                     if (Vector<byte>.Zero.Equals(matches))
                     {
-                        offset -= Vector<byte>.Count;
-                        lengthToExamine -= Vector<byte>.Count;
+                        offset -= (nuint)Vector<byte>.Count;
+                        lengthToExamine -= (nuint)Vector<byte>.Count;
                         continue;
                     }
 
@@ -1154,7 +1154,7 @@ namespace System
                     return (int)(offset) - Vector<byte>.Count + LocateLastFoundByte(matches);
                 }
 
-                if ((byte*)offset > (byte*)0)
+                if (offset > 0)
                 {
                     lengthToExamine = offset;
                     goto SequentialScan;
@@ -1162,32 +1162,32 @@ namespace System
             }
             return -1;
         Found: // Workaround for https://github.com/dotnet/runtime/issues/8795
-            return (int)(byte*)offset;
+            return (int)offset;
         Found1:
-            return (int)(byte*)(offset + 1);
+            return (int)(offset + 1);
         Found2:
-            return (int)(byte*)(offset + 2);
+            return (int)(offset + 2);
         Found3:
-            return (int)(byte*)(offset + 3);
+            return (int)(offset + 3);
         Found4:
-            return (int)(byte*)(offset + 4);
+            return (int)(offset + 4);
         Found5:
-            return (int)(byte*)(offset + 5);
+            return (int)(offset + 5);
         Found6:
-            return (int)(byte*)(offset + 6);
+            return (int)(offset + 6);
         Found7:
-            return (int)(byte*)(offset + 7);
+            return (int)(offset + 7);
         }
 
-        public static unsafe int LastIndexOfAny(ref byte searchSpace, byte value0, byte value1, byte value2, int length)
+        public static int LastIndexOfAny(ref byte searchSpace, byte value0, byte value1, byte value2, int length)
         {
             Debug.Assert(length >= 0);
 
             uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
             uint uValue1 = value1;
             uint uValue2 = value2;
-            IntPtr offset = (IntPtr)length; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
-            IntPtr lengthToExamine = (IntPtr)length;
+            nuint offset = (nuint)(uint)length; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations
+            nuint lengthToExamine = (nuint)(uint)length;
 
             if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
             {
@@ -1195,7 +1195,7 @@ namespace System
             }
         SequentialScan:
             uint lookUp;
-            while ((byte*)lengthToExamine >= (byte*)8)
+            while (lengthToExamine >= 8)
             {
                 lengthToExamine -= 8;
                 offset -= 8;
@@ -1226,7 +1226,7 @@ namespace System
                     goto Found;
             }
 
-            if ((byte*)lengthToExamine >= (byte*)4)
+            if (lengthToExamine >= 4)
             {
                 lengthToExamine -= 4;
                 offset -= 4;
@@ -1245,7 +1245,7 @@ namespace System
                     goto Found;
             }
 
-            while ((byte*)lengthToExamine > (byte*)0)
+            while (lengthToExamine > 0)
             {
                 lengthToExamine -= 1;
                 offset -= 1;
@@ -1255,17 +1255,17 @@ namespace System
                     goto Found;
             }
 
-            if (Vector.IsHardwareAccelerated && ((byte*)offset > (byte*)0))
+            if (Vector.IsHardwareAccelerated && (offset > 0))
             {
-                lengthToExamine = (IntPtr)((int)(byte*)offset & ~(Vector<byte>.Count - 1));
+                lengthToExamine = (offset & (nuint)~(Vector<byte>.Count - 1));
 
                 Vector<byte> values0 = new Vector<byte>(value0);
                 Vector<byte> values1 = new Vector<byte>(value1);
                 Vector<byte> values2 = new Vector<byte>(value2);
 
-                while ((byte*)lengthToExamine > (byte*)(Vector<byte>.Count - 1))
+                while (lengthToExamine > (nuint)(Vector<byte>.Count - 1))
                 {
-                    Vector<byte> search = LoadVector(ref searchSpace, offset - Vector<byte>.Count);
+                    Vector<byte> search = LoadVector(ref searchSpace, offset - (nuint)Vector<byte>.Count);
 
                     var matches = Vector.BitwiseOr(
                                     Vector.BitwiseOr(
@@ -1275,8 +1275,8 @@ namespace System
 
                     if (Vector<byte>.Zero.Equals(matches))
                     {
-                        offset -= Vector<byte>.Count;
-                        lengthToExamine -= Vector<byte>.Count;
+                        offset -= (nuint)Vector<byte>.Count;
+                        lengthToExamine -= (nuint)Vector<byte>.Count;
                         continue;
                     }
 
@@ -1284,7 +1284,7 @@ namespace System
                     return (int)(offset) - Vector<byte>.Count + LocateLastFoundByte(matches);
                 }
 
-                if ((byte*)offset > (byte*)0)
+                if (offset > 0)
                 {
                     lengthToExamine = offset;
                     goto SequentialScan;
@@ -1292,21 +1292,21 @@ namespace System
             }
             return -1;
         Found: // Workaround for https://github.com/dotnet/runtime/issues/8795
-            return (int)(byte*)offset;
+            return (int)offset;
         Found1:
-            return (int)(byte*)(offset + 1);
+            return (int)(offset + 1);
         Found2:
-            return (int)(byte*)(offset + 2);
+            return (int)(offset + 2);
         Found3:
-            return (int)(byte*)(offset + 3);
+            return (int)(offset + 3);
         Found4:
-            return (int)(byte*)(offset + 4);
+            return (int)(offset + 4);
         Found5:
-            return (int)(byte*)(offset + 5);
+            return (int)(offset + 5);
         Found6:
-            return (int)(byte*)(offset + 6);
+            return (int)(offset + 6);
         Found7:
-            return (int)(byte*)(offset + 7);
+            return (int)(offset + 7);
         }
 
         // Optimized byte-based SequenceEquals. The "length" parameter for this one is declared a nuint rather than int as we also use it for types other than byte
@@ -1540,7 +1540,7 @@ namespace System
         }
 
         [MethodImpl(MethodImplOptions.AggressiveOptimization)]
-        public static unsafe int SequenceCompareTo(ref byte first, int firstLength, ref byte second, int secondLength)
+        public static int SequenceCompareTo(ref byte first, int firstLength, ref byte second, int secondLength)
         {
             Debug.Assert(firstLength >= 0);
             Debug.Assert(secondLength >= 0);
@@ -1548,18 +1548,18 @@ namespace System
             if (Unsafe.AreSame(ref first, ref second))
                 goto Equal;
 
-            IntPtr minLength = (IntPtr)((firstLength < secondLength) ? firstLength : secondLength);
+            nuint minLength = (nuint)(((uint)firstLength < (uint)secondLength) ? (uint)firstLength : (uint)secondLength);
 
-            IntPtr offset = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
-            IntPtr lengthToExamine = (IntPtr)(void*)minLength;
+            nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations
+            nuint lengthToExamine = minLength;
 
             if (Avx2.IsSupported)
             {
-                if ((byte*)lengthToExamine >= (byte*)Vector256<byte>.Count)
+                if (lengthToExamine >= (nuint)Vector256<byte>.Count)
                 {
-                    lengthToExamine -= Vector256<byte>.Count;
+                    lengthToExamine -= (nuint)Vector256<byte>.Count;
                     uint matches;
-                    while ((byte*)lengthToExamine > (byte*)offset)
+                    while (lengthToExamine > offset)
                     {
                         matches = (uint)Avx2.MoveMask(Avx2.CompareEqual(LoadVector256(ref first, offset), LoadVector256(ref second, offset)));
                         // Note that MoveMask has converted the equal vector elements into a set of bit flags,
@@ -1569,7 +1569,7 @@ namespace System
                         if (matches == uint.MaxValue)
                         {
                             // All matched
-                            offset += Vector256<byte>.Count;
+                            offset += (nuint)Vector256<byte>.Count;
                             continue;
                         }
 
@@ -1588,7 +1588,7 @@ namespace System
                     // Invert matches to find differences
                     uint differences = ~matches;
                     // Find bitflag offset of first difference and add to current offset
-                    offset = (IntPtr)((int)(byte*)offset + BitOperations.TrailingZeroCount((int)differences));
+                    offset += (uint)BitOperations.TrailingZeroCount(differences);
 
                     int result = Unsafe.AddByteOffset(ref first, offset).CompareTo(Unsafe.AddByteOffset(ref second, offset));
                     Debug.Assert(result != 0);
@@ -1596,11 +1596,11 @@ namespace System
                     return result;
                 }
 
-                if ((byte*)lengthToExamine >= (byte*)Vector128<byte>.Count)
+                if (lengthToExamine >= (nuint)Vector128<byte>.Count)
                 {
-                    lengthToExamine -= Vector128<byte>.Count;
+                    lengthToExamine -= (nuint)Vector128<byte>.Count;
                     uint matches;
-                    if ((byte*)lengthToExamine > (byte*)offset)
+                    if (lengthToExamine > offset)
                     {
                         matches = (uint)Sse2.MoveMask(Sse2.CompareEqual(LoadVector128(ref first, offset), LoadVector128(ref second, offset)));
                         // Note that MoveMask has converted the equal vector elements into a set of bit flags,
@@ -1625,7 +1625,7 @@ namespace System
                     // Invert matches to find differences
                     uint differences = ~matches;
                     // Find bitflag offset of first difference and add to current offset
-                    offset = (IntPtr)((int)(byte*)offset + BitOperations.TrailingZeroCount((int)differences));
+                    offset += (uint)BitOperations.TrailingZeroCount(differences);
 
                     int result = Unsafe.AddByteOffset(ref first, offset).CompareTo(Unsafe.AddByteOffset(ref second, offset));
                     Debug.Assert(result != 0);
@@ -1635,11 +1635,11 @@ namespace System
             }
             else if (Sse2.IsSupported)
             {
-                if ((byte*)lengthToExamine >= (byte*)Vector128<byte>.Count)
+                if (lengthToExamine >= (nuint)Vector128<byte>.Count)
                 {
-                    lengthToExamine -= Vector128<byte>.Count;
+                    lengthToExamine -= (nuint)Vector128<byte>.Count;
                     uint matches;
-                    while ((byte*)lengthToExamine > (byte*)offset)
+                    while (lengthToExamine > offset)
                     {
                         matches = (uint)Sse2.MoveMask(Sse2.CompareEqual(LoadVector128(ref first, offset), LoadVector128(ref second, offset)));
                         // Note that MoveMask has converted the equal vector elements into a set of bit flags,
@@ -1649,7 +1649,7 @@ namespace System
                         if (matches == ushort.MaxValue)
                         {
                             // All matched
-                            offset += Vector128<byte>.Count;
+                            offset += (nuint)Vector128<byte>.Count;
                             continue;
                         }
 
@@ -1668,7 +1668,7 @@ namespace System
                     // Invert matches to find differences
                     uint differences = ~matches;
                     // Find bitflag offset of first difference and add to current offset
-                    offset = (IntPtr)((int)(byte*)offset + BitOperations.TrailingZeroCount((int)differences));
+                    offset += (uint)BitOperations.TrailingZeroCount(differences);
 
                     int result = Unsafe.AddByteOffset(ref first, offset).CompareTo(Unsafe.AddByteOffset(ref second, offset));
                     Debug.Assert(result != 0);
@@ -1678,36 +1678,36 @@ namespace System
             }
             else if (Vector.IsHardwareAccelerated)
             {
-                if ((byte*)lengthToExamine > (byte*)Vector<byte>.Count)
+                if (lengthToExamine > (nuint)Vector<byte>.Count)
                 {
-                    lengthToExamine -= Vector<byte>.Count;
-                    while ((byte*)lengthToExamine > (byte*)offset)
+                    lengthToExamine -= (nuint)Vector<byte>.Count;
+                    while (lengthToExamine > offset)
                     {
                         if (LoadVector(ref first, offset) != LoadVector(ref second, offset))
                         {
                             goto BytewiseCheck;
                         }
-                        offset += Vector<byte>.Count;
+                        offset += (nuint)Vector<byte>.Count;
                     }
                     goto BytewiseCheck;
                 }
             }
 
-            if ((byte*)lengthToExamine > (byte*)sizeof(UIntPtr))
+            if (lengthToExamine > sizeof(nuint))
             {
-                lengthToExamine -= sizeof(UIntPtr);
-                while ((byte*)lengthToExamine > (byte*)offset)
+                lengthToExamine -= sizeof(nuint);
+                while (lengthToExamine > offset)
                 {
-                    if (LoadUIntPtr(ref first, offset) != LoadUIntPtr(ref second, offset))
+                    if (LoadNUInt(ref first, offset) != LoadNUInt(ref second, offset))
                     {
                         goto BytewiseCheck;
                     }
-                    offset += sizeof(UIntPtr);
+                    offset += sizeof(nuint);
                 }
             }
 
         BytewiseCheck:  // Workaround for https://github.com/dotnet/runtime/issues/8795
-            while ((byte*)minLength > (byte*)offset)
+            while (minLength > offset)
             {
                 int result = Unsafe.AddByteOffset(ref first, offset).CompareTo(Unsafe.AddByteOffset(ref second, offset));
                 if (result != 0)
@@ -1775,10 +1775,6 @@ namespace System
             => Unsafe.ReadUnaligned<ushort>(ref start);
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static ushort LoadUShort(ref byte start, nuint offset)
-            => Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref start, offset));
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private static uint LoadUInt(ref byte start)
             => Unsafe.ReadUnaligned<uint>(ref start);
 
@@ -1795,64 +1791,48 @@ namespace System
             => Unsafe.ReadUnaligned<nuint>(ref Unsafe.AddByteOffset(ref start, offset));
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static UIntPtr LoadUIntPtr(ref byte start, IntPtr offset)
-            => Unsafe.ReadUnaligned<UIntPtr>(ref Unsafe.AddByteOffset(ref start, offset));
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static Vector<byte> LoadVector(ref byte start, IntPtr offset)
-            => Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref start, offset));
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private static Vector<byte> LoadVector(ref byte start, nuint offset)
             => Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref start, offset));
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static Vector128<byte> LoadVector128(ref byte start, IntPtr offset)
-            => Unsafe.ReadUnaligned<Vector128<byte>>(ref Unsafe.AddByteOffset(ref start, offset));
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private static Vector128<byte> LoadVector128(ref byte start, nuint offset)
             => Unsafe.ReadUnaligned<Vector128<byte>>(ref Unsafe.AddByteOffset(ref start, offset));
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static Vector256<byte> LoadVector256(ref byte start, IntPtr offset)
-            => Unsafe.ReadUnaligned<Vector256<byte>>(ref Unsafe.AddByteOffset(ref start, offset));
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private static Vector256<byte> LoadVector256(ref byte start, nuint offset)
             => Unsafe.ReadUnaligned<Vector256<byte>>(ref Unsafe.AddByteOffset(ref start, offset));
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static unsafe IntPtr GetByteVectorSpanLength(IntPtr offset, int length)
-            => (IntPtr)((length - (int)(byte*)offset) & ~(Vector<byte>.Count - 1));
+        private static nuint GetByteVectorSpanLength(nuint offset, int length)
+            => (nuint)(uint)((length - (int)offset) & ~(Vector<byte>.Count - 1));
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static unsafe IntPtr GetByteVector128SpanLength(IntPtr offset, int length)
-            => (IntPtr)((length - (int)(byte*)offset) & ~(Vector128<byte>.Count - 1));
+        private static nuint GetByteVector128SpanLength(nuint offset, int length)
+            => (nuint)(uint)((length - (int)offset) & ~(Vector128<byte>.Count - 1));
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static unsafe IntPtr GetByteVector256SpanLength(IntPtr offset, int length)
-            => (IntPtr)((length - (int)(byte*)offset) & ~(Vector256<byte>.Count - 1));
+        private static nuint GetByteVector256SpanLength(nuint offset, int length)
+            => (nuint)(uint)((length - (int)offset) & ~(Vector256<byte>.Count - 1));
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static unsafe IntPtr UnalignedCountVector(ref byte searchSpace)
+        private static unsafe nuint UnalignedCountVector(ref byte searchSpace)
         {
-            int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
-            return (IntPtr)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
+            nint unaligned = (nint)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+            return (nuint)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static unsafe IntPtr UnalignedCountVector128(ref byte searchSpace)
+        private static unsafe nuint UnalignedCountVector128(ref byte searchSpace)
         {
-            int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector128<byte>.Count - 1);
-            return (IntPtr)((Vector128<byte>.Count - unaligned) & (Vector128<byte>.Count - 1));
+            nint unaligned = (nint)Unsafe.AsPointer(ref searchSpace) & (Vector128<byte>.Count - 1);
+            return (nuint)(uint)((Vector128<byte>.Count - unaligned) & (Vector128<byte>.Count - 1));
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static unsafe IntPtr UnalignedCountVectorFromEnd(ref byte searchSpace, int length)
+        private static unsafe nuint UnalignedCountVectorFromEnd(ref byte searchSpace, int length)
         {
-            int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
-            return (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
+            nint unaligned = (nint)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+            return (nuint)(uint)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
         }
     }
 }
index d0426d0..0f21d07 100644 (file)
@@ -54,7 +54,7 @@ namespace System
                 if (SequenceEqual(
                     ref Unsafe.As<char, byte>(ref Unsafe.Add(ref searchSpace, index + 1)),
                     ref Unsafe.As<char, byte>(ref valueTail),
-                    (nuint)valueTailLength * 2))
+                    (nuint)(uint)valueTailLength * 2))
                 {
                     return index;  // The tail matched. Return a successful find.
                 }
@@ -66,7 +66,7 @@ namespace System
         }
 
         [MethodImpl(MethodImplOptions.AggressiveOptimization)]
-        public static unsafe int SequenceCompareTo(ref char first, int firstLength, ref char second, int secondLength)
+        public static int SequenceCompareTo(ref char first, int firstLength, ref char second, int secondLength)
         {
             Debug.Assert(firstLength >= 0);
             Debug.Assert(secondLength >= 0);
@@ -76,51 +76,51 @@ namespace System
             if (Unsafe.AreSame(ref first, ref second))
                 goto Equal;
 
-            IntPtr minLength = (IntPtr)((firstLength < secondLength) ? firstLength : secondLength);
-            IntPtr i = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+            nuint minLength = (nuint)(((uint)firstLength < (uint)secondLength) ? (uint)firstLength : (uint)secondLength);
+            nuint i = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations
 
-            if ((byte*)minLength >= (byte*)(sizeof(UIntPtr) / sizeof(char)))
+            if (minLength >= (sizeof(nuint) / sizeof(char)))
             {
-                if (Vector.IsHardwareAccelerated && (byte*)minLength >= (byte*)Vector<ushort>.Count)
+                if (Vector.IsHardwareAccelerated && minLength >= (nuint)Vector<ushort>.Count)
                 {
-                    IntPtr nLength = minLength - Vector<ushort>.Count;
+                    nuint nLength = minLength - (nuint)Vector<ushort>.Count;
                     do
                     {
-                        if (Unsafe.ReadUnaligned<Vector<ushort>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref first, i))) !=
-                            Unsafe.ReadUnaligned<Vector<ushort>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref second, i))))
+                        if (Unsafe.ReadUnaligned<Vector<ushort>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref first, (nint)i))) !=
+                            Unsafe.ReadUnaligned<Vector<ushort>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref second, (nint)i))))
                         {
                             break;
                         }
-                        i += Vector<ushort>.Count;
+                        i += (nuint)Vector<ushort>.Count;
                     }
-                    while ((byte*)nLength >= (byte*)i);
+                    while (nLength >= i);
                 }
 
-                while ((byte*)minLength >= (byte*)(i + sizeof(UIntPtr) / sizeof(char)))
+                while (minLength >= (i + sizeof(nuint) / sizeof(char)))
                 {
-                    if (Unsafe.ReadUnaligned<UIntPtr>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref first, i))) !=
-                        Unsafe.ReadUnaligned<UIntPtr>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref second, i))))
+                    if (Unsafe.ReadUnaligned<nuint> (ref Unsafe.As<char, byte>(ref Unsafe.Add(ref first, (nint)i))) !=
+                        Unsafe.ReadUnaligned<nuint>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref second, (nint)i))))
                     {
                         break;
                     }
-                    i += sizeof(UIntPtr) / sizeof(char);
+                    i += sizeof(nuint) / sizeof(char);
                 }
             }
 
 #if TARGET_64BIT
-            if ((byte*)minLength >= (byte*)(i + sizeof(int) / sizeof(char)))
+            if (minLength >= (i + sizeof(int) / sizeof(char)))
             {
-                if (Unsafe.ReadUnaligned<int>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref first, i))) ==
-                    Unsafe.ReadUnaligned<int>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref second, i))))
+                if (Unsafe.ReadUnaligned<int>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref first, (nint)i))) ==
+                    Unsafe.ReadUnaligned<int>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref second, (nint)i))))
                 {
                     i += sizeof(int) / sizeof(char);
                 }
             }
 #endif
 
-            while ((byte*)i < (byte*)minLength)
+            while (i < minLength)
             {
-                int result = Unsafe.Add(ref first, i).CompareTo(Unsafe.Add(ref second, i));
+                int result = Unsafe.Add(ref first, (nint)i).CompareTo(Unsafe.Add(ref second, (nint)i));
                 if (result != 0)
                     return result;
                 i += 1;
@@ -287,7 +287,7 @@ namespace System
                 if (offset < length)
                 {
                     Debug.Assert(length - offset >= Vector128<ushort>.Count);
-                    if (((nint)Unsafe.AsPointer(ref Unsafe.Add(ref searchSpace, (IntPtr)offset)) & (nint)(Vector256<byte>.Count - 1)) != 0)
+                    if (((nint)Unsafe.AsPointer(ref Unsafe.Add(ref searchSpace, (nint)offset)) & (nint)(Vector256<byte>.Count - 1)) != 0)
                     {
                         // Not currently aligned to Vector256 (is aligned to Vector128); this can cause a problem for searches
                         // with no upper bound e.g. String.wcslen. Start with a check on Vector128 to align to Vector256,
@@ -1034,23 +1034,23 @@ namespace System
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static unsafe Vector<ushort> LoadVector(ref char start, nint offset)
-            => Unsafe.ReadUnaligned<Vector<ushort>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref start, (IntPtr)offset)));
+        private static Vector<ushort> LoadVector(ref char start, nint offset)
+            => Unsafe.ReadUnaligned<Vector<ushort>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref start, offset)));
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static unsafe Vector128<ushort> LoadVector128(ref char start, nint offset)
-            => Unsafe.ReadUnaligned<Vector128<ushort>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref start, (IntPtr)offset)));
+        private static Vector128<ushort> LoadVector128(ref char start, nint offset)
+            => Unsafe.ReadUnaligned<Vector128<ushort>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref start, offset)));
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static unsafe Vector256<ushort> LoadVector256(ref char start, nint offset)
-            => Unsafe.ReadUnaligned<Vector256<ushort>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref start, (IntPtr)offset)));
+        private static Vector256<ushort> LoadVector256(ref char start, nint offset)
+            => Unsafe.ReadUnaligned<Vector256<ushort>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref start, offset)));
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static unsafe nint GetCharVectorSpanLength(nint offset, nint length)
+        private static nint GetCharVectorSpanLength(nint offset, nint length)
             => (length - offset) & ~(Vector<ushort>.Count - 1);
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static unsafe nint GetCharVector128SpanLength(nint offset, nint length)
+        private static nint GetCharVector128SpanLength(nint offset, nint length)
             => (length - offset) & ~(Vector128<ushort>.Count - 1);
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]