@@ -1504,7 +1504,7 @@ private static bool VectorContainsNonAsciiChar(Vector128<byte> asciiVector)
1504
1504
// prefer architecture specific intrinsic as they offer better perf
1505
1505
if ( Sse41 . IsSupported )
1506
1506
{
1507
- return ! Sse41 . TestZ ( asciiVector , Vector128 . Create ( ( byte ) 0x80 ) ) ;
1507
+ return ( asciiVector & Vector128 . Create ( ( byte ) 0x80 ) ) != Vector128 < byte > . Zero ;
1508
1508
}
1509
1509
else if ( AdvSimd . Arm64 . IsSupported )
1510
1510
{
@@ -1521,22 +1521,15 @@ private static bool VectorContainsNonAsciiChar(Vector128<byte> asciiVector)
1521
1521
internal static bool VectorContainsNonAsciiChar( Vector128 < ushort > utf16Vector )
1522
1522
{
1523
1523
// prefer architecture specific intrinsic as they offer better perf
1524
- if ( Sse2 . IsSupported )
1524
+ #pragma warning disable IntrinsicsInSystemPrivateCoreLibConditionParsing // A negated IsSupported condition isn't parseable by the intrinsics analyzer
1525
+ if ( Sse2 . IsSupported && ! Sse41 . IsSupported )
1526
+ #pragma warning restore IntrinsicsInSystemPrivateCoreLibConditionParsing
1525
1527
{
1526
- if ( Sse41 . IsSupported )
1527
- {
1528
- Vector128 < ushort > asciiMaskForTestZ = Vector128. Create( ( ushort ) 0xFF80 ) ;
1529
- // If a non-ASCII bit is set in any WORD of the vector, we have seen non-ASCII data.
1530
- return ! Sse41 . TestZ ( utf16Vector . AsInt16 ( ) , asciiMaskForTestZ . AsInt16 ( ) ) ;
1531
- }
1532
- else
1533
- {
1534
- Vector128 < ushort > asciiMaskForAddSaturate = Vector128. Create( ( ushort ) 0x7F80 ) ;
1535
- // The operation below forces the 0x8000 bit of each WORD to be set iff the WORD element
1536
- // has value >= 0x0800 (non-ASCII). Then we'll treat the vector as a BYTE vector in order
1537
- // to extract the mask. Reminder: the 0x0080 bit of each WORD should be ignored.
1538
- return ( Sse2 . MoveMask ( Sse2 . AddSaturate ( utf16Vector , asciiMaskForAddSaturate ) . AsByte ( ) ) & 0b_1010_1010_1010_1010 ) != 0 ;
1539
- }
1528
+ Vector128 < ushort > asciiMaskForAddSaturate = Vector128. Create( ( ushort ) 0x7F80 ) ;
1529
+ // The operation below forces the 0x8000 bit of each WORD to be set iff the WORD element
1530
+ // has value >= 0x0800 (non-ASCII). Then we'll treat the vector as a BYTE vector in order
1531
+ // to extract the mask. Reminder: the 0x0080 bit of each WORD should be ignored.
1532
+ return ( Sse2 . MoveMask ( Sse2 . AddSaturate ( utf16Vector , asciiMaskForAddSaturate ) . AsByte ( ) ) & 0b_1010_1010_1010_1010 ) != 0 ;
1540
1533
}
1541
1534
else if ( AdvSimd . Arm64 . IsSupported )
1542
1535
{
@@ -1557,18 +1550,10 @@ internal static bool VectorContainsNonAsciiChar(Vector128<ushort> utf16Vector)
1557
1550
[ MethodImpl( MethodImplOptions. AggressiveInlining) ]
1558
1551
internal static bool VectorContainsNonAsciiChar( Vector256< ushort > utf16Vector)
1559
1552
{
1560
- if ( Avx. IsSupported)
1561
- {
1562
- Vector256< ushort > asciiMaskForTestZ = Vector256. Create( ( ushort ) 0xFF80 ) ;
1563
- return ! Avx. TestZ( utf16Vector. AsInt16( ) , asciiMaskForTestZ . AsInt16 ( ) ) ;
1564
- }
1565
- else
1566
- {
1567
- const ushort asciiMask = ushort . MaxValue - 127 ; // 0xFF80
1568
- Vector256< ushort > zeroIsAscii = utf16Vector & Vector256. Create( asciiMask) ;
1569
- // If a non-ASCII bit is set in any WORD of the vector, we have seen non-ASCII data.
1570
- return zeroIsAscii != Vector256< ushort > . Zero;
1571
- }
1553
+ const ushort asciiMask = ushort . MaxValue - 127 ; // 0xFF80
1554
+ Vector256< ushort > zeroIsAscii = utf16Vector & Vector256. Create( asciiMask) ;
1555
+ // If a non-ASCII bit is set in any WORD of the vector, we have seen non-ASCII data.
1556
+ return zeroIsAscii != Vector256< ushort > . Zero;
1572
1557
}
1573
1558
1574
1559
[ MethodImpl( MethodImplOptions. AggressiveInlining) ]
@@ -1601,14 +1586,13 @@ private static bool AllCharsInVectorAreAscii<T>(Vector128<T> vector)
1601
1586
if ( typeof ( T) == typeof ( byte ) )
1602
1587
{
1603
1588
return
1604
- Sse41. IsSupported ? Sse41 . TestZ ( vector. AsByte( ) , Vector128 . Create ( ( byte ) 0x80 ) ) :
1589
+ Sse41. IsSupported ? ( vector. AsByte( ) & Vector128. Create( ( byte ) 0x80 ) ) == Vector128 < byte > . Zero :
1605
1590
AdvSimd. Arm64. IsSupported ? AllBytesInUInt64AreAscii( AdvSimd. Arm64. MaxPairwise( vector. AsByte( ) , vector . AsByte ( ) ) . AsUInt64( ) . ToScalar( ) ) :
1606
1591
vector. AsByte( ) . ExtractMostSignificantBits( ) == 0 ;
1607
1592
}
1608
1593
else
1609
1594
{
1610
1595
return
1611
- Sse41 . IsSupported ? Sse41 . TestZ ( vector . AsUInt16 ( ) , Vector128 . Create ( ( ushort ) 0xFF80 ) ) :
1612
1596
AdvSimd. Arm64. IsSupported ? AllCharsInUInt64AreAscii( AdvSimd. Arm64. MaxPairwise( vector. AsUInt16( ) , vector . AsUInt16 ( ) ) . AsUInt64( ) . ToScalar( ) ) :
1613
1597
( vector. AsUInt16( ) & Vector128. Create( ( ushort ) 0xFF80 ) ) == Vector128< ushort > . Zero;
1614
1598
}
@@ -1624,14 +1608,12 @@ private static bool AllCharsInVectorAreAscii<T>(Vector256<T> vector)
1624
1608
if ( typeof ( T) == typeof ( byte ) )
1625
1609
{
1626
1610
return
1627
- Avx . IsSupported ? Avx . TestZ ( vector . AsByte ( ) , Vector256 . Create ( ( byte ) 0x80 ) ) :
1611
+ Avx. IsSupported ? ( vector. AsByte( ) & Vector256. Create( ( byte ) 0x80 ) ) == Vector256 < byte > . Zero :
1628
1612
vector. AsByte( ) . ExtractMostSignificantBits( ) == 0 ;
1629
1613
}
1630
1614
else
1631
1615
{
1632
- return
1633
- Avx . IsSupported ? Avx . TestZ ( vector . AsUInt16 ( ) , Vector256 . Create ( ( ushort ) 0xFF80 ) ) :
1634
- ( vector . AsUInt16 ( ) & Vector256 . Create ( ( ushort ) 0xFF80 ) ) == Vector256 < ushort > . Zero ;
1616
+ return ( vector. AsUInt16( ) & Vector256. Create( ( ushort ) 0xFF80 ) ) == Vector256< ushort > . Zero;
1635
1617
}
1636
1618
}
1637
1619
0 commit comments