From d9a0b40286b2424a6a7f1bdd9f7a5232a6e5e513 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 30 May 2022 14:19:42 +0200 Subject: [PATCH 1/2] builder: move some code to transform package The transform package is the more appropriate location for package-level optimizations, to match `transform.Optimize` for whole-program optimizations. This is just a refactor, to make later changes easier to read. --- builder/build.go | 22 +--------------------- transform/optimizer.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/builder/build.go b/builder/build.go index cf9f577760..d0e92d7c96 100644 --- a/builder/build.go +++ b/builder/build.go @@ -439,27 +439,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil return errors.New("verification error after interpreting " + pkgInit.Name()) } - // Run function passes for each function in the module. - // These passes are intended to be run on each function right - // after they're created to reduce IR size (and maybe also for - // cache locality to improve performance), but for now they're - // run here for each function in turn. Maybe this can be - // improved in the future. - builder := llvm.NewPassManagerBuilder() - defer builder.Dispose() - builder.SetOptLevel(optLevel) - builder.SetSizeLevel(sizeLevel) - funcPasses := llvm.NewFunctionPassManagerForModule(mod) - defer funcPasses.Dispose() - builder.PopulateFunc(funcPasses) - funcPasses.InitializeFunc() - for fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) { - if fn.IsDeclaration() { - continue - } - funcPasses.RunFunc(fn) - } - funcPasses.FinalizeFunc() + transform.OptimizePackage(mod, config) // Serialize the LLVM module as a bitcode file. // Write to a temporary path that is renamed to the destination diff --git a/transform/optimizer.go b/transform/optimizer.go index 8e2ef7a83a..66ad43f4ba 100644 --- a/transform/optimizer.go +++ b/transform/optimizer.go @@ -11,6 +11,34 @@ import ( "tinygo.org/x/go-llvm" ) +// OptimizePackage runs optimization passes over the LLVM module for the given +// Go package. +func OptimizePackage(mod llvm.Module, config *compileopts.Config) { + optLevel, sizeLevel, _ := config.OptLevels() + + // Run function passes for each function in the module. + // These passes are intended to be run on each function right + // after they're created to reduce IR size (and maybe also for + // cache locality to improve performance), but for now they're + // run here for each function in turn. Maybe this can be + // improved in the future. + builder := llvm.NewPassManagerBuilder() + defer builder.Dispose() + builder.SetOptLevel(optLevel) + builder.SetSizeLevel(sizeLevel) + funcPasses := llvm.NewFunctionPassManagerForModule(mod) + defer funcPasses.Dispose() + builder.PopulateFunc(funcPasses) + funcPasses.InitializeFunc() + for fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) { + if fn.IsDeclaration() { + continue + } + funcPasses.RunFunc(fn) + } + funcPasses.FinalizeFunc() +} + // Optimize runs a number of optimization and transformation passes over the // given module. Some passes are specific to TinyGo, others are generic LLVM // passes. You can set a preferred performance (0-3) and size (0-2) level and From f1827ede051b181817cef5dedc7c605696e94dbe Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 30 May 2022 14:55:14 +0200 Subject: [PATCH 2/2] transform: run OptimizeMaps during package optimizations This shrinks transform.Optimize() a little bit, working towards the goal of https://github.com/tinygo-org/tinygo/issues/2870. I ran the smoke tests and there is no practical downside: one test got smaller (??) and one had a different .hex hash, but other than that there was no difference. This should also make TinyGo a liiitle bit faster but it's probably not even measurable. --- transform/optimizer.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/transform/optimizer.go b/transform/optimizer.go index 66ad43f4ba..e688a53947 100644 --- a/transform/optimizer.go +++ b/transform/optimizer.go @@ -37,6 +37,11 @@ func OptimizePackage(mod llvm.Module, config *compileopts.Config) { funcPasses.RunFunc(fn) } funcPasses.FinalizeFunc() + + // Run TinyGo-specific optimization passes. + if optLevel > 0 { + OptimizeMaps(mod) + } } // Optimize runs a number of optimization and transformation passes over the @@ -92,7 +97,6 @@ func Optimize(mod llvm.Module, config *compileopts.Config, optLevel, sizeLevel i goPasses.Run(mod) // Run TinyGo-specific optimization passes. - OptimizeMaps(mod) OptimizeStringToBytes(mod) OptimizeReflectImplements(mod) OptimizeAllocs(mod, nil, nil)