4
4
using System . IO ;
5
5
using System . Linq ;
6
6
using System . Text ;
7
+ using BenchmarkDotNet . Environments ;
8
+ using BenchmarkDotNet . Extensions ;
7
9
using BenchmarkDotNet . Loggers ;
8
10
using BenchmarkDotNet . Portability ;
9
11
using BenchmarkDotNet . Running ;
@@ -26,7 +28,8 @@ internal Generator(string ilCompilerVersion,
26
28
string runtimeFrameworkVersion , string targetFrameworkMoniker , string cliPath ,
27
29
string runtimeIdentifier , IReadOnlyDictionary < string , string > feeds , bool useNuGetClearTag ,
28
30
bool useTempFolderForRestore , string packagesRestorePath ,
29
- bool rootAllApplicationAssemblies , bool ilcGenerateCompleteTypeMetadata , bool ilcGenerateStackTraceData )
31
+ bool rootAllApplicationAssemblies , bool ilcGenerateCompleteTypeMetadata , bool ilcGenerateStackTraceData ,
32
+ string ilcOptimizationPreference , string ilcInstructionSet )
30
33
: base ( targetFrameworkMoniker , cliPath , GetPackagesDirectoryPath ( useTempFolderForRestore , packagesRestorePath ) , runtimeFrameworkVersion )
31
34
{
32
35
this . ilCompilerVersion = ilCompilerVersion ;
@@ -38,6 +41,8 @@ internal Generator(string ilCompilerVersion,
38
41
this . rootAllApplicationAssemblies = rootAllApplicationAssemblies ;
39
42
this . ilcGenerateCompleteTypeMetadata = ilcGenerateCompleteTypeMetadata ;
40
43
this . ilcGenerateStackTraceData = ilcGenerateStackTraceData ;
44
+ this . ilcOptimizationPreference = ilcOptimizationPreference ;
45
+ this . ilcInstructionSet = ilcInstructionSet ;
41
46
}
42
47
43
48
private readonly string ilCompilerVersion ;
@@ -50,6 +55,8 @@ internal Generator(string ilCompilerVersion,
50
55
private readonly bool rootAllApplicationAssemblies ;
51
56
private readonly bool ilcGenerateCompleteTypeMetadata ;
52
57
private readonly bool ilcGenerateStackTraceData ;
58
+ private readonly string ilcOptimizationPreference ;
59
+ private readonly string ilcInstructionSet ;
53
60
54
61
private bool IsNuGet => feeds . ContainsKey ( NativeAotNuGetFeed ) && ! string . IsNullOrWhiteSpace ( ilCompilerVersion ) ;
55
62
@@ -127,11 +134,13 @@ private string GenerateProjectForNuGetBuild(BuildPartition buildPartition, Artif
127
134
<AssemblyName>{ artifactsPaths . ProgramName } </AssemblyName>
128
135
<AssemblyTitle>{ artifactsPaths . ProgramName } </AssemblyTitle>
129
136
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
137
+ <PlatformTarget>{ buildPartition . Platform . ToConfig ( ) } </PlatformTarget>
130
138
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
131
139
<DebugSymbols>false</DebugSymbols>
132
140
<UseSharedCompilation>false</UseSharedCompilation>
133
141
<Deterministic>true</Deterministic>
134
142
<RunAnalyzers>false</RunAnalyzers>
143
+ <IlcOptimizationPreference>{ ilcOptimizationPreference } </IlcOptimizationPreference>
135
144
{ GetTrimmingSettings ( ) }
136
145
<IlcGenerateCompleteTypeMetadata>{ ilcGenerateCompleteTypeMetadata } </IlcGenerateCompleteTypeMetadata>
137
146
<IlcGenerateStackTraceData>{ ilcGenerateStackTraceData } </IlcGenerateStackTraceData>
@@ -149,6 +158,9 @@ private string GenerateProjectForNuGetBuild(BuildPartition buildPartition, Artif
149
158
<ItemGroup>
150
159
{ string . Join ( Environment . NewLine , GetRdXmlFiles ( buildPartition . RepresentativeBenchmarkCase . Descriptor . Type , logger ) . Select ( file => $ "<RdXmlFile Include=\" { file } \" />") ) }
151
160
</ItemGroup>
161
+ <ItemGroup>
162
+ { GetInstructionSetSettings ( buildPartition ) }
163
+ </ItemGroup>
152
164
</Project>" ;
153
165
154
166
private string GenerateProjectForLocalBuild ( BuildPartition buildPartition , ArtifactsPaths artifactsPaths , ILogger logger ) => $@ "
@@ -162,11 +174,13 @@ private string GenerateProjectForLocalBuild(BuildPartition buildPartition, Artif
162
174
<AssemblyName>{ artifactsPaths . ProgramName } </AssemblyName>
163
175
<AssemblyTitle>{ artifactsPaths . ProgramName } </AssemblyTitle>
164
176
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
177
+ <PlatformTarget>{ buildPartition . Platform . ToConfig ( ) } </PlatformTarget>
165
178
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
166
179
<DebugSymbols>false</DebugSymbols>
167
180
<UseSharedCompilation>false</UseSharedCompilation>
168
181
<Deterministic>true</Deterministic>
169
182
<RunAnalyzers>false</RunAnalyzers>
183
+ <IlcOptimizationPreference>{ ilcOptimizationPreference } </IlcOptimizationPreference>
170
184
{ GetTrimmingSettings ( ) }
171
185
<IlcGenerateCompleteTypeMetadata>{ ilcGenerateCompleteTypeMetadata } </IlcGenerateCompleteTypeMetadata>
172
186
<IlcGenerateStackTraceData>{ ilcGenerateStackTraceData } </IlcGenerateStackTraceData>
@@ -184,6 +198,9 @@ private string GenerateProjectForLocalBuild(BuildPartition buildPartition, Artif
184
198
<ItemGroup>
185
199
{ string . Join ( Environment . NewLine , GetRdXmlFiles ( buildPartition . RepresentativeBenchmarkCase . Descriptor . Type , logger ) . Select ( file => $ "<RdXmlFile Include=\" { file } \" />") ) }
186
200
</ItemGroup>
201
+ <ItemGroup>
202
+ { GetInstructionSetSettings ( buildPartition ) }
203
+ </ItemGroup>
187
204
</Project>" ;
188
205
189
206
private string GetTrimmingSettings ( )
@@ -192,6 +209,14 @@ private string GetTrimmingSettings()
192
209
// TrimMode is set in explicit way as for older versions it might have different default value
193
210
: "<TrimMode>link</TrimMode><TrimmerDefaultAction>link</TrimmerDefaultAction>" ;
194
211
212
+ private string GetInstructionSetSettings ( BuildPartition buildPartition )
213
+ {
214
+ string instructionSet = ilcInstructionSet ?? GetCurrentInstructionSet ( buildPartition . Platform ) ;
215
+ return ! string . IsNullOrEmpty ( instructionSet )
216
+ ? $@ "<IlcArg Include=""--instructionset:{ instructionSet } "" />"
217
+ : "" ;
218
+ }
219
+
195
220
public IEnumerable < string > GetRdXmlFiles ( Type benchmarkTarget , ILogger logger )
196
221
{
197
222
yield return GeneratedRdXmlFileName ;
@@ -237,5 +262,56 @@ private void GenerateReflectionFile(ArtifactsPaths artifactsPaths)
237
262
else
238
263
throw new InvalidOperationException ( $ "Can't get directory of projectFilePath ('{ artifactsPaths . ProjectFilePath } ')") ;
239
264
}
265
+
266
+ private string GetCurrentInstructionSet ( Platform platform )
267
+ => string . Join ( "," , GetHostProcessInstructionSets ( platform ) ) ;
268
+
269
+ // based on https://github.com/dotnet/runtime/blob/ce61c09a5f6fc71d8f717d3fc4562f42171869a0/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs#L727
270
+ private static IEnumerable < string > GetHostProcessInstructionSets ( Platform platform )
271
+ {
272
+ switch ( platform )
273
+ {
274
+ case Platform . X86 :
275
+ case Platform . X64 :
276
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.X86Base" ) ) yield return "base" ;
277
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.Sse" ) ) yield return "sse" ;
278
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.Sse2" ) ) yield return "sse2" ;
279
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.Sse3" ) ) yield return "sse3" ;
280
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.Sse41" ) ) yield return "sse4.1" ;
281
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.Sse42" ) ) yield return "sse4.2" ;
282
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx" ) ) yield return "avx" ;
283
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.Avx2" ) ) yield return "avx2" ;
284
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.Aes" ) ) yield return "aes" ;
285
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.Bmi1" ) ) yield return "bmi" ;
286
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.Bmi2" ) ) yield return "bmi2" ;
287
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.Fma" ) ) yield return "fma" ;
288
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.Lzcnt" ) ) yield return "lzcnt" ;
289
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.Pclmulqdq" ) ) yield return "pclmul" ;
290
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.Popcnt" ) ) yield return "popcnt" ;
291
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.X86.AvxVnni" ) ) yield return "avxvnni" ;
292
+ break ;
293
+ case Platform . Arm64 :
294
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.Arm.ArmBase" ) ) yield return "base" ;
295
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.Arm.AdvSimd" ) ) yield return "neon" ;
296
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.Arm.Aes" ) ) yield return "aes" ;
297
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.Arm.Crc32" ) ) yield return "crc" ;
298
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.Arm.Dp" ) ) yield return "dotprod" ;
299
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.Arm.Rdm" ) ) yield return "rdma" ;
300
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.Arm.Sha1" ) ) yield return "sha1" ;
301
+ if ( GetIsSupported ( "System.Runtime.Intrinsics.Arm.Sha256" ) ) yield return "sha2" ;
302
+ // todo: handle "lse"
303
+ break ;
304
+ default :
305
+ yield break ;
306
+ }
307
+ }
308
+
309
+ private static bool GetIsSupported ( string typeName )
310
+ {
311
+ Type type = Type . GetType ( typeName ) ;
312
+ if ( type == null ) return false ;
313
+
314
+ return ( bool ) type . GetProperty ( "IsSupported" , System . Reflection . BindingFlags . Public | System . Reflection . BindingFlags . Static ) . GetValue ( null , null ) ;
315
+ }
240
316
}
241
317
}
0 commit comments