@@ -111,6 +111,18 @@ pub fn to_llvm_opt_settings(
111
111
}
112
112
}
113
113
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
+
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.
@@ -327,6 +339,58 @@ pub(crate) unsafe fn optimize(
327
339
}
328
340
329
341
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
+
330
394
// Create the two optimizing pass managers. These mirror what clang
331
395
// does, and are by populated by LLVM's default PassManagerBuilder.
332
396
// Each manager has a different set of passes, but they also share
@@ -346,8 +410,6 @@ pub(crate) unsafe fn optimize(
346
410
}
347
411
348
412
let mut extra_passes = Vec :: new ( ) ;
349
- let mut have_name_anon_globals_pass = false ;
350
-
351
413
for pass_name in & config. passes {
352
414
if pass_name == "lint" {
353
415
// Linting should also be performed early, directly on the generated IR.
@@ -360,10 +422,6 @@ pub(crate) unsafe fn optimize(
360
422
} else {
361
423
diag_handler. warn ( & format ! ( "unknown pass `{}`, ignoring" , pass_name) ) ;
362
424
}
363
-
364
- if pass_name == "name-anon-globals" {
365
- have_name_anon_globals_pass = true ;
366
- }
367
425
}
368
426
369
427
add_sanitizer_passes ( config, & mut extra_passes) ;
@@ -389,33 +447,17 @@ pub(crate) unsafe fn optimize(
389
447
llvm:: LLVMPassManagerBuilderPopulateModulePassManager ( b, mpm) ;
390
448
} ) ;
391
449
392
- have_name_anon_globals_pass = have_name_anon_globals_pass || prepare_for_thin_lto;
393
450
if using_thin_buffers && !prepare_for_thin_lto {
394
451
llvm:: LLVMRustAddPass ( mpm, find_pass ( "name-anon-globals" ) . unwrap ( ) ) ;
395
- have_name_anon_globals_pass = true ;
396
452
}
397
453
} else {
398
454
// If we don't use the standard pipeline, directly populate the MPM
399
455
// with the extra passes.
400
456
for pass in extra_passes {
401
457
llvm:: LLVMRustAddPass ( mpm, pass) ;
402
458
}
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 ( ) ) ;
419
461
}
420
462
}
421
463
}
0 commit comments