@@ -781,7 +781,7 @@ public static int IndexOfAny(ref byte searchSpace, byte value0, byte value1, int
781781 nuint offset = 0 ; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations
782782 nuint lengthToExamine = ( nuint ) ( uint ) length ;
783783
784- if ( Sse2 . IsSupported || AdvSimd . Arm64 . IsSupported )
784+ if ( Vector128 . IsHardwareAccelerated )
785785 {
786786 // Avx2 branch also operates on Sse2 sizes, so check is combined.
787787 nint vectorDiff = ( nint ) length - Vector128 < byte > . Count ;
@@ -897,10 +897,10 @@ public static int IndexOfAny(ref byte searchSpace, byte value0, byte value1, int
897897 // the end and forwards, which may overlap on an earlier compare.
898898
899899 // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported.
900- if ( Sse2 . IsSupported )
900+ if ( Vector128 . IsHardwareAccelerated )
901901 {
902- int matches ;
903- if ( Avx2 . IsSupported )
902+ uint matches ;
903+ if ( Vector256 . IsHardwareAccelerated )
904904 {
905905 Vector256 < byte > search ;
906906 // Guard as we may only have a valid size for Vector128; when we will move to the Sse2
@@ -916,13 +916,10 @@ public static int IndexOfAny(ref byte searchSpace, byte value0, byte value1, int
916916 // First time this checks again against 0, however we will move into final compare if it fails.
917917 while ( lengthToExamine > offset )
918918 {
919- search = LoadVector256 ( ref searchSpace , offset ) ;
919+ search = Vector256 . LoadUnsafe ( ref searchSpace , offset ) ;
920920 // Bitwise Or to combine the flagged matches for the second value to our match flags
921- matches = Avx2 . MoveMask (
922- Avx2 . Or (
923- Avx2 . CompareEqual ( values0 , search ) ,
924- Avx2 . CompareEqual ( values1 , search ) ) ) ;
925- // Note that MoveMask has converted the equal vector elements into a set of bit flags,
921+ matches = ( Vector256 . Equals ( values0 , search ) | Vector256 . Equals ( values1 , search ) ) . ExtractMostSignificantBits ( ) ;
922+ // Note that ExtractMostSignificantBits has converted the equal vector elements into a set of bit flags,
926923 // So the bit position in 'matches' corresponds to the element offset.
927924 if ( matches == 0 )
928925 {
@@ -935,13 +932,10 @@ public static int IndexOfAny(ref byte searchSpace, byte value0, byte value1, int
935932 }
936933
937934 // Move to Vector length from end for final compare
938- search = LoadVector256 ( ref searchSpace , lengthToExamine ) ;
935+ search = Vector256 . LoadUnsafe ( ref searchSpace , lengthToExamine ) ;
939936 offset = lengthToExamine ;
940937 // Same as method as above
941- matches = Avx2 . MoveMask (
942- Avx2 . Or (
943- Avx2 . CompareEqual ( values0 , search ) ,
944- Avx2 . CompareEqual ( values1 , search ) ) ) ;
938+ matches = ( Vector256 . Equals ( values0 , search ) | Vector256 . Equals ( values1 , search ) ) . ExtractMostSignificantBits ( ) ;
945939 if ( matches == 0 )
946940 {
947941 // None matched
@@ -953,6 +947,7 @@ public static int IndexOfAny(ref byte searchSpace, byte value0, byte value1, int
953947 }
954948
955949 // Initial size check was done on method entry.
950+ Vector128 < byte > compareResult ;
956951 Debug . Assert ( length >= Vector128 < byte > . Count ) ;
957952 {
958953 Vector128 < byte > search ;
@@ -961,90 +956,40 @@ public static int IndexOfAny(ref byte searchSpace, byte value0, byte value1, int
961956 // First time this checks against 0 and we will move into final compare if it fails.
962957 while ( lengthToExamine > offset )
963958 {
964- search = LoadVector128 ( ref searchSpace , offset ) ;
959+ search = Vector128 . LoadUnsafe ( ref searchSpace , offset ) ;
965960
966- matches = Sse2 . MoveMask (
967- Sse2 . Or (
968- Sse2 . CompareEqual ( values0 , search ) ,
969- Sse2 . CompareEqual ( values1 , search ) )
970- . AsByte ( ) ) ;
971- // Note that MoveMask has converted the equal vector elements into a set of bit flags,
972- // So the bit position in 'matches' corresponds to the element offset.
973- if ( matches == 0 )
961+ compareResult = Vector128 . Equals ( values0 , search ) | Vector128 . Equals ( values1 , search ) ;
962+
963+ if ( compareResult == Vector128 < byte > . Zero )
974964 {
975965 // None matched
976966 offset += ( nuint ) Vector128 < byte > . Count ;
977967 continue ;
978968 }
979969
970+ matches = compareResult . ExtractMostSignificantBits ( ) ;
980971 goto IntrinsicsMatch ;
981972 }
982973 // Move to Vector length from end for final compare
983- search = LoadVector128 ( ref searchSpace , lengthToExamine ) ;
974+ search = Vector128 . LoadUnsafe ( ref searchSpace , lengthToExamine ) ;
984975 offset = lengthToExamine ;
985976 // Same as method as above
986- matches = Sse2 . MoveMask (
987- Sse2 . Or (
988- Sse2 . CompareEqual ( values0 , search ) ,
989- Sse2 . CompareEqual ( values1 , search ) ) ) ;
990- if ( matches == 0 )
977+ compareResult = Vector128 . Equals ( values0 , search ) | Vector128 . Equals ( values1 , search ) ;
978+
979+ if ( compareResult == Vector128 < byte > . Zero )
991980 {
992981 // None matched
993982 goto NotFound ;
994983 }
984+
985+ matches = compareResult . ExtractMostSignificantBits ( ) ;
995986 }
996987
997988 IntrinsicsMatch :
998989 // Find bitflag offset of first difference and add to current offset
999990 offset += ( nuint ) BitOperations . TrailingZeroCount ( matches ) ;
1000991 goto Found ;
1001992 }
1002- else if ( AdvSimd . Arm64 . IsSupported )
1003- {
1004- Vector128 < byte > search ;
1005- Vector128 < byte > matches ;
1006- Vector128 < byte > values0 = Vector128 . Create ( value0 ) ;
1007- Vector128 < byte > values1 = Vector128 . Create ( value1 ) ;
1008- // First time this checks against 0 and we will move into final compare if it fails.
1009- while ( lengthToExamine > offset )
1010- {
1011- search = LoadVector128 ( ref searchSpace , offset ) ;
1012-
1013- matches = AdvSimd . Or (
1014- AdvSimd . CompareEqual ( values0 , search ) ,
1015- AdvSimd . CompareEqual ( values1 , search ) ) ;
1016-
1017- if ( matches == Vector128 < byte > . Zero )
1018- {
1019- offset += ( nuint ) Vector128 < byte > . Count ;
1020- continue ;
1021- }
1022-
1023- // Find bitflag offset of first match and add to current offset
1024- offset += FindFirstMatchedLane ( matches ) ;
1025-
1026- goto Found ;
1027- }
1028-
1029- // Move to Vector length from end for final compare
1030- search = LoadVector128 ( ref searchSpace , lengthToExamine ) ;
1031- offset = lengthToExamine ;
1032- // Same as method as above
1033- matches = AdvSimd . Or (
1034- AdvSimd . CompareEqual ( values0 , search ) ,
1035- AdvSimd . CompareEqual ( values1 , search ) ) ;
1036-
1037- if ( matches == Vector128 < byte > . Zero )
1038- {
1039- // None matched
1040- goto NotFound ;
1041- }
1042-
1043- // Find bitflag offset of first match and add to current offset
1044- offset += FindFirstMatchedLane ( matches ) ;
1045-
1046- goto Found ;
1047- }
1048993 else if ( Vector . IsHardwareAccelerated )
1049994 {
1050995 Vector < byte > values0 = new Vector < byte > ( value0 ) ;
0 commit comments