1 package llvm
2 3 /*
4 #include "llvm-c/Transforms/PassBuilder.h"
5 #include "llvm-c/Error.h"
6 #include <stdlib.h>
7 */
8 import "C"
9 import (
10 "errors"
11 "unsafe"
12 )
13 14 // PassBuilderOptions allows specifying several options for the PassBuilder.
15 type PassBuilderOptions struct {
16 C C.LLVMPassBuilderOptionsRef
17 }
18 19 // NewPassBuilderOptions creates a PassBuilderOptions which can be used
20 // to specify pass options for RunPasses.
21 func NewPassBuilderOptions() (pbo PassBuilderOptions) {
22 pbo.C = C.LLVMCreatePassBuilderOptions()
23 return
24 }
25 26 // RunPasses runs the specified optimization passes on the functions in the module.
27 // `passes` is a comma separated list of pass names in the same format as llvm's
28 // `opt -passes=...` command. Running `opt -print-passes` can list the available
29 // passes.
30 //
31 // Some notable passes include:
32 //
33 // default<O0> -- run the default -O0 passes
34 // default<O1> -- run the default -O1 passes
35 // default<O2> -- run the default -O2 passes
36 // default<O3> -- run the default -O3 passes
37 // default<Os> -- run the default -Os passes, like -O2 but size conscious
38 // default<Oz> -- run the default -Oz passes, optimizing for size above all else
39 func (mod Module) RunPasses(passes string, tm TargetMachine, options PassBuilderOptions) error {
40 cpasses := C.CString(passes)
41 defer C.free(unsafe.Pointer(cpasses))
42 43 err := C.LLVMRunPasses(mod.C, cpasses, tm.C, options.C)
44 if err != nil {
45 cstr := C.LLVMGetErrorMessage(err)
46 gstr := C.GoString(cstr)
47 C.LLVMDisposeErrorMessage(cstr)
48 49 return errors.New(gstr)
50 }
51 return nil
52 }
53 54 // SetVerifyEach toggles adding a VerifierPass to the PassBuilder,
55 // ensuring all functions inside the module are valid. Useful for
56 // debugging, but adds a significant amount of overhead.
57 func (pbo PassBuilderOptions) SetVerifyEach(verifyEach bool) {
58 C.LLVMPassBuilderOptionsSetVerifyEach(pbo.C, boolToLLVMBool(verifyEach))
59 }
60 61 // SetDebugLogging toggles debug logging for the PassBuilder.
62 func (pbo PassBuilderOptions) SetDebugLogging(debugLogging bool) {
63 C.LLVMPassBuilderOptionsSetDebugLogging(pbo.C, boolToLLVMBool(debugLogging))
64 }
65 66 // SetLoopInterleaving toggles loop interleaving, which is part of
67 // loop vectorization.
68 func (pbo PassBuilderOptions) SetLoopInterleaving(loopInterleaving bool) {
69 C.LLVMPassBuilderOptionsSetLoopInterleaving(pbo.C, boolToLLVMBool(loopInterleaving))
70 }
71 72 // SetLoopVectorization toggles loop vectorization.
73 func (pbo PassBuilderOptions) SetLoopVectorization(loopVectorization bool) {
74 C.LLVMPassBuilderOptionsSetLoopVectorization(pbo.C, boolToLLVMBool(loopVectorization))
75 }
76 77 // SetSLPVectorization toggles Super-Word Level Parallelism vectorization,
78 // whose goal is to combine multiple similar independent instructions into
79 // a vector instruction.
80 func (pbo PassBuilderOptions) SetSLPVectorization(slpVectorization bool) {
81 C.LLVMPassBuilderOptionsSetSLPVectorization(pbo.C, boolToLLVMBool(slpVectorization))
82 }
83 84 // SetLoopUnrolling toggles loop unrolling.
85 func (pbo PassBuilderOptions) SetLoopUnrolling(loopUnrolling bool) {
86 C.LLVMPassBuilderOptionsSetLoopUnrolling(pbo.C, boolToLLVMBool(loopUnrolling))
87 }
88 89 // SetForgetAllSCEVInLoopUnroll toggles forgetting all SCEV (Scalar Evolution)
90 // information in loop unrolling. Scalar Evolution is a pass that analyses
91 // the how scalars evolve over iterations of a loop in order to optimize
92 // the loop better. Forgetting this information can be useful in some cases.
93 func (pbo PassBuilderOptions) SetForgetAllSCEVInLoopUnroll(forgetSCEV bool) {
94 C.LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll(pbo.C, boolToLLVMBool(forgetSCEV))
95 }
96 97 // SetLicmMssaOptCap sets a tuning option to cap the number of calls to
98 // retrieve clobbering accesses in MemorySSA, in Loop Invariant Code Motion
99 // optimization.
100 // See [llvm::PipelineTuningOptions::LicmMssaOptCap].
101 func (pbo PassBuilderOptions) SetLicmMssaOptCap(optCap uint) {
102 C.LLVMPassBuilderOptionsSetLicmMssaOptCap(pbo.C, C.unsigned(optCap))
103 }
104 105 // SetLicmMssaNoAccForPromotionCap sets a tuning option to cap the number of
106 // promotions to scalars in Loop Invariant Code Motion with MemorySSA, if
107 // the number of accesses is too large.
108 // See [llvm::PipelineTuningOptions::LicmMssaNoAccForPromotionCap].
109 func (pbo PassBuilderOptions) SetLicmMssaNoAccForPromotionCap(promotionCap uint) {
110 C.LLVMPassBuilderOptionsSetLicmMssaNoAccForPromotionCap(pbo.C, C.unsigned(promotionCap))
111 }
112 113 // SetCallGraphProfile toggles whether call graph profiling should be used.
114 func (pbo PassBuilderOptions) SetCallGraphProfile(cgProfile bool) {
115 C.LLVMPassBuilderOptionsSetCallGraphProfile(pbo.C, boolToLLVMBool(cgProfile))
116 }
117 118 // SetMergeFunctions toggles finding functions which will generate identical
119 // machine code by considering all pointer types to be equivalent. Once
120 // identified, they will be folded by replacing a call to one with a call to a
121 // bitcast of the other.
122 func (pbo PassBuilderOptions) SetMergeFunctions(mergeFuncs bool) {
123 C.LLVMPassBuilderOptionsSetMergeFunctions(pbo.C, boolToLLVMBool(mergeFuncs))
124 }
125 126 // Dispose of the memory allocated for the PassBuilderOptions.
127 func (pbo PassBuilderOptions) Dispose() {
128 C.LLVMDisposePassBuilderOptions(pbo.C)
129 }
130