[mtouch] Add support for specifying how to optimize LLVM output. (#1532)
Performance tests ----------------- This is for a new watchOS extension project, built for release. * The default (currently -O2) optimizations: 41s ( baseline ) 30.027.060 bytes ( baseline ) * All optimizations disabled (`--llvm-opt=all=`): 17s (-24s = -59%) 32.978.312 bytes (+2.951.252 = +10%) * Optimized for size (`--llvm-opt=all=-Os`): 36s ( -5s = -12%) 28.617.408 bytes (-1.409.652 = -5%) * Optimized for more size (`--llvm-opt=all=-Oz`): 35s ( -6s = -15%) 28.601.016 bytes (-1.426.044 = -5%) * Optimized slightly (`--llvm-opt=all=-O1`): 35s ( -6s = -15%) 28.666.556 bytes (-1.360.504 = -5%) * Optimized a lot (`--llvm-opt=all=-O3`): 41s ( 0s = 0%) 30.403.996 bytes (+ 376.936 = +1%) Conclusions ----------- * The fastest build by far (less than twice as fast) is if optimizations are disabled, but this adds a 10% size penalty (~3 MB in this test case), compared to the baseline, and 15% size penalty (4.3 MB) compared to -Oz. * -Oz seems to have the best overall results: at least as fast as any other optimized build, and the smallest app as well. Caveats ------- Some optimizations might not work the AOT compiled code. The resulting binaries have not been tested.
This commit is contained in:
Родитель
834f3e3be5
Коммит
1a7a4ab463
|
@ -431,6 +431,17 @@ namespace Xamarin
|
|||
mtouch.AssertError (25, $"No SDK version was provided. Please add --sdk=X.Y to specify which {GetPlatformSimpleName (profile)} SDK should be used to build your application.");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MT0026 ()
|
||||
{
|
||||
using (var mtouch = new MTouchTool ()) {
|
||||
mtouch.CreateTemporaryApp ();
|
||||
mtouch.LLVMOptimizations = "-O2";
|
||||
mtouch.AssertExecuteFailure (MTouchAction.BuildDev, "build");
|
||||
mtouch.AssertError (26, "Could not parse the command line argument '--llvm-opt=-O2': Both assembly and optimization must be specified (assembly=optimization)");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MT0051 ()
|
||||
|
|
|
@ -84,6 +84,7 @@ namespace Xamarin
|
|||
public Profile Profile = Profile.iOS;
|
||||
public bool NoPlatformAssemblyReference;
|
||||
static XmlDocument device_list_cache;
|
||||
public string LLVMOptimizations;
|
||||
public string [] CustomArguments; // Sometimes you want to pass invalid arguments to mtouch, in this case this array is used. No processing will be done, if quotes are required, they must be added to the arguments in the array.
|
||||
|
||||
public class DeviceInfo
|
||||
|
@ -310,6 +311,9 @@ namespace Xamarin
|
|||
if (!string.IsNullOrEmpty (Device))
|
||||
sb.Append (" --device:").Append (MTouch.Quote (Device));
|
||||
|
||||
if (!string.IsNullOrEmpty (LLVMOptimizations))
|
||||
sb.Append (" --llvm-opt=").Append (MTouch.Quote (LLVMOptimizations));
|
||||
|
||||
if (CustomArguments != null) {
|
||||
foreach (var arg in CustomArguments) {
|
||||
sb.Append (" ").Append (arg);
|
||||
|
|
|
@ -131,6 +131,7 @@ namespace Xamarin.Bundler {
|
|||
public string AotArguments = "static,asmonly,direct-icalls,";
|
||||
public string AotOtherArguments = string.Empty;
|
||||
public bool? LLVMAsmWriter;
|
||||
public Dictionary<string, string> LLVMOptimizations = new Dictionary<string, string> ();
|
||||
|
||||
public Dictionary<string, string> EnvironmentVariables = new Dictionary<string, string> ();
|
||||
|
||||
|
@ -158,6 +159,16 @@ namespace Xamarin.Bundler {
|
|||
List<Abi> abis;
|
||||
HashSet<Abi> all_architectures; // all Abis used in the app, including extensions.
|
||||
|
||||
public string GetLLVMOptimizations (Assembly assembly)
|
||||
{
|
||||
string opt;
|
||||
if (LLVMOptimizations.TryGetValue (assembly.FileName, out opt))
|
||||
return opt;
|
||||
if (LLVMOptimizations.TryGetValue ("all", out opt))
|
||||
return opt;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetDlsymOption (string asm, bool dlsym)
|
||||
{
|
||||
if (DlsymAssemblies == null)
|
||||
|
|
|
@ -337,6 +337,17 @@ namespace Xamarin.Bundler {
|
|||
compiler_flags.ReferenceSymbols (Target.GetRequiredSymbols (this, true));
|
||||
}
|
||||
|
||||
if (App.EnableLLVMOnlyBitCode) {
|
||||
// The AOT compiler doesn't optimize the bitcode so clang will do it
|
||||
compiler_flags.AddOtherFlag ("-fexceptions");
|
||||
var optimizations = App.GetLLVMOptimizations (this);
|
||||
if (optimizations == null) {
|
||||
compiler_flags.AddOtherFlag ("-O2");
|
||||
} else if (optimizations.Length > 0) {
|
||||
compiler_flags.AddOtherFlag (optimizations);
|
||||
}
|
||||
}
|
||||
|
||||
link_task = new LinkTask ()
|
||||
{
|
||||
Target = Target,
|
||||
|
|
|
@ -349,10 +349,6 @@ namespace Xamarin.Bundler
|
|||
GetCompilerFlags (App, flags, ifile, Language);
|
||||
|
||||
flags.AddOtherFlag ($"-m{Driver.GetTargetMinSdkName (App)}-version-min={App.DeploymentTarget.ToString ()}");
|
||||
|
||||
if (App.EnableLLVMOnlyBitCode)
|
||||
// The AOT compiler doesn't optimize the bitcode so clang will do it
|
||||
flags.AddOtherFlag ("-O2 -fexceptions");
|
||||
}
|
||||
|
||||
void GetSharedCompilerFlags (CompilerFlags flags, string install_name)
|
||||
|
|
|
@ -1258,6 +1258,16 @@ namespace Xamarin.Bundler
|
|||
}
|
||||
},
|
||||
{ "llvm-asm", "Make the LLVM compiler emit assembly files instead of object files. [Deprecated]", v => { app.LLVMAsmWriter = true; }, true},
|
||||
{ "llvm-opt=", "Specify how to optimize the LLVM output (only applicable when using LLVM to compile to bitcode), per assembly: 'assembly'='optimizations', where 'assembly is the filename (including extension) of the assembly (the special value 'all' can be passed to set the same optimization for all assemblies), and 'optimizations' are optimization arguments. Valid optimization flags are Clang optimization flags.", v =>
|
||||
{
|
||||
var equals = v.IndexOf ('=');
|
||||
if (equals == -1)
|
||||
throw ErrorHelper.CreateError (26, "Could not parse the command line argument '{0}': {1}", "--llvm-opt=" + v, "Both assembly and optimization must be specified (assembly=optimization)");
|
||||
var asm = v.Substring (0, equals);
|
||||
var opt = v.Substring (equals + 1); // An empty string is valid here, meaning 'no optimizations'
|
||||
app.LLVMOptimizations [asm] = opt;
|
||||
}
|
||||
},
|
||||
{ "http-message-handler=", "Specify the default HTTP message handler for HttpClient", v => { http_message_handler = v; }},
|
||||
{ "output-format=", "Specify the output format for some commands. Possible values: Default, XML", v =>
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче