Optimize runs a number of optimization and transformation passes over the given module. Some passes are specific to TinyGo, others are generic LLVM passes. Please note that some optimizations are not optional, thus Optimize must always be run before emitting machine code.
(mod llvm.Module, config *compileopts.Config)
| 30 | // Please note that some optimizations are not optional, thus Optimize must |
| 31 | // always be run before emitting machine code. |
| 32 | func Optimize(mod llvm.Module, config *compileopts.Config) []error { |
| 33 | optLevel, speedLevel, _ := config.OptLevel() |
| 34 | |
| 35 | // Make sure these functions are kept in tact during TinyGo transformation passes. |
| 36 | for _, name := range functionsUsedInTransforms { |
| 37 | fn := mod.NamedFunction(name) |
| 38 | if fn.IsNil() { |
| 39 | panic(fmt.Errorf("missing core function %q", name)) |
| 40 | } |
| 41 | fn.SetLinkage(llvm.ExternalLinkage) |
| 42 | } |
| 43 | |
| 44 | // run a check of all of our code |
| 45 | if config.VerifyIR() { |
| 46 | errs := ircheck.Module(mod) |
| 47 | if errs != nil { |
| 48 | return errs |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | if speedLevel > 0 { |
| 53 | // Run some preparatory passes for the Go optimizer. |
| 54 | po := llvm.NewPassBuilderOptions() |
| 55 | defer po.Dispose() |
| 56 | optPasses := "globaldce,globalopt,ipsccp,instcombine<no-verify-fixpoint>,adce,function-attrs" |
| 57 | if llvmutil.Version() < 18 { |
| 58 | // LLVM 17 doesn't have the no-verify-fixpoint flag. |
| 59 | optPasses = "globaldce,globalopt,ipsccp,instcombine,adce,function-attrs" |
| 60 | } |
| 61 | err := mod.RunPasses(optPasses, llvm.TargetMachine{}, po) |
| 62 | if err != nil { |
| 63 | return []error{fmt.Errorf("could not build pass pipeline: %w", err)} |
| 64 | } |
| 65 | |
| 66 | // Run TinyGo-specific optimization passes. |
| 67 | OptimizeStringToBytes(mod) |
| 68 | maxStackSize := config.MaxStackAlloc() |
| 69 | OptimizeAllocs(mod, nil, maxStackSize, nil) |
| 70 | err = LowerInterfaces(mod, config) |
| 71 | if err != nil { |
| 72 | return []error{err} |
| 73 | } |
| 74 | |
| 75 | errs := LowerInterrupts(mod) |
| 76 | if len(errs) > 0 { |
| 77 | return errs |
| 78 | } |
| 79 | |
| 80 | // After interfaces are lowered, there are many more opportunities for |
| 81 | // interprocedural optimizations. To get them to work, function |
| 82 | // attributes have to be updated first. |
| 83 | err = mod.RunPasses(optPasses, llvm.TargetMachine{}, po) |
| 84 | if err != nil { |
| 85 | return []error{fmt.Errorf("could not build pass pipeline: %w", err)} |
| 86 | } |
| 87 | |
| 88 | // Run TinyGo-specific interprocedural optimizations. |
| 89 | OptimizeAllocs(mod, config.Options.PrintAllocs, maxStackSize, func(pos token.Position, msg string) { |
no test coverage detected