Skip to content

Commit 48ecbc2

Browse files
authored
add missing hardware intrinsic info (#2052)
* handle SSSE3 * handle X86Base * Vector<T> existed before .NET Core, but it's provided via standalone package * handle SERIALIZE
1 parent 8c963ba commit 48ecbc2

File tree

3 files changed

+28
-17
lines changed

3 files changed

+28
-17
lines changed

src/BenchmarkDotNet/BenchmarkDotNet.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="3.1.6" />
3030
</ItemGroup>
3131
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
32+
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
3233
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
3334
</ItemGroup>
3435
<ItemGroup Condition="'$(OS)' == 'Windows_NT'">

src/BenchmarkDotNet/Portability/Cpu/HardwareIntrinsics.cs

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Numerics;
24
using BenchmarkDotNet.Environments;
5+
using System.Diagnostics.CodeAnalysis;
36
#if NET6_0_OR_GREATER
47
using System.Runtime.Intrinsics.X86;
58
using System.Runtime.Intrinsics.Arm;
6-
using System.Numerics;
7-
#elif NETSTANDARD2_0_OR_GREATER
8-
using System;
99
#endif
1010

1111
namespace BenchmarkDotNet.Portability.Cpu
1212
{
1313
internal static class HardwareIntrinsics
1414
{
15-
internal static string GetVectorSize()
16-
{
17-
#if NET6_0_OR_GREATER
18-
if (Vector.IsHardwareAccelerated)
19-
return $"VectorSize={Vector<byte>.Count * 8}";
20-
#endif
21-
return string.Empty;
22-
}
15+
internal static string GetVectorSize() => Vector.IsHardwareAccelerated ? $"VectorSize={Vector<byte>.Count * 8}" : string.Empty;
2316

2417
internal static string GetShortInfo()
2518
{
@@ -31,18 +24,22 @@ internal static string GetShortInfo()
3124
return "SSE4.2";
3225
else if (IsX86Sse41Supported)
3326
return "SSE4.1";
27+
else if (IsX86Ssse3Supported)
28+
return "SSSE3";
3429
else if (IsX86Sse3Supported)
3530
return "SSE3";
3631
else if (IsX86Sse2Supported)
3732
return "SSE2";
3833
else if (IsX86SseSupported)
3934
return "SSE";
35+
else if (IsX86BaseSupported)
36+
return "X86Base";
4037
else if (IsArmAdvSimdSupported)
4138
return "AdvSIMD";
4239
else if (IsArmBaseSupported)
43-
return "base";
40+
return "ArmBase";
4441
else
45-
return string.Empty;
42+
return string.Empty; // Runtimes prior to .NET Core 3.0 (APIs did not exist)
4643
}
4744

4845
internal static string GetFullInfo(Platform platform)
@@ -59,9 +56,11 @@ static IEnumerable<string> GetCurrentProcessInstructionSets(Platform platform)
5956
else if (IsX86AvxSupported) yield return "AVX";
6057
else if (IsX86Sse42Supported) yield return "SSE4.2";
6158
else if (IsX86Sse41Supported) yield return "SSE4.1";
59+
else if (IsX86Ssse3Supported) yield return "SSSE3";
6260
else if (IsX86Sse3Supported) yield return "SSE3";
6361
else if (IsX86Sse2Supported) yield return "SSE2";
6462
else if (IsX86SseSupported) yield return "SSE";
63+
else if (IsX86BaseSupported) yield return "X86Base";
6564

6665
if (IsX86AesSupported) yield return "AES";
6766
if (IsX86Bmi1Supported) yield return "BMI1";
@@ -71,10 +70,12 @@ static IEnumerable<string> GetCurrentProcessInstructionSets(Platform platform)
7170
if (IsX86PclmulqdqSupported) yield return "PCLMUL";
7271
if (IsX86PopcntSupported) yield return "POPCNT";
7372
if (IsX86AvxVnniSupported) yield return "AvxVnni";
73+
if (IsX86SerializeSupported) yield return "SERIALIZE";
7474
// TODO: Add MOVBE when API is added.
7575
break;
7676
case Platform.Arm64:
7777
if (IsArmAdvSimdSupported) yield return "AdvSIMD";
78+
else if (IsArmBaseSupported) yield return "ArmBase";
7879

7980
if (IsArmAesSupported) yield return "AES";
8081
if (IsArmCrc32Supported) yield return "CRC32";
@@ -117,6 +118,13 @@ static IEnumerable<string> GetCurrentProcessInstructionSets(Platform platform)
117118
GetIsSupported("System.Runtime.Intrinsics.X86.Sse3");
118119
#endif
119120

121+
internal static bool IsX86Ssse3Supported =>
122+
#if NET6_0_OR_GREATER
123+
Ssse3.IsSupported;
124+
#elif NETSTANDARD
125+
GetIsSupported("System.Runtime.Intrinsics.X86.Ssse3");
126+
#endif
127+
120128
internal static bool IsX86Sse41Supported =>
121129
#if NET6_0_OR_GREATER
122130
Sse41.IsSupported;
@@ -203,6 +211,9 @@ static IEnumerable<string> GetCurrentProcessInstructionSets(Platform platform)
203211
GetIsSupported("System.Runtime.Intrinsics.X86.AvxVnni");
204212
#endif
205213

214+
// X86Serialize was introduced in .NET 7.0, BDN does not target it so we need to use reflection
215+
internal static bool IsX86SerializeSupported => GetIsSupported("System.Runtime.Intrinsics.X86.X86Serialize");
216+
206217
internal static bool IsArmBaseSupported =>
207218
#if NET6_0_OR_GREATER
208219
ArmBase.IsSupported;
@@ -259,14 +270,12 @@ static IEnumerable<string> GetCurrentProcessInstructionSets(Platform platform)
259270
GetIsSupported("System.Runtime.Intrinsics.Arm.Sha256");
260271
#endif
261272

262-
#if NETSTANDARD
263-
private static bool GetIsSupported(string typeName)
273+
private static bool GetIsSupported([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] string typeName)
264274
{
265275
Type type = Type.GetType(typeName);
266276
if (type == null) return false;
267277

268278
return (bool)type.GetProperty("IsSupported", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static).GetValue(null, null);
269279
}
270-
#endif
271280
}
272281
}

src/BenchmarkDotNet/Toolchains/NativeAot/Generator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ private static IEnumerable<string> GetCurrentProcessInstructionSets(Platform pla
225225
if (HardwareIntrinsics.IsX86SseSupported) yield return "sse";
226226
if (HardwareIntrinsics.IsX86Sse2Supported) yield return "sse2";
227227
if (HardwareIntrinsics.IsX86Sse3Supported) yield return "sse3";
228+
if (HardwareIntrinsics.IsX86Ssse3Supported) yield return "ssse3";
228229
if (HardwareIntrinsics.IsX86Sse41Supported) yield return "sse4.1";
229230
if (HardwareIntrinsics.IsX86Sse42Supported) yield return "sse4.2";
230231
if (HardwareIntrinsics.IsX86AvxSupported) yield return "avx";

0 commit comments

Comments
 (0)