-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
181 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package llvm | ||
|
||
/* | ||
#include "llvm-c/Transforms/PassBuilder.h" | ||
#include "llvm-c/Error.h" | ||
#include <stdlib.h> | ||
*/ | ||
import "C" | ||
import ( | ||
"errors" | ||
"unsafe" | ||
) | ||
|
||
type PassBuilderOptions struct { | ||
C C.LLVMPassBuilderOptionsRef | ||
} | ||
|
||
// NewPassBuilderOptions creates a PassBuilderOptions which can be used | ||
// to specify pass options for RunPasses. | ||
func NewPassBuilderOptions() (pbo PassBuilderOptions) { | ||
pbo.C = C.LLVMCreatePassBuilderOptions() | ||
return | ||
} | ||
|
||
// RunPasses runs the specified optimization passes on the functions in the module. | ||
// `passes` is a comma separated list of pass names in the same format as llvm's | ||
// `opt -passes=...` command. Running `opt -print-passes` can list the available | ||
// passes. | ||
// | ||
// Some notable passes include: | ||
// | ||
// default<O0> -- run the default -O0 passes | ||
// default<O1> -- run the default -O1 passes | ||
// default<O2> -- run the default -O2 passes | ||
// default<O3> -- run the default -O3 passes | ||
// default<Os> -- run the default -Os passes, like -O2 but size concious | ||
// default<Oz> -- run the default -Oz passes, optimizing for size above all else | ||
func (mod Module) RunPasses(passes string, tm TargetMachine, options PassBuilderOptions) error { | ||
cpasses := C.CString(passes) | ||
defer C.free(unsafe.Pointer(cpasses)) | ||
|
||
err := C.LLVMRunPasses(mod.C, cpasses, tm.C, options.C) | ||
if err != nil { | ||
cstr := C.LLVMGetErrorMessage(err) | ||
gstr := C.GoString(cstr) | ||
C.LLVMDisposeErrorMessage(cstr) | ||
|
||
return errors.New(gstr) | ||
} | ||
return nil | ||
} | ||
|
||
// SetVerifyEach toggles adding a VerifierPass to the PassBuilder, | ||
// ensuring all functions inside the module are valid. | ||
func (pbo PassBuilderOptions) SetVerifyEach(verifyEach bool) { | ||
C.LLVMPassBuilderOptionsSetVerifyEach(pbo.C, boolToLLVMBool(verifyEach)) | ||
} | ||
|
||
func (pbo PassBuilderOptions) SetDebugLogging(debugLogging bool) { | ||
C.LLVMPassBuilderOptionsSetDebugLogging(pbo.C, boolToLLVMBool(debugLogging)) | ||
} | ||
|
||
func (pbo PassBuilderOptions) SetLoopInterleaving(loopInterleaving bool) { | ||
C.LLVMPassBuilderOptionsSetLoopInterleaving(pbo.C, boolToLLVMBool(loopInterleaving)) | ||
} | ||
|
||
func (pbo PassBuilderOptions) SetLoopVectorization(loopVectorization bool) { | ||
C.LLVMPassBuilderOptionsSetLoopVectorization(pbo.C, boolToLLVMBool(loopVectorization)) | ||
} | ||
|
||
func (pbo PassBuilderOptions) SetSLPVectorization(slpVectorization bool) { | ||
C.LLVMPassBuilderOptionsSetSLPVectorization(pbo.C, boolToLLVMBool(slpVectorization)) | ||
} | ||
|
||
func (pbo PassBuilderOptions) SetLoopUnrolling(loopUnrolling bool) { | ||
C.LLVMPassBuilderOptionsSetLoopUnrolling(pbo.C, boolToLLVMBool(loopUnrolling)) | ||
} | ||
|
||
func (pbo PassBuilderOptions) SetForgetAllSCEVInLoopUnroll(forgetSCEV bool) { | ||
C.LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll(pbo.C, boolToLLVMBool(forgetSCEV)) | ||
} | ||
|
||
func (pbo PassBuilderOptions) SetLicmMssaOptCap(optCap uint) { | ||
C.LLVMPassBuilderOptionsSetLicmMssaOptCap(pbo.C, C.unsigned(optCap)) | ||
} | ||
|
||
func (pbo PassBuilderOptions) SetLicmMssaNoAccForPromotionCap(promotionCap uint) { | ||
C.LLVMPassBuilderOptionsSetLicmMssaNoAccForPromotionCap(pbo.C, C.unsigned(promotionCap)) | ||
} | ||
|
||
func (pbo PassBuilderOptions) SetCallGraphProfile(cgProfile bool) { | ||
C.LLVMPassBuilderOptionsSetCallGraphProfile(pbo.C, boolToLLVMBool(cgProfile)) | ||
} | ||
|
||
func (pbo PassBuilderOptions) SetMergeFunctions(mergeFuncs bool) { | ||
C.LLVMPassBuilderOptionsSetMergeFunctions(pbo.C, boolToLLVMBool(mergeFuncs)) | ||
} | ||
|
||
func (pbo PassBuilderOptions) Dispose() { | ||
C.LLVMDisposePassBuilderOptions(pbo.C) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package llvm | ||
|
||
import "testing" | ||
|
||
func TestPasses(t *testing.T) { | ||
InitializeNativeTarget() | ||
InitializeNativeAsmPrinter() | ||
|
||
mod := NewModule("fac_module") | ||
|
||
fac_args := []Type{Int32Type()} | ||
fac_type := FunctionType(Int32Type(), fac_args, false) | ||
fac := AddFunction(mod, "fac", fac_type) | ||
fac.SetFunctionCallConv(CCallConv) | ||
n := fac.Param(0) | ||
|
||
entry := AddBasicBlock(fac, "entry") | ||
iftrue := AddBasicBlock(fac, "iftrue") | ||
iffalse := AddBasicBlock(fac, "iffalse") | ||
end := AddBasicBlock(fac, "end") | ||
|
||
builder := NewBuilder() | ||
defer builder.Dispose() | ||
|
||
builder.SetInsertPointAtEnd(entry) | ||
If := builder.CreateICmp(IntEQ, n, ConstInt(Int32Type(), 0, false), "cmptmp") | ||
builder.CreateCondBr(If, iftrue, iffalse) | ||
|
||
builder.SetInsertPointAtEnd(iftrue) | ||
res_iftrue := ConstInt(Int32Type(), 1, false) | ||
builder.CreateBr(end) | ||
|
||
builder.SetInsertPointAtEnd(iffalse) | ||
n_minus := builder.CreateSub(n, ConstInt(Int32Type(), 1, false), "subtmp") | ||
call_fac_args := []Value{n_minus} | ||
call_fac := builder.CreateCall(fac_type, fac, call_fac_args, "calltmp") | ||
res_iffalse := builder.CreateMul(n, call_fac, "multmp") | ||
builder.CreateBr(end) | ||
|
||
builder.SetInsertPointAtEnd(end) | ||
res := builder.CreatePHI(Int32Type(), "result") | ||
phi_vals := []Value{res_iftrue, res_iffalse} | ||
phi_blocks := []BasicBlock{iftrue, iffalse} | ||
res.AddIncoming(phi_vals, phi_blocks) | ||
builder.CreateRet(res) | ||
|
||
err := VerifyModule(mod, ReturnStatusAction) | ||
if err != nil { | ||
t.Errorf("Error verifying module: %s", err) | ||
return | ||
} | ||
|
||
targ, err := GetTargetFromTriple(DefaultTargetTriple()) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
mt := targ.CreateTargetMachine(DefaultTargetTriple(), "", "", CodeGenLevelDefault, RelocDefault, CodeModelDefault) | ||
|
||
pbo := NewPassBuilderOptions() | ||
defer pbo.Dispose() | ||
|
||
t.Run("no error running default pass", func(t *testing.T) { | ||
err := mod.RunPasses("default<Os>", mt, pbo) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
}) | ||
|
||
t.Run("errors on unknown pass name", func(t *testing.T) { | ||
err := mod.RunPasses("badpassnamedoesnotexist", mt, pbo) | ||
if err == nil { | ||
t.Error("expecting error but got none") | ||
} | ||
|
||
if err.Error() != "unknown pass name 'badpassnamedoesnotexist'" { | ||
t.Errorf("expected error about unknow pass name, instead got %s", err) | ||
} | ||
}) | ||
} |