@@ -111,6 +111,18 @@ pub fn to_llvm_opt_settings(
111111 }
112112}
113113
114+ pub fn to_pass_builder_opt_level ( cfg : config:: OptLevel ) -> llvm:: PassBuilderOptLevel {
115+ use config:: OptLevel :: * ;
116+ match cfg {
117+ No => llvm:: PassBuilderOptLevel :: O0 ,
118+ Less => llvm:: PassBuilderOptLevel :: O1 ,
119+ Default => llvm:: PassBuilderOptLevel :: O2 ,
120+ Aggressive => llvm:: PassBuilderOptLevel :: O3 ,
121+ Size => llvm:: PassBuilderOptLevel :: Os ,
122+ SizeMin => llvm:: PassBuilderOptLevel :: Oz ,
123+ }
124+ }
125+
114126// If find_features is true this won't access `sess.crate_types` by assuming
115127// that `is_pie_binary` is false. When we discover LLVM target features
116128// `sess.crate_types` is uninitialized so we cannot access it.
@@ -327,6 +339,58 @@ pub(crate) unsafe fn optimize(
327339 }
328340
329341 if let Some ( opt_level) = config. opt_level {
342+ if config. new_llvm_pass_manager {
343+ let unroll_loops =
344+ opt_level != config:: OptLevel :: Size && opt_level != config:: OptLevel :: SizeMin ;
345+ let prepare_for_thin_lto = cgcx. lto == Lto :: Thin
346+ || cgcx. lto == Lto :: ThinLocal
347+ || ( cgcx. lto != Lto :: Fat && cgcx. opts . cg . linker_plugin_lto . enabled ( ) ) ;
348+ let using_thin_buffers = prepare_for_thin_lto || config. bitcode_needed ( ) ;
349+
350+ let pgo_gen_path = match config. pgo_gen {
351+ SwitchWithOptPath :: Enabled ( ref opt_dir_path) => {
352+ let path = if let Some ( dir_path) = opt_dir_path {
353+ dir_path. join ( "default_%m.profraw" )
354+ } else {
355+ PathBuf :: from ( "default_%m.profraw" )
356+ } ;
357+
358+ Some ( CString :: new ( format ! ( "{}" , path. display( ) ) ) . unwrap ( ) )
359+ }
360+ SwitchWithOptPath :: Disabled => None ,
361+ } ;
362+ let pgo_use_path = config
363+ . pgo_use
364+ . as_ref ( )
365+ . map ( |path_buf| CString :: new ( path_buf. to_string_lossy ( ) . as_bytes ( ) ) . unwrap ( ) ) ;
366+
367+ // FIXME: NewPM doesn't seem to have a facility to provide custom InlineParams.
368+ // FIXME: Support extra passes.
369+ llvm:: LLVMRustOptimizeWithNewPassManager (
370+ llmod,
371+ tm,
372+ to_pass_builder_opt_level ( opt_level) ,
373+ config. no_prepopulate_passes ,
374+ config. verify_llvm_ir ,
375+ prepare_for_thin_lto,
376+ /* prepare_for_lto */ false , // FIXME: Actually differentiate this?
377+ using_thin_buffers,
378+ config. merge_functions ,
379+ unroll_loops,
380+ config. vectorize_slp ,
381+ config. vectorize_loop ,
382+ config. no_builtins ,
383+ Some ( Sanitizer :: Memory ) == config. sanitizer ,
384+ Some ( Sanitizer :: Thread ) == config. sanitizer ,
385+ Some ( Sanitizer :: Address ) == config. sanitizer ,
386+ config. sanitizer . as_ref ( ) . map_or ( false , |s| config. sanitizer_recover . contains ( s) ) ,
387+ config. sanitizer_memory_track_origins as c_int ,
388+ pgo_gen_path. as_ref ( ) . map_or ( std:: ptr:: null ( ) , |s| s. as_ptr ( ) ) ,
389+ pgo_use_path. as_ref ( ) . map_or ( std:: ptr:: null ( ) , |s| s. as_ptr ( ) ) ,
390+ ) ;
391+ return Ok ( ( ) ) ;
392+ }
393+
330394 // Create the two optimizing pass managers. These mirror what clang
331395 // does, and are by populated by LLVM's default PassManagerBuilder.
332396 // Each manager has a different set of passes, but they also share
@@ -346,8 +410,6 @@ pub(crate) unsafe fn optimize(
346410 }
347411
348412 let mut extra_passes = Vec :: new ( ) ;
349- let mut have_name_anon_globals_pass = false ;
350-
351413 for pass_name in & config. passes {
352414 if pass_name == "lint" {
353415 // Linting should also be performed early, directly on the generated IR.
@@ -360,10 +422,6 @@ pub(crate) unsafe fn optimize(
360422 } else {
361423 diag_handler. warn ( & format ! ( "unknown pass `{}`, ignoring" , pass_name) ) ;
362424 }
363-
364- if pass_name == "name-anon-globals" {
365- have_name_anon_globals_pass = true ;
366- }
367425 }
368426
369427 add_sanitizer_passes ( config, & mut extra_passes) ;
@@ -389,33 +447,17 @@ pub(crate) unsafe fn optimize(
389447 llvm:: LLVMPassManagerBuilderPopulateModulePassManager ( b, mpm) ;
390448 } ) ;
391449
392- have_name_anon_globals_pass = have_name_anon_globals_pass || prepare_for_thin_lto;
393450 if using_thin_buffers && !prepare_for_thin_lto {
394451 llvm:: LLVMRustAddPass ( mpm, find_pass ( "name-anon-globals" ) . unwrap ( ) ) ;
395- have_name_anon_globals_pass = true ;
396452 }
397453 } else {
398454 // If we don't use the standard pipeline, directly populate the MPM
399455 // with the extra passes.
400456 for pass in extra_passes {
401457 llvm:: LLVMRustAddPass ( mpm, pass) ;
402458 }
403- }
404-
405- if using_thin_buffers && !have_name_anon_globals_pass {
406- // As described above, this will probably cause an error in LLVM
407- if config. no_prepopulate_passes {
408- diag_handler. err (
409- "The current compilation is going to use thin LTO buffers \
410- without running LLVM's NameAnonGlobals pass. \
411- This will likely cause errors in LLVM. Consider adding \
412- -C passes=name-anon-globals to the compiler command line.",
413- ) ;
414- } else {
415- bug ! (
416- "We are using thin LTO buffers without running the NameAnonGlobals pass. \
417- This will likely cause errors in LLVM and should never happen."
418- ) ;
459+ if using_thin_buffers {
460+ llvm:: LLVMRustAddPass ( mpm, find_pass ( "name-anon-globals" ) . unwrap ( ) ) ;
419461 }
420462 }
421463 }
0 commit comments