diff options
author | Johannes Stoelp <johannes.stoelp@gmail.com> | 2021-09-16 21:13:16 +0200 |
---|---|---|
committer | Johannes Stoelp <johannes.stoelp@gmail.com> | 2021-09-16 21:13:16 +0200 |
commit | b0cad668398c0102b726336871bac28ddfac347c (patch) | |
tree | a78f207fe1034c85555faf51457daa8bc5e8e470 /src/llvm.rs | |
parent | 0773a1531f1a34c9bba2fba19ef90b935267a160 (diff) | |
download | llvm-kaleidoscope-rs-b0cad668398c0102b726336871bac28ddfac347c.tar.gz llvm-kaleidoscope-rs-b0cad668398c0102b726336871bac28ddfac347c.zip |
ch4: add function optimization passes
Diffstat (limited to 'src/llvm.rs')
-rw-r--r-- | src/llvm.rs | 81 |
1 files changed, 75 insertions, 6 deletions
diff --git a/src/llvm.rs b/src/llvm.rs index ed6b930..5598cd4 100644 --- a/src/llvm.rs +++ b/src/llvm.rs @@ -10,14 +10,19 @@ use llvm_sys::core::{ LLVMAddFunction, LLVMAppendBasicBlockInContext, LLVMBuildFAdd, LLVMBuildFCmp, LLVMBuildFMul, LLVMBuildFSub, LLVMBuildRet, LLVMBuildUIToFP, LLVMConstReal, LLVMContextCreate, LLVMContextDispose, LLVMCountBasicBlocks, LLVMCountParams, LLVMCreateBuilderInContext, - LLVMDisposeBuilder, LLVMDisposeModule, LLVMDoubleTypeInContext, LLVMDumpModule, LLVMDumpType, - LLVMDumpValue, LLVMGetNamedFunction, LLVMGetParam, LLVMGetReturnType, LLVMGetTypeKind, - LLVMGetValueKind, LLVMGetValueName2, LLVMModuleCreateWithNameInContext, - LLVMPositionBuilderAtEnd, LLVMSetValueName2, LLVMTypeOf, + LLVMCreateFunctionPassManagerForModule, LLVMDisposeBuilder, LLVMDisposeModule, + LLVMDisposePassManager, LLVMDoubleTypeInContext, LLVMDumpModule, LLVMDumpType, LLVMDumpValue, + LLVMGetNamedFunction, LLVMGetParam, LLVMGetReturnType, LLVMGetTypeKind, LLVMGetValueKind, + LLVMGetValueName2, LLVMInitializeFunctionPassManager, LLVMModuleCreateWithNameInContext, + LLVMPositionBuilderAtEnd, LLVMRunFunctionPassManager, LLVMSetValueName2, LLVMTypeOf, }; use llvm_sys::prelude::{ - LLVMBasicBlockRef, LLVMBool, LLVMBuilderRef, LLVMContextRef, LLVMModuleRef, LLVMTypeRef, - LLVMValueRef, + LLVMBasicBlockRef, LLVMBool, LLVMBuilderRef, LLVMContextRef, LLVMModuleRef, LLVMPassManagerRef, + LLVMTypeRef, LLVMValueRef, +}; +use llvm_sys::transforms::{ + instcombine::LLVMAddInstructionCombiningPass, + scalar::{LLVMAddCFGSimplificationPass, LLVMAddNewGVNPass, LLVMAddReassociatePass}, }; use llvm_sys::{LLVMRealPredicate, LLVMTypeKind, LLVMValueKind}; @@ -532,3 +537,67 @@ impl<'llvm> FnValue<'llvm> { } } } + +// ======================= +// FunctionPassManager +// ======================= + +/// Wrapper for a LLVM Function PassManager (legacy). +pub struct FunctionPassManager<'llvm> { + fpm: LLVMPassManagerRef, + _ctx: PhantomData<&'llvm ()>, +} + +impl<'llvm> FunctionPassManager<'llvm> { + /// Create a new Function PassManager with the following optimization passes + /// - InstructionCombiningPass + /// - ReassociatePass + /// - NewGVNPass + /// - CFGSimplificationPass + /// + /// The list of selected optimization passes is taken from the tutorial chapter [LLVM + /// Optimization Passes](https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/LangImpl04.html#id3). + pub fn with_ctx(module: &'llvm Module) -> FunctionPassManager<'llvm> { + let fpm = unsafe { + // Borrows module reference. + LLVMCreateFunctionPassManagerForModule(module.module) + }; + assert!(!fpm.is_null()); + + unsafe { + // Do simple "peephole" optimizations and bit-twiddling optzns. + LLVMAddInstructionCombiningPass(fpm); + // Reassociate expressions. + LLVMAddReassociatePass(fpm); + // Eliminate Common SubExpressions. + LLVMAddNewGVNPass(fpm); + // Simplify the control flow graph (deleting unreachable blocks, etc). + LLVMAddCFGSimplificationPass(fpm); + + let fail = LLVMInitializeFunctionPassManager(fpm); + assert_eq!(fail, 0); + } + + FunctionPassManager { + fpm, + _ctx: PhantomData, + } + } + + /// Run the optimization passes registered with the Function PassManager on the function + /// referenced by `fn_value`. + pub fn run(&'llvm self, fn_value: FnValue<'llvm>) { + unsafe { + // Returns 1 if any of the passes modified the function, false otherwise. + LLVMRunFunctionPassManager(self.fpm, fn_value.value_ref()); + } + } +} + +impl Drop for FunctionPassManager<'_> { + fn drop(&mut self) { + unsafe { + LLVMDisposePassManager(self.fpm); + } + } +} |