diff --git a/src/llvm/mod.rs b/src/llvm/mod.rs index d186b8fc..dbed3453 100644 --- a/src/llvm/mod.rs +++ b/src/llvm/mod.rs @@ -18,8 +18,7 @@ use llvm_sys::prelude::*; use llvm_sys::support::LLVMParseCommandLineOptions; use llvm_sys::target::*; use llvm_sys::target_machine::*; -use llvm_sys::transforms::ipo::*; -use llvm_sys::transforms::pass_manager_builder::*; +use llvm_sys::transforms::pass_builder::*; use llvm_sys::LLVMAttributeFunctionIndex; use llvm_sys::{LLVMLinkage, LLVMVisibility}; use log::*; @@ -176,40 +175,6 @@ pub unsafe fn optimize( LLVMSetModuleInlineAsm2(module, ptr::null_mut(), 0); } - let mpm = LLVMCreatePassManager(); - let fpm = LLVMCreateFunctionPassManagerForModule(module); - - LLVMAddAnalysisPasses(tm, mpm); - LLVMAddAnalysisPasses(tm, fpm); - - // even with -O0 and without LTO we still want to avoid linking in unused code from core etc - LLVMAddGlobalDCEPass(mpm); - - let pmb = LLVMPassManagerBuilderCreate(); - - use OptLevel::*; - let (inline_threshold, opt) = match opt_level { - No | SizeMin => (0, 1), // Pretty much nothing compiles with -O0 s∫o make it an alias for -O1 - Less => (25, 1), - Default => (225, 2), - Aggressive => (275, 3), - Size => (25, 0), - }; - LLVMPassManagerBuilderSetOptLevel(pmb, opt); - LLVMPassManagerBuilderSetSizeLevel( - pmb, - match opt_level { - Size => 1, - SizeMin => 2, - _ => 0, - }, - ); - LLVMPassManagerBuilderUseInlinerWithThreshold(pmb, inline_threshold); - - // populate the pass managers - LLVMPassManagerBuilderPopulateFunctionPassManager(pmb, fpm); - LLVMPassManagerBuilderPopulateModulePassManager(pmb, mpm); - for sym in module.globals_iter() { internalize(sym, symbol_name(sym), export_symbols); } @@ -217,8 +182,6 @@ pub unsafe fn optimize( internalize(sym, symbol_name(sym), export_symbols); } - debug!("running function passes"); - LLVMInitializeFunctionPassManager(fpm); for function in module.functions_iter() { let name = symbol_name(function); if !name.starts_with("llvm.") { @@ -226,15 +189,34 @@ pub unsafe fn optimize( remove_attribute(function, "noinline"); } internalize(function, name, export_symbols); - if LLVMIsDeclaration(function) == 0 { - LLVMRunFunctionPassManager(fpm, function); - } } } - LLVMFinalizeFunctionPassManager(fpm); - debug!("running module passes"); - LLVMRunPassManager(mpm, module); + let options = LLVMCreatePassBuilderOptions(); + + let passes = [ + // NB: "default<_>" must be the first pass in the list, otherwise it will be ignored. + match opt_level { + // Pretty much nothing compiles with -O0 so make it an alias for -O1. + OptLevel::No | OptLevel::Less => "default", + OptLevel::Default => "default", + OptLevel::Aggressive => "default", + OptLevel::Size => "default", + OptLevel::SizeMin => "default", + }, + // NB: This seems to be included in most default pipelines, but not obviously all of them. + // See + // https://github.com/llvm/llvm-project/blob/bbe2887f/llvm/lib/Passes/PassBuilderPipelines.cpp#L2011-L2012 + // for a case which includes DCE only conditionally. Better safe than sorry; include it always. + "dce", + ]; + + let passes = passes.join(","); + debug!("running passes: {passes}"); + let passes = CString::new(passes).unwrap(); + LLVMRunPasses(module, passes.as_ptr(), tm, options); + + LLVMDisposePassBuilderOptions(options); // Some debug info generated by rustc seems to trigger a segfault in the // BTF code in llvm, so strip it until that is fixed