1111
1212namespace BenchmarkDotNet . Detectors . Cpu
1313{
14+ // based on https://github.com/dotnet/runtime/tree/v10.0.0-rc.1.25451.107/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt
1415 internal static class HardwareIntrinsics
1516 {
1617 internal static string GetVectorSize ( ) => Vector . IsHardwareAccelerated ? $ "VectorSize={ Vector < byte > . Count * 8 } " : string . Empty ;
1718
1819 internal static string GetShortInfo ( )
1920 {
20- if ( IsX86Avx512FSupported )
21- return GetShortAvx512Representation ( ) ;
22- if ( IsX86Avx2Supported )
23- return "AVX2" ;
24- else if ( IsX86AvxSupported )
25- return "AVX" ;
26- else if ( IsX86Sse42Supported )
27- return "SSE4.2" ;
28- else if ( IsX86Sse41Supported )
29- return "SSE4.1" ;
30- else if ( IsX86Ssse3Supported )
31- return "SSSE3" ;
32- else if ( IsX86Sse3Supported )
33- return "SSE3" ;
34- else if ( IsX86Sse2Supported )
35- return "SSE2" ;
36- else if ( IsX86SseSupported )
37- return "SSE" ;
38- else if ( IsX86BaseSupported )
39- return "X86Base" ;
40- else if ( IsArmAdvSimdSupported )
41- return "AdvSIMD" ;
21+ if ( IsX86BaseSupported )
22+ {
23+ if ( IsX86Avx512Supported )
24+ {
25+ return "x86-64-v4" ;
26+ }
27+ else if ( IsX86Avx2Supported )
28+ {
29+ return "x86-64-v3" ;
30+ }
31+ else if ( IsX86Sse42Supported )
32+ {
33+ return "x86-64-v2" ;
34+ }
35+ else
36+ {
37+ return "x86-64-v1" ;
38+ }
39+ }
4240 else if ( IsArmBaseSupported )
43- return "ArmBase" ;
41+ {
42+ return "armv8.0-a" ;
43+ }
4444 else
45+ {
4546 return GetVectorSize ( ) ; // Runtimes prior to .NET Core 3.0 (APIs did not exist so we print non-exact Vector info)
47+ }
4648 }
4749
4850 internal static string GetFullInfo ( Platform platform )
@@ -55,32 +57,31 @@ static IEnumerable<string> GetCurrentProcessInstructionSets(Platform platform)
5557 {
5658 case Platform . X86 :
5759 case Platform . X64 :
58-
59- if ( IsX86Avx512FSupported ) yield return GetShortAvx512Representation ( ) ;
60- else if ( IsX86Avx2Supported ) yield return "AVX2" ;
61- else if ( IsX86AvxSupported ) yield return "AVX" ;
62- else if ( IsX86Sse42Supported ) yield return "SSE4.2" ;
63- else if ( IsX86Sse41Supported ) yield return "SSE4.1" ;
64- else if ( IsX86Ssse3Supported ) yield return "SSSE3" ;
65- else if ( IsX86Sse3Supported ) yield return "SSE3" ;
66- else if ( IsX86Sse2Supported ) yield return "SSE2" ;
67- else if ( IsX86SseSupported ) yield return "SSE" ;
68- else if ( IsX86BaseSupported ) yield return "X86Base" ;
69-
70- if ( IsX86AesSupported ) yield return "AES" ;
71- if ( IsX86Bmi1Supported ) yield return "BMI1" ;
72- if ( IsX86Bmi2Supported ) yield return "BMI2" ;
73- if ( IsX86FmaSupported ) yield return "FMA" ;
74- if ( IsX86LzcntSupported ) yield return "LZCNT" ;
75- if ( IsX86PclmulqdqSupported ) yield return "PCLMUL" ;
76- if ( IsX86PopcntSupported ) yield return "POPCNT" ;
60+ {
61+ if ( IsX86Avx10v2Supported ) yield return "AVX10v2" ;
62+ if ( IsX86Avx10v1Supported )
63+ {
64+ yield return "AVX10v1" ;
65+ yield return "AVX512 BF16+FP16" ;
66+ }
67+ if ( IsX86Avx512v3Supported ) yield return "AVX512 BITALG+VBMI2+VNNI+VPOPCNTDQ" ;
68+ if ( IsX86Avx512v2Supported ) yield return "AVX512 IFMA+VBMI" ;
69+ if ( IsX86Avx512Supported ) yield return "AVX512 F+BW+CD+DQ+VL" ;
70+ if ( IsX86Avx2Supported ) yield return "AVX2+BMI1+BMI2+F16C+FMA+LZCNT+MOVBE" ;
71+ if ( IsX86AvxSupported ) yield return "AVX" ;
72+ if ( IsX86Sse42Supported ) yield return "SSE3+SSSE3+SSE4.1+SSE4.2+POPCNT" ;
73+ if ( IsX86BaseSupported ) yield return "X86Base+SSE+SSE2" ;
74+ if ( IsX86AesSupported ) yield return "AES+PCLMUL" ;
7775 if ( IsX86AvxVnniSupported ) yield return "AvxVnni" ;
7876 if ( IsX86SerializeSupported ) yield return "SERIALIZE" ;
79- // TODO: Add MOVBE when API is added.
8077 break ;
78+ }
8179 case Platform . Arm64 :
82- if ( IsArmAdvSimdSupported ) yield return "AdvSIMD" ;
83- else if ( IsArmBaseSupported ) yield return "ArmBase" ;
80+ {
81+ if ( IsArmBaseSupported )
82+ {
83+ yield return "ArmBase+AdvSimd" ;
84+ }
8485
8586 if ( IsArmAesSupported ) yield return "AES" ;
8687 if ( IsArmCrc32Supported ) yield return "CRC32" ;
@@ -89,71 +90,39 @@ static IEnumerable<string> GetCurrentProcessInstructionSets(Platform platform)
8990 if ( IsArmSha1Supported ) yield return "SHA1" ;
9091 if ( IsArmSha256Supported ) yield return "SHA256" ;
9192 break ;
93+ }
94+
9295 default :
9396 yield break ;
9497 }
9598 }
9699 }
97100
98- private static string GetShortAvx512Representation ( )
99- {
100- StringBuilder avx512 = new ( "AVX-512F" ) ;
101- if ( IsX86Avx512CDSupported ) avx512 . Append ( "+CD" ) ;
102- if ( IsX86Avx512BWSupported ) avx512 . Append ( "+BW" ) ;
103- if ( IsX86Avx512DQSupported ) avx512 . Append ( "+DQ" ) ;
104- if ( IsX86Avx512FVLSupported ) avx512 . Append ( "+VL" ) ;
105- if ( IsX86Avx512VbmiSupported ) avx512 . Append ( "+VBMI" ) ;
106-
107- return avx512 . ToString ( ) ;
108- }
109-
101+ #pragma warning disable CA2252 // Some APIs require opting into preview features
110102 internal static bool IsX86BaseSupported =>
111103#if NET6_0_OR_GREATER
112- X86Base . IsSupported ;
113- #elif NETSTANDARD
114- GetIsSupported ( "System.Runtime.Intrinsics.X86.X86Base" ) ;
115- #endif
116-
117- internal static bool IsX86SseSupported =>
118- #if NET6_0_OR_GREATER
119- Sse . IsSupported ;
120- #elif NETSTANDARD
121- GetIsSupported ( "System.Runtime.Intrinsics.X86.Sse" ) ;
122- #endif
123-
124- internal static bool IsX86Sse2Supported =>
125- #if NET6_0_OR_GREATER
104+ X86Base . IsSupported &&
105+ Sse . IsSupported &&
126106 Sse2 . IsSupported ;
127107#elif NETSTANDARD
108+ GetIsSupported ( "System.Runtime.Intrinsics.X86.X86Base" ) &&
109+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Sse" ) &&
128110 GetIsSupported ( "System.Runtime.Intrinsics.X86.Sse2" ) ;
129111#endif
130112
131- internal static bool IsX86Sse3Supported =>
132- #if NET6_0_OR_GREATER
133- Sse3 . IsSupported ;
134- #elif NETSTANDARD
135- GetIsSupported ( "System.Runtime.Intrinsics.X86.Sse3" ) ;
136- #endif
137-
138- internal static bool IsX86Ssse3Supported =>
139- #if NET6_0_OR_GREATER
140- Ssse3 . IsSupported ;
141- #elif NETSTANDARD
142- GetIsSupported ( "System.Runtime.Intrinsics.X86.Ssse3" ) ;
143- #endif
144-
145- internal static bool IsX86Sse41Supported =>
146- #if NET6_0_OR_GREATER
147- Sse41 . IsSupported ;
148- #elif NETSTANDARD
149- GetIsSupported ( "System.Runtime.Intrinsics.X86.Sse41" ) ;
150- #endif
151-
152113 internal static bool IsX86Sse42Supported =>
153114#if NET6_0_OR_GREATER
154- Sse42 . IsSupported ;
115+ Sse3 . IsSupported &&
116+ Ssse3 . IsSupported &&
117+ Sse41 . IsSupported &&
118+ Sse42 . IsSupported &&
119+ Popcnt . IsSupported ;
155120#elif NETSTANDARD
156- GetIsSupported ( "System.Runtime.Intrinsics.X86.Sse42" ) ;
121+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Sse3" ) &&
122+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Ssse3" ) &&
123+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Sse41" ) &&
124+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Sse42" ) &&
125+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Popcnt" ) ;
157126#endif
158127
159128 internal static bool IsX86AvxSupported =>
@@ -165,107 +134,88 @@ private static string GetShortAvx512Representation()
165134
166135 internal static bool IsX86Avx2Supported =>
167136#if NET6_0_OR_GREATER
168- Avx2 . IsSupported ;
137+ Avx2 . IsSupported &&
138+ Bmi1 . IsSupported &&
139+ Bmi2 . IsSupported &&
140+ Fma . IsSupported &&
141+ Lzcnt . IsSupported ;
169142#elif NETSTANDARD
170- GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx2" ) ;
171- #endif
172-
173- internal static bool IsX86Avx512FSupported =>
174- #if NET8_0_OR_GREATER
175- Avx512F . IsSupported ;
176- #else
177- GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512F" ) ;
143+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx2" ) &&
144+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Bmi1" ) &&
145+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Bmi2" ) &&
146+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Fma" ) &&
147+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Lzcnt" ) ;
178148#endif
179149
180- internal static bool IsX86Avx512FVLSupported =>
150+ internal static bool IsX86Avx512Supported =>
181151#if NET8_0_OR_GREATER
182- Avx512F . VL . IsSupported ;
152+ Avx512F . IsSupported &&
153+ Avx512F . VL . IsSupported &&
154+ Avx512BW . IsSupported &&
155+ Avx512BW . VL . IsSupported &&
156+ Avx512CD . IsSupported &&
157+ Avx512CD . VL . IsSupported &&
158+ Avx512DQ . IsSupported &&
159+ Avx512DQ . VL . IsSupported ;
183160#else
184- GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512F+VL" ) ;
161+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512F" ) &&
162+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512F+VL" ) &&
163+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512BW" ) &&
164+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512BW+VL" ) &&
165+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512CD" ) &&
166+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512CD+VL" ) &&
167+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512DQ" ) &&
168+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512DQ+VL" ) ;
185169#endif
186170
187- internal static bool IsX86Avx512BWSupported =>
171+ internal static bool IsX86Avx512v2Supported =>
188172#if NET8_0_OR_GREATER
189- Avx512BW . IsSupported ;
173+ Avx512Vbmi . IsSupported &&
174+ Avx512Vbmi . VL . IsSupported ;
190175#else
191- GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512BW" ) ;
176+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512Vbmi" ) &&
177+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512Vbmi+VL" ) ;
192178#endif
193179
194- internal static bool IsX86Avx512CDSupported =>
195- #if NET8_0_OR_GREATER
196- Avx512CD . IsSupported ;
180+ internal static bool IsX86Avx512v3Supported =>
181+ #if NET10_0_OR_GREATER
182+ Avx512Vbmi2 . IsSupported &&
183+ Avx512Vbmi2 . VL . IsSupported ;
197184#else
198- GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512CD" ) ;
185+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512Vbmi2" ) &&
186+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512Vbmi2+VL" ) ;
199187#endif
200188
201- internal static bool IsX86Avx512DQSupported =>
202- #if NET8_0_OR_GREATER
203- Avx512DQ . IsSupported ;
189+ internal static bool IsX86Avx10v1Supported =>
190+ #if NET9_0_OR_GREATER
191+ Avx10v1 . IsSupported &&
192+ Avx10v1 . V512 . IsSupported ;
204193#else
205- GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512DQ" ) ;
194+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx10v1" ) &&
195+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx10v1+V512" ) ;
206196#endif
207197
208- internal static bool IsX86Avx512VbmiSupported =>
209- #if NET8_0_OR_GREATER
210- Avx512Vbmi . IsSupported ;
198+ internal static bool IsX86Avx10v2Supported =>
199+ #if NET10_0_OR_GREATER
200+ Avx10v2 . IsSupported &&
201+ Avx10v2 . V512 . IsSupported ;
211202#else
212- GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx512Vbmi" ) ;
203+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx10v2" ) &&
204+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx10v2+V512" ) ;
213205#endif
214206
215207 internal static bool IsX86AesSupported =>
216208#if NET6_0_OR_GREATER
217- System . Runtime . Intrinsics . X86 . Aes . IsSupported ;
218- #elif NETSTANDARD
219- GetIsSupported ( "System.Runtime.Intrinsics.X86.Aes" ) ;
220- #endif
221-
222- internal static bool IsX86Bmi1Supported =>
223- #if NET6_0_OR_GREATER
224- Bmi1 . IsSupported ;
225- #elif NETSTANDARD
226- GetIsSupported ( "System.Runtime.Intrinsics.X86.Bmi1" ) ;
227- #endif
228-
229- internal static bool IsX86Bmi2Supported =>
230- #if NET6_0_OR_GREATER
231- Bmi2 . IsSupported ;
232- #elif NETSTANDARD
233- GetIsSupported ( "System.Runtime.Intrinsics.X86.Bmi2" ) ;
234- #endif
235-
236- internal static bool IsX86FmaSupported =>
237- #if NET6_0_OR_GREATER
238- Fma . IsSupported ;
239- #elif NETSTANDARD
240- GetIsSupported ( "System.Runtime.Intrinsics.X86.Fma" ) ;
241- #endif
242-
243- internal static bool IsX86LzcntSupported =>
244- #if NET6_0_OR_GREATER
245- Lzcnt . IsSupported ;
246- #elif NETSTANDARD
247- GetIsSupported ( "System.Runtime.Intrinsics.X86.Lzcnt" ) ;
248- #endif
249-
250- internal static bool IsX86PclmulqdqSupported =>
251- #if NET6_0_OR_GREATER
209+ System . Runtime . Intrinsics . X86 . Aes . IsSupported &&
252210 Pclmulqdq . IsSupported ;
253211#elif NETSTANDARD
212+ GetIsSupported ( "System.Runtime.Intrinsics.X86.Aes" ) &&
254213 GetIsSupported ( "System.Runtime.Intrinsics.X86.Pclmulqdq" ) ;
255214#endif
256215
257- internal static bool IsX86PopcntSupported =>
258- #if NET6_0_OR_GREATER
259- Popcnt . IsSupported ;
260- #elif NETSTANDARD
261- GetIsSupported ( "System.Runtime.Intrinsics.X86.Popcnt" ) ;
262- #endif
263-
264216 internal static bool IsX86AvxVnniSupported =>
265217#if NET6_0_OR_GREATER
266- #pragma warning disable CA2252 // This API requires opting into preview features
267218 AvxVnni . IsSupported ;
268- #pragma warning restore CA2252 // This API requires opting into preview features
269219#elif NETSTANDARD
270220 GetIsSupported ( "System.Runtime.Intrinsics.X86.AvxVnni" ) ;
271221#endif
@@ -279,15 +229,10 @@ private static string GetShortAvx512Representation()
279229
280230 internal static bool IsArmBaseSupported =>
281231#if NET6_0_OR_GREATER
282- ArmBase . IsSupported ;
283- #elif NETSTANDARD
284- GetIsSupported ( "System.Runtime.Intrinsics.Arm.ArmBase" ) ;
285- #endif
286-
287- internal static bool IsArmAdvSimdSupported =>
288- #if NET6_0_OR_GREATER
232+ ArmBase . IsSupported &&
289233 AdvSimd . IsSupported ;
290234#elif NETSTANDARD
235+ GetIsSupported ( "System.Runtime.Intrinsics.Arm.ArmBase" ) &&
291236 GetIsSupported ( "System.Runtime.Intrinsics.Arm.AdvSimd" ) ;
292237#endif
293238
@@ -332,6 +277,7 @@ private static string GetShortAvx512Representation()
332277#elif NETSTANDARD
333278 GetIsSupported ( "System.Runtime.Intrinsics.Arm.Sha256" ) ;
334279#endif
280+ #pragma warning restore CA2252 // Some APIs require opting into preview features
335281
336282 private static bool GetIsSupported ( [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . PublicProperties ) ] string typeName )
337283 {
0 commit comments