passes.go raw

   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