@@ -111,6 +111,18 @@ pub fn to_llvm_opt_settings(
111
111
}
112
112
}
113
113
114
+ 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
+
114
126
// If find_features is true this won't access `sess.crate_types` by assuming
115
127
// that `is_pie_binary` is false. When we discover LLVM target features
116
128
// `sess.crate_types` is uninitialized so we cannot access it.
@@ -303,6 +315,88 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
303
315
}
304
316
}
305
317
318
+ fn get_pgo_gen_path ( config : & ModuleConfig ) -> Option < CString > {
319
+ match config. pgo_gen {
320
+ SwitchWithOptPath :: Enabled ( ref opt_dir_path) => {
321
+ let path = if let Some ( dir_path) = opt_dir_path {
322
+ dir_path. join ( "default_%m.profraw" )
323
+ } else {
324
+ PathBuf :: from ( "default_%m.profraw" )
325
+ } ;
326
+
327
+ Some ( CString :: new ( format ! ( "{}" , path. display( ) ) ) . unwrap ( ) )
328
+ }
329
+ SwitchWithOptPath :: Disabled => None ,
330
+ }
331
+ }
332
+
333
+ fn get_pgo_use_path ( config : & ModuleConfig ) -> Option < CString > {
334
+ config
335
+ . pgo_use
336
+ . as_ref ( )
337
+ . map ( |path_buf| CString :: new ( path_buf. to_string_lossy ( ) . as_bytes ( ) ) . unwrap ( ) )
338
+ }
339
+
340
+ pub ( crate ) fn should_use_new_llvm_pass_manager ( config : & ModuleConfig ) -> bool {
341
+ // We only support the new pass manager starting with LLVM 9.
342
+ if llvm_util:: get_major_version ( ) < 9 {
343
+ return false ;
344
+ }
345
+
346
+ // The new pass manager is disabled by default.
347
+ config. new_llvm_pass_manager . unwrap_or ( false )
348
+ }
349
+
350
+ pub ( crate ) unsafe fn optimize_with_new_llvm_pass_manager (
351
+ module : & ModuleCodegen < ModuleLlvm > ,
352
+ config : & ModuleConfig ,
353
+ opt_level : config:: OptLevel ,
354
+ opt_stage : llvm:: OptStage ,
355
+ ) {
356
+ let unroll_loops =
357
+ opt_level != config:: OptLevel :: Size && opt_level != config:: OptLevel :: SizeMin ;
358
+ let using_thin_buffers = opt_stage == llvm:: OptStage :: PreLinkThinLTO || config. bitcode_needed ( ) ;
359
+ let pgo_gen_path = get_pgo_gen_path ( config) ;
360
+ let pgo_use_path = get_pgo_use_path ( config) ;
361
+ let is_lto = opt_stage == llvm:: OptStage :: ThinLTO || opt_stage == llvm:: OptStage :: FatLTO ;
362
+ // Sanitizer instrumentation is only inserted during the pre-link optimization stage.
363
+ let sanitizer_options = if !is_lto {
364
+ config. sanitizer . as_ref ( ) . map ( |s| llvm:: SanitizerOptions {
365
+ sanitize_memory : * s == Sanitizer :: Memory ,
366
+ sanitize_thread : * s == Sanitizer :: Thread ,
367
+ sanitize_address : * s == Sanitizer :: Address ,
368
+ sanitize_recover : config. sanitizer_recover . contains ( s) ,
369
+ sanitize_memory_track_origins : config. sanitizer_memory_track_origins as c_int ,
370
+ } )
371
+ } else {
372
+ None
373
+ } ;
374
+
375
+ // FIXME: NewPM doesn't provide a facility to pass custom InlineParams.
376
+ // We would have to add upstream support for this first, before we can support
377
+ // config.inline_threshold and our more aggressive default thresholds.
378
+ // FIXME: NewPM uses an different and more explicit way to textually represent
379
+ // pass pipelines. It would probably make sense to expose this, but it would
380
+ // require a different format than the current -C passes.
381
+ llvm:: LLVMRustOptimizeWithNewPassManager (
382
+ module. module_llvm . llmod ( ) ,
383
+ & * module. module_llvm . tm ,
384
+ to_pass_builder_opt_level ( opt_level) ,
385
+ opt_stage,
386
+ config. no_prepopulate_passes ,
387
+ config. verify_llvm_ir ,
388
+ using_thin_buffers,
389
+ config. merge_functions ,
390
+ unroll_loops,
391
+ config. vectorize_slp ,
392
+ config. vectorize_loop ,
393
+ config. no_builtins ,
394
+ sanitizer_options. as_ref ( ) ,
395
+ pgo_gen_path. as_ref ( ) . map_or ( std:: ptr:: null ( ) , |s| s. as_ptr ( ) ) ,
396
+ pgo_use_path. as_ref ( ) . map_or ( std:: ptr:: null ( ) , |s| s. as_ptr ( ) ) ,
397
+ ) ;
398
+ }
399
+
306
400
// Unsafe due to LLVM calls.
307
401
pub ( crate ) unsafe fn optimize (
308
402
cgcx : & CodegenContext < LlvmCodegenBackend > ,
@@ -327,6 +421,17 @@ pub(crate) unsafe fn optimize(
327
421
}
328
422
329
423
if let Some ( opt_level) = config. opt_level {
424
+ if should_use_new_llvm_pass_manager ( config) {
425
+ let opt_stage = match cgcx. lto {
426
+ Lto :: Fat => llvm:: OptStage :: PreLinkFatLTO ,
427
+ Lto :: Thin | Lto :: ThinLocal => llvm:: OptStage :: PreLinkThinLTO ,
428
+ _ if cgcx. opts . cg . linker_plugin_lto . enabled ( ) => llvm:: OptStage :: PreLinkThinLTO ,
429
+ _ => llvm:: OptStage :: PreLinkNoLTO ,
430
+ } ;
431
+ optimize_with_new_llvm_pass_manager ( module, config, opt_level, opt_stage) ;
432
+ return Ok ( ( ) ) ;
433
+ }
434
+
330
435
// Create the two optimizing pass managers. These mirror what clang
331
436
// does, and are by populated by LLVM's default PassManagerBuilder.
332
437
// Each manager has a different set of passes, but they also share
@@ -757,24 +862,8 @@ pub unsafe fn with_llvm_pmb(
757
862
let opt_size =
758
863
config. opt_size . map ( |x| to_llvm_opt_settings ( x) . 1 ) . unwrap_or ( llvm:: CodeGenOptSizeNone ) ;
759
864
let inline_threshold = config. inline_threshold ;
760
-
761
- let pgo_gen_path = match config. pgo_gen {
762
- SwitchWithOptPath :: Enabled ( ref opt_dir_path) => {
763
- let path = if let Some ( dir_path) = opt_dir_path {
764
- dir_path. join ( "default_%m.profraw" )
765
- } else {
766
- PathBuf :: from ( "default_%m.profraw" )
767
- } ;
768
-
769
- Some ( CString :: new ( format ! ( "{}" , path. display( ) ) ) . unwrap ( ) )
770
- }
771
- SwitchWithOptPath :: Disabled => None ,
772
- } ;
773
-
774
- let pgo_use_path = config
775
- . pgo_use
776
- . as_ref ( )
777
- . map ( |path_buf| CString :: new ( path_buf. to_string_lossy ( ) . as_bytes ( ) ) . unwrap ( ) ) ;
865
+ let pgo_gen_path = get_pgo_gen_path ( config) ;
866
+ let pgo_use_path = get_pgo_use_path ( config) ;
778
867
779
868
llvm:: LLVMRustConfigurePassManagerBuilder (
780
869
builder,
0 commit comments