passes.go raw

   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