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