rustc: Fix some ThinLTO internalization
First the `addPreservedGUID` function forgot to take care of "alias" summaries. I'm not 100% sure what this is but the current code now matches upstream. Next the `computeDeadSymbols` return value wasn't actually being used, but it needed to be used! Together these should... Closes #45195
This commit is contained in:
parent
df095cefe2
commit
2e1c4cd0f5
8 changed files with 67 additions and 10 deletions
|
@ -130,6 +130,7 @@ pub fn run(cgcx: &CodegenContext,
|
|||
.filter_map(symbol_filter)
|
||||
.collect::<Vec<CString>>();
|
||||
timeline.record("whitelist");
|
||||
info!("{} symbols to preserve in this crate", symbol_white_list.len());
|
||||
|
||||
// If we're performing LTO for the entire crate graph, then for each of our
|
||||
// upstream dependencies, find the corresponding rlib and load the bitcode
|
||||
|
@ -437,7 +438,24 @@ fn run_pass_manager(cgcx: &CodegenContext,
|
|||
assert!(!pass.is_null());
|
||||
llvm::LLVMRustAddPass(pm, pass);
|
||||
|
||||
with_llvm_pmb(llmod, config, &mut |b| {
|
||||
// When optimizing for LTO we don't actually pass in `-O0`, but we force
|
||||
// it to always happen at least with `-O1`.
|
||||
//
|
||||
// With ThinLTO we mess around a lot with symbol visibility in a way
|
||||
// that will actually cause linking failures if we optimize at O0 which
|
||||
// notable is lacking in dead code elimination. To ensure we at least
|
||||
// get some optimizations and correctly link we forcibly switch to `-O1`
|
||||
// to get dead code elimination.
|
||||
//
|
||||
// Note that in general this shouldn't matter too much as you typically
|
||||
// only turn on ThinLTO when you're compiling with optimizations
|
||||
// otherwise.
|
||||
let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
|
||||
let opt_level = match opt_level {
|
||||
llvm::CodeGenOptLevel::None => llvm::CodeGenOptLevel::Less,
|
||||
level => level,
|
||||
};
|
||||
with_llvm_pmb(llmod, config, opt_level, &mut |b| {
|
||||
if thin {
|
||||
if !llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm) {
|
||||
panic!("this version of LLVM does not support ThinLTO");
|
||||
|
|
|
@ -217,7 +217,7 @@ pub struct ModuleConfig {
|
|||
passes: Vec<String>,
|
||||
/// Some(level) to optimize at a certain level, or None to run
|
||||
/// absolutely no optimizations (used for the metadata module).
|
||||
opt_level: Option<llvm::CodeGenOptLevel>,
|
||||
pub opt_level: Option<llvm::CodeGenOptLevel>,
|
||||
|
||||
/// Some(level) to optimize binary size, or None to not affect program size.
|
||||
opt_size: Option<llvm::CodeGenOptSize>,
|
||||
|
@ -507,7 +507,8 @@ unsafe fn optimize(cgcx: &CodegenContext,
|
|||
if !config.no_prepopulate_passes {
|
||||
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
|
||||
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
|
||||
with_llvm_pmb(llmod, &config, &mut |b| {
|
||||
let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
|
||||
with_llvm_pmb(llmod, &config, opt_level, &mut |b| {
|
||||
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
|
||||
llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
|
||||
})
|
||||
|
@ -1842,16 +1843,17 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
|
|||
|
||||
pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
|
||||
config: &ModuleConfig,
|
||||
opt_level: llvm::CodeGenOptLevel,
|
||||
f: &mut FnMut(llvm::PassManagerBuilderRef)) {
|
||||
// Create the PassManagerBuilder for LLVM. We configure it with
|
||||
// reasonable defaults and prepare it to actually populate the pass
|
||||
// manager.
|
||||
let builder = llvm::LLVMPassManagerBuilderCreate();
|
||||
let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
|
||||
let opt_size = config.opt_size.unwrap_or(llvm::CodeGenOptSizeNone);
|
||||
let inline_threshold = config.inline_threshold;
|
||||
|
||||
llvm::LLVMRustConfigurePassManagerBuilder(builder, opt_level,
|
||||
llvm::LLVMRustConfigurePassManagerBuilder(builder,
|
||||
opt_level,
|
||||
config.merge_functions,
|
||||
config.vectorize_slp,
|
||||
config.vectorize_loop);
|
||||
|
|
|
@ -901,9 +901,7 @@ addPreservedGUID(const ModuleSummaryIndex &Index,
|
|||
}
|
||||
}
|
||||
|
||||
GlobalValueSummary *GVSummary = Summary.get();
|
||||
if (isa<FunctionSummary>(GVSummary)) {
|
||||
FunctionSummary *FS = cast<FunctionSummary>(GVSummary);
|
||||
if (auto *FS = dyn_cast<FunctionSummary>(Summary.get())) {
|
||||
for (auto &Call: FS->calls()) {
|
||||
if (Call.first.isGUID()) {
|
||||
addPreservedGUID(Index, Preserved, Call.first.getGUID());
|
||||
|
@ -916,6 +914,10 @@ addPreservedGUID(const ModuleSummaryIndex &Index,
|
|||
addPreservedGUID(Index, Preserved, GUID);
|
||||
}
|
||||
}
|
||||
if (auto *AS = dyn_cast<AliasSummary>(Summary.get())) {
|
||||
auto GUID = AS->getAliasee().getOriginalName();
|
||||
addPreservedGUID(Index, Preserved, GUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -963,12 +965,13 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
|
|||
// combined index
|
||||
//
|
||||
// This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
|
||||
computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols);
|
||||
auto DeadSymbols = computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols);
|
||||
ComputeCrossModuleImport(
|
||||
Ret->Index,
|
||||
Ret->ModuleToDefinedGVSummaries,
|
||||
Ret->ImportLists,
|
||||
Ret->ExportLists
|
||||
Ret->ExportLists,
|
||||
&DeadSymbols
|
||||
);
|
||||
|
||||
// Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
|
||||
|
|
16
src/test/run-pass/thinlto/auxiliary/dylib.rs
Normal file
16
src/test/run-pass/thinlto/auxiliary/dylib.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z thinlto -C codegen-units=8
|
||||
|
||||
#[inline]
|
||||
pub fn foo(b: u8) {
|
||||
b.to_string();
|
||||
}
|
18
src/test/run-pass/thinlto/dylib-works.rs
Normal file
18
src/test/run-pass/thinlto/dylib-works.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// aux-build:dylib.rs
|
||||
// min-llvm-version 4.0
|
||||
|
||||
extern crate dylib;
|
||||
|
||||
fn main() {
|
||||
dylib::foo(1);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue