Skip to content

Commit 9228ca1

Browse files
committed
Add new pass builder AP
1 parent 41ff177 commit 9228ca1

File tree

2 files changed

+181
-0
lines changed

2 files changed

+181
-0
lines changed

passes.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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+
type PassBuilderOptions struct {
15+
C C.LLVMPassBuilderOptionsRef
16+
}
17+
18+
// NewPassBuilderOptions creates a PassBuilderOptions which can be used
19+
// to specify pass options for RunPasses.
20+
func NewPassBuilderOptions() (pbo PassBuilderOptions) {
21+
pbo.C = C.LLVMCreatePassBuilderOptions()
22+
return
23+
}
24+
25+
// RunPasses runs the specified optimization passes on the functions in the module.
26+
// `passes` is a comma separated list of pass names in the same format as llvm's
27+
// `opt -passes=...` command. Running `opt -print-passes` can list the available
28+
// passes.
29+
//
30+
// Some notable passes include:
31+
//
32+
// default<O0> -- run the default -O0 passes
33+
// default<O1> -- run the default -O1 passes
34+
// default<O2> -- run the default -O2 passes
35+
// default<O3> -- run the default -O3 passes
36+
// default<Os> -- run the default -Os passes, like -O2 but size concious
37+
// default<Oz> -- run the default -Oz passes, optimizing for size above all else
38+
func (mod Module) RunPasses(passes string, tm TargetMachine, options PassBuilderOptions) error {
39+
cpasses := C.CString(passes)
40+
defer C.free(unsafe.Pointer(cpasses))
41+
42+
err := C.LLVMRunPasses(mod.C, cpasses, tm.C, options.C)
43+
if err != nil {
44+
cstr := C.LLVMGetErrorMessage(err)
45+
gstr := C.GoString(cstr)
46+
C.LLVMDisposeErrorMessage(cstr)
47+
48+
return errors.New(gstr)
49+
}
50+
return nil
51+
}
52+
53+
// SetVerifyEach toggles adding a VerifierPass to the PassBuilder,
54+
// ensuring all functions inside the module are valid.
55+
func (pbo PassBuilderOptions) SetVerifyEach(verifyEach bool) {
56+
C.LLVMPassBuilderOptionsSetVerifyEach(pbo.C, boolToLLVMBool(verifyEach))
57+
}
58+
59+
func (pbo PassBuilderOptions) SetDebugLogging(debugLogging bool) {
60+
C.LLVMPassBuilderOptionsSetDebugLogging(pbo.C, boolToLLVMBool(debugLogging))
61+
}
62+
63+
func (pbo PassBuilderOptions) SetLoopInterleaving(loopInterleaving bool) {
64+
C.LLVMPassBuilderOptionsSetLoopInterleaving(pbo.C, boolToLLVMBool(loopInterleaving))
65+
}
66+
67+
func (pbo PassBuilderOptions) SetLoopVectorization(loopVectorization bool) {
68+
C.LLVMPassBuilderOptionsSetLoopVectorization(pbo.C, boolToLLVMBool(loopVectorization))
69+
}
70+
71+
func (pbo PassBuilderOptions) SetSLPVectorization(slpVectorization bool) {
72+
C.LLVMPassBuilderOptionsSetSLPVectorization(pbo.C, boolToLLVMBool(slpVectorization))
73+
}
74+
75+
func (pbo PassBuilderOptions) SetLoopUnrolling(loopUnrolling bool) {
76+
C.LLVMPassBuilderOptionsSetLoopUnrolling(pbo.C, boolToLLVMBool(loopUnrolling))
77+
}
78+
79+
func (pbo PassBuilderOptions) SetForgetAllSCEVInLoopUnroll(forgetSCEV bool) {
80+
C.LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll(pbo.C, boolToLLVMBool(forgetSCEV))
81+
}
82+
83+
func (pbo PassBuilderOptions) SetLicmMssaOptCap(optCap uint) {
84+
C.LLVMPassBuilderOptionsSetLicmMssaOptCap(pbo.C, C.unsigned(optCap))
85+
}
86+
87+
func (pbo PassBuilderOptions) SetLicmMssaNoAccForPromotionCap(promotionCap uint) {
88+
C.LLVMPassBuilderOptionsSetLicmMssaNoAccForPromotionCap(pbo.C, C.unsigned(promotionCap))
89+
}
90+
91+
func (pbo PassBuilderOptions) SetCallGraphProfile(cgProfile bool) {
92+
C.LLVMPassBuilderOptionsSetCallGraphProfile(pbo.C, boolToLLVMBool(cgProfile))
93+
}
94+
95+
func (pbo PassBuilderOptions) SetMergeFunctions(mergeFuncs bool) {
96+
C.LLVMPassBuilderOptionsSetMergeFunctions(pbo.C, boolToLLVMBool(mergeFuncs))
97+
}
98+
99+
func (pbo PassBuilderOptions) Dispose() {
100+
C.LLVMDisposePassBuilderOptions(pbo.C)
101+
}

passes_test.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package llvm
2+
3+
import "testing"
4+
5+
func TestPasses(t *testing.T) {
6+
InitializeNativeTarget()
7+
InitializeNativeAsmPrinter()
8+
9+
mod := NewModule("fac_module")
10+
11+
fac_args := []Type{Int32Type()}
12+
fac_type := FunctionType(Int32Type(), fac_args, false)
13+
fac := AddFunction(mod, "fac", fac_type)
14+
fac.SetFunctionCallConv(CCallConv)
15+
n := fac.Param(0)
16+
17+
entry := AddBasicBlock(fac, "entry")
18+
iftrue := AddBasicBlock(fac, "iftrue")
19+
iffalse := AddBasicBlock(fac, "iffalse")
20+
end := AddBasicBlock(fac, "end")
21+
22+
builder := NewBuilder()
23+
defer builder.Dispose()
24+
25+
builder.SetInsertPointAtEnd(entry)
26+
If := builder.CreateICmp(IntEQ, n, ConstInt(Int32Type(), 0, false), "cmptmp")
27+
builder.CreateCondBr(If, iftrue, iffalse)
28+
29+
builder.SetInsertPointAtEnd(iftrue)
30+
res_iftrue := ConstInt(Int32Type(), 1, false)
31+
builder.CreateBr(end)
32+
33+
builder.SetInsertPointAtEnd(iffalse)
34+
n_minus := builder.CreateSub(n, ConstInt(Int32Type(), 1, false), "subtmp")
35+
call_fac_args := []Value{n_minus}
36+
call_fac := builder.CreateCall(fac_type, fac, call_fac_args, "calltmp")
37+
res_iffalse := builder.CreateMul(n, call_fac, "multmp")
38+
builder.CreateBr(end)
39+
40+
builder.SetInsertPointAtEnd(end)
41+
res := builder.CreatePHI(Int32Type(), "result")
42+
phi_vals := []Value{res_iftrue, res_iffalse}
43+
phi_blocks := []BasicBlock{iftrue, iffalse}
44+
res.AddIncoming(phi_vals, phi_blocks)
45+
builder.CreateRet(res)
46+
47+
err := VerifyModule(mod, ReturnStatusAction)
48+
if err != nil {
49+
t.Errorf("Error verifying module: %s", err)
50+
return
51+
}
52+
53+
targ, err := GetTargetFromTriple(DefaultTargetTriple())
54+
if err != nil {
55+
t.Error(err)
56+
}
57+
58+
mt := targ.CreateTargetMachine(DefaultTargetTriple(), "", "", CodeGenLevelDefault, RelocDefault, CodeModelDefault)
59+
60+
pbo := NewPassBuilderOptions()
61+
defer pbo.Dispose()
62+
63+
t.Run("no error running default pass", func(t *testing.T) {
64+
err := mod.RunPasses("default<Os>", mt, pbo)
65+
if err != nil {
66+
t.Error(err)
67+
}
68+
})
69+
70+
t.Run("errors on unknown pass name", func(t *testing.T) {
71+
err := mod.RunPasses("badpassnamedoesnotexist", mt, pbo)
72+
if err == nil {
73+
t.Error("expecting error but got none")
74+
}
75+
76+
if err.Error() != "unknown pass name 'badpassnamedoesnotexist'" {
77+
t.Errorf("expected error about unknow pass name, instead got %s", err)
78+
}
79+
})
80+
}

0 commit comments

Comments
 (0)