TODO: We use rustc's optimization approach from when it used llvm 7, because many things are incompatible with llvm 7 nowadays. Although we should probably consult a rustc dev on whether any big things were discovered in that timespan that we should modify.
(
cgcx: &CodegenContext<NvvmCodegenBackend>,
diag_handler: &Handler,
module: &ModuleCodegen<LlvmMod>,
config: &ModuleConfig,
)
| 314 | // are incompatible with llvm 7 nowadays. Although we should probably consult a rustc dev on whether |
| 315 | // any big things were discovered in that timespan that we should modify. |
| 316 | pub(crate) unsafe fn optimize( |
| 317 | cgcx: &CodegenContext<NvvmCodegenBackend>, |
| 318 | diag_handler: &Handler, |
| 319 | module: &ModuleCodegen<LlvmMod>, |
| 320 | config: &ModuleConfig, |
| 321 | ) -> Result<(), FatalError> { |
| 322 | let _timer = cgcx |
| 323 | .prof |
| 324 | .generic_activity_with_arg("LLVM_module_optimize", &module.name[..]); |
| 325 | |
| 326 | let llmod = &*module.module_llvm.llmod; |
| 327 | |
| 328 | let module_name = module.name.clone(); |
| 329 | let module_name = Some(&module_name[..]); |
| 330 | |
| 331 | if config.emit_no_opt_bc { |
| 332 | let out = cgcx |
| 333 | .output_filenames |
| 334 | .temp_path_ext("no-opt.bc", module_name); |
| 335 | let out = path_to_c_string(&out); |
| 336 | llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); |
| 337 | } |
| 338 | |
| 339 | let tm_factory_config = TargetMachineFactoryConfig { |
| 340 | split_dwarf_file: None, |
| 341 | }; |
| 342 | |
| 343 | let tm = (cgcx.tm_factory)(tm_factory_config).expect("failed to create target machine"); |
| 344 | |
| 345 | if config.opt_level.is_some() { |
| 346 | let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod); |
| 347 | let mpm = llvm::LLVMCreatePassManager(); |
| 348 | |
| 349 | let addpass = |pass_name: &str| { |
| 350 | let pass_name = CString::new(pass_name).unwrap(); |
| 351 | let pass = llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()); |
| 352 | if pass.is_none() { |
| 353 | return false; |
| 354 | } |
| 355 | let pass = pass.unwrap(); |
| 356 | let pass_manager = match llvm::LLVMRustPassKind(pass) { |
| 357 | llvm::PassKind::Function => &fpm, |
| 358 | llvm::PassKind::Module => &mpm, |
| 359 | llvm::PassKind::Other => { |
| 360 | diag_handler.err("Encountered LLVM pass kind we can't handle"); |
| 361 | return true; |
| 362 | } |
| 363 | }; |
| 364 | llvm::LLVMRustAddPass(pass_manager, pass); |
| 365 | true |
| 366 | }; |
| 367 | |
| 368 | if !config.no_prepopulate_passes { |
| 369 | llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod); |
| 370 | llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod); |
| 371 | let opt_level = config |
| 372 | .opt_level |
| 373 | .map_or(llvm::CodeGenOptLevel::None, |x| to_llvm_opt_settings(x).0); |
no test coverage detected