Skip to content

Commit a5c3956

Browse files
committed
Don't add extra passes into the function pass manager
Exception for specific cases like linting, additional passes should be going into the module pass manager (even if they are function passes). The separate function pass manager is only used for very early optimization passes. Rather than apparending passes to the MPM, use the OptimizerLast and EnabledOnOptLevel0 pass manager builder extension hooks, which allow adding passes directly before finalization (alias canonicalization and name-anon-globals). The main effect and purpose of this change is to add sanitizer passes at the end of the pipeline, which is where they belong. In LLVM 9 the address sanitizer can't be used as a pass in the early function pass manager, because it has a dependence on a module-level analysis pass.
1 parent 2c102cb commit a5c3956

File tree

3 files changed

+69
-39
lines changed

3 files changed

+69
-39
lines changed

src/librustc_codegen_llvm/back/write.rs

+49-39
Original file line numberDiff line numberDiff line change
@@ -329,33 +329,55 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
329329
let mpm = llvm::LLVMCreatePassManager();
330330

331331
{
332-
// If we're verifying or linting, add them to the function pass
333-
// manager.
334-
let addpass = |pass_name: &str| {
332+
let find_pass = |pass_name: &str| {
335333
let pass_name = SmallCStr::new(pass_name);
336-
let pass = match llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()) {
337-
Some(pass) => pass,
338-
None => return false,
339-
};
340-
let pass_manager = match llvm::LLVMRustPassKind(pass) {
341-
llvm::PassKind::Function => &*fpm,
342-
llvm::PassKind::Module => &*mpm,
343-
llvm::PassKind::Other => {
344-
diag_handler.err("Encountered LLVM pass kind we can't handle");
345-
return true
346-
},
347-
};
348-
llvm::LLVMRustAddPass(pass_manager, pass);
349-
true
334+
llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr())
350335
};
351336

352-
if config.verify_llvm_ir { assert!(addpass("verify")); }
337+
if config.verify_llvm_ir {
338+
// Verification should run as the very first pass.
339+
llvm::LLVMRustAddPass(fpm, find_pass("verify").unwrap());
340+
}
341+
342+
let mut extra_passes = Vec::new();
343+
let mut have_name_anon_globals_pass = false;
344+
345+
for pass_name in &config.passes {
346+
if pass_name == "lint" {
347+
// Linting should also be performed early, directly on the generated IR.
348+
llvm::LLVMRustAddPass(fpm, find_pass("lint").unwrap());
349+
continue;
350+
}
351+
352+
if let Some(pass) = find_pass(pass_name) {
353+
extra_passes.push(pass);
354+
} else {
355+
diag_handler.warn(&format!("unknown pass `{}`, ignoring", pass_name));
356+
}
357+
358+
if pass_name == "name-anon-globals" {
359+
have_name_anon_globals_pass = true;
360+
}
361+
}
362+
363+
for pass_name in &cgcx.plugin_passes {
364+
if let Some(pass) = find_pass(pass_name) {
365+
extra_passes.push(pass);
366+
} else {
367+
diag_handler.err(&format!("a plugin asked for LLVM pass \
368+
`{}` but LLVM does not \
369+
recognize it", pass_name));
370+
}
371+
372+
if pass_name == "name-anon-globals" {
373+
have_name_anon_globals_pass = true;
374+
}
375+
}
353376

354377
// Some options cause LLVM bitcode to be emitted, which uses ThinLTOBuffers, so we need
355378
// to make sure we run LLVM's NameAnonGlobals pass when emitting bitcode; otherwise
356379
// we'll get errors in LLVM.
357380
let using_thin_buffers = config.bitcode_needed();
358-
let mut have_name_anon_globals_pass = false;
359381
if !config.no_prepopulate_passes {
360382
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
361383
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
@@ -364,34 +386,22 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
364386
let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal ||
365387
(cgcx.lto != Lto::Fat && cgcx.opts.cg.linker_plugin_lto.enabled());
366388
with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| {
389+
llvm::LLVMRustAddLastExtensionPasses(
390+
b, extra_passes.as_ptr(), extra_passes.len() as size_t);
367391
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
368392
llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
369393
});
370394

371395
have_name_anon_globals_pass = have_name_anon_globals_pass || prepare_for_thin_lto;
372396
if using_thin_buffers && !prepare_for_thin_lto {
373-
assert!(addpass("name-anon-globals"));
374-
have_name_anon_globals_pass = true;
375-
}
376-
}
377-
378-
for pass in &config.passes {
379-
if !addpass(pass) {
380-
diag_handler.warn(&format!("unknown pass `{}`, ignoring", pass));
381-
}
382-
if pass == "name-anon-globals" {
397+
llvm::LLVMRustAddPass(mpm, find_pass("name-anon-globals").unwrap());
383398
have_name_anon_globals_pass = true;
384399
}
385-
}
386-
387-
for pass in &cgcx.plugin_passes {
388-
if !addpass(pass) {
389-
diag_handler.err(&format!("a plugin asked for LLVM pass \
390-
`{}` but LLVM does not \
391-
recognize it", pass));
392-
}
393-
if pass == "name-anon-globals" {
394-
have_name_anon_globals_pass = true;
400+
} else {
401+
// If we don't use the standard pipeline, directly populate the MPM
402+
// with the extra passes.
403+
for pass in extra_passes {
404+
llvm::LLVMRustAddPass(mpm, pass);
395405
}
396406
}
397407

src/librustc_codegen_llvm/llvm/ffi.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1668,6 +1668,9 @@ extern "C" {
16681668
pub fn LLVMRustPassKind(Pass: &Pass) -> PassKind;
16691669
pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>;
16701670
pub fn LLVMRustAddPass(PM: &PassManager<'_>, Pass: &'static mut Pass);
1671+
pub fn LLVMRustAddLastExtensionPasses(PMB: &PassManagerBuilder,
1672+
Passes: *const &'static mut Pass,
1673+
NumPasses: size_t);
16711674

16721675
pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool;
16731676

src/rustllvm/PassWrapper.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,23 @@ void LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
9999
unwrap(PMBR)->populateThinLTOPassManager(*unwrap(PMR));
100100
}
101101

102+
extern "C"
103+
void LLVMRustAddLastExtensionPasses(
104+
LLVMPassManagerBuilderRef PMBR, LLVMPassRef *Passes, size_t NumPasses) {
105+
auto AddExtensionPasses = [Passes, NumPasses](
106+
const PassManagerBuilder &Builder, PassManagerBase &PM) {
107+
for (size_t I = 0; I < NumPasses; I++) {
108+
PM.add(unwrap(Passes[I]));
109+
}
110+
};
111+
// Add the passes to both of the pre-finalization extension points,
112+
// so they are run for optimized and non-optimized builds.
113+
unwrap(PMBR)->addExtension(PassManagerBuilder::EP_OptimizerLast,
114+
AddExtensionPasses);
115+
unwrap(PMBR)->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
116+
AddExtensionPasses);
117+
}
118+
102119
#ifdef LLVM_COMPONENT_X86
103120
#define SUBTARGET_X86 SUBTARGET(X86)
104121
#else

0 commit comments

Comments
 (0)