diff --git a/src/libraries/System.Private.CoreLib/src/System/Guid.cs b/src/libraries/System.Private.CoreLib/src/System/Guid.cs index 8fd0da14bd6c62..05c56457a076cb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Guid.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Guid.cs @@ -1405,7 +1405,7 @@ private static (Vector128, Vector128, Vector128) FormatGuidVec if (useDashes) { - // We divide 16 bytes into 3 x Vector128: + // We divide 32 bytes into 3 x Vector128: // // ________-____-____-____-____________ // xxxxxxxxxxxxxxxx @@ -1421,14 +1421,29 @@ private static (Vector128, Vector128, Vector128) FormatGuidVec Vector128.Create(0x7060504FF030201, 0xF0E0D0C0B0A0908).AsByte()); // Vector "z" - we need to merge some elements of hexLow with hexHigh and add 4 dashes. - Vector128 mid1 = Vector128.Shuffle(hexLow, - Vector128.Create(0x0D0CFF0B0A0908FF, 0xFFFFFFFFFFFF0F0E).AsByte()); - Vector128 mid2 = Vector128.Shuffle(hexHigh, - Vector128.Create(0xFFFFFFFFFFFFFFFF, 0xFF03020100FFFFFF).AsByte()); - Vector128 dashesMask = Vector128.Shuffle(Vector128.CreateScalarUnsafe((byte)'-'), - Vector128.Create(0xFFFF00FFFFFFFF00, 0x00FFFFFFFF00FFFF).AsByte()); - - Vector128 vecZ = (mid1 | mid2 | dashesMask); + Vector128 vecZ; + Vector128 dashesMask = Vector128.Create(0x00002D000000002D, 0x2D000000002D0000).AsByte(); + if (AdvSimd.Arm64.IsSupported) + { + // Arm64 allows shuffling values using a 32-byte wide look-up table consisting of two 128-bit registers. + // Each byte in the second arg represents a value between 0 to 31 that acts as an index in the look-up table. + // Now we can create a "z" vector by selecting 12 values starting from the 9th element (index 0x08) and + // leaving gaps for dashes. Thus, the wider look-up table allows combining two shuffles, as used in the + // generic else-case, into a single instruction on Arm64. + // TODO: Check if the JIT can merge the consecutive table look-ups and avoid the Arm64 specific if-case. + Vector128 mid = AdvSimd.Arm64.VectorTableLookup((hexLow, hexHigh), + Vector128.Create(0x0D0CFF0B0A0908FF, 0xFF13121110FF0F0E).AsByte()); + vecZ = (mid | dashesMask); + } + else + { + Vector128 mid1 = Vector128.Shuffle(hexLow, + Vector128.Create(0x0D0CFF0B0A0908FF, 0xFFFFFFFFFFFF0F0E).AsByte()); + Vector128 mid2 = Vector128.Shuffle(hexHigh, + Vector128.Create(0xFFFFFFFFFFFFFFFF, 0xFF03020100FFFFFF).AsByte()); + vecZ = (mid1 | mid2 | dashesMask); + } + return (vecX, vecY, vecZ); }