Skip to content

Commit 29ed49f

Browse files
committed
Auto merge of #45215 - alexcrichton:thin-lto-reference-more, r=michaelwoerister
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
2 parents c4f489a + 2e1c4cd commit 29ed49f

File tree

8 files changed

+67
-10
lines changed

8 files changed

+67
-10
lines changed

src/librustc_trans/back/lto.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ pub fn run(cgcx: &CodegenContext,
130130
.filter_map(symbol_filter)
131131
.collect::<Vec<CString>>();
132132
timeline.record("whitelist");
133+
info!("{} symbols to preserve in this crate", symbol_white_list.len());
133134

134135
// If we're performing LTO for the entire crate graph, then for each of our
135136
// upstream dependencies, find the corresponding rlib and load the bitcode
@@ -437,7 +438,24 @@ fn run_pass_manager(cgcx: &CodegenContext,
437438
assert!(!pass.is_null());
438439
llvm::LLVMRustAddPass(pm, pass);
439440

440-
with_llvm_pmb(llmod, config, &mut |b| {
441+
// When optimizing for LTO we don't actually pass in `-O0`, but we force
442+
// it to always happen at least with `-O1`.
443+
//
444+
// With ThinLTO we mess around a lot with symbol visibility in a way
445+
// that will actually cause linking failures if we optimize at O0 which
446+
// notable is lacking in dead code elimination. To ensure we at least
447+
// get some optimizations and correctly link we forcibly switch to `-O1`
448+
// to get dead code elimination.
449+
//
450+
// Note that in general this shouldn't matter too much as you typically
451+
// only turn on ThinLTO when you're compiling with optimizations
452+
// otherwise.
453+
let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
454+
let opt_level = match opt_level {
455+
llvm::CodeGenOptLevel::None => llvm::CodeGenOptLevel::Less,
456+
level => level,
457+
};
458+
with_llvm_pmb(llmod, config, opt_level, &mut |b| {
441459
if thin {
442460
if !llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm) {
443461
panic!("this version of LLVM does not support ThinLTO");

src/librustc_trans/back/write.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ pub struct ModuleConfig {
217217
passes: Vec<String>,
218218
/// Some(level) to optimize at a certain level, or None to run
219219
/// absolutely no optimizations (used for the metadata module).
220-
opt_level: Option<llvm::CodeGenOptLevel>,
220+
pub opt_level: Option<llvm::CodeGenOptLevel>,
221221

222222
/// Some(level) to optimize binary size, or None to not affect program size.
223223
opt_size: Option<llvm::CodeGenOptSize>,
@@ -507,7 +507,8 @@ unsafe fn optimize(cgcx: &CodegenContext,
507507
if !config.no_prepopulate_passes {
508508
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
509509
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
510-
with_llvm_pmb(llmod, &config, &mut |b| {
510+
let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
511+
with_llvm_pmb(llmod, &config, opt_level, &mut |b| {
511512
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
512513
llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
513514
})
@@ -1842,16 +1843,17 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
18421843

18431844
pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
18441845
config: &ModuleConfig,
1846+
opt_level: llvm::CodeGenOptLevel,
18451847
f: &mut FnMut(llvm::PassManagerBuilderRef)) {
18461848
// Create the PassManagerBuilder for LLVM. We configure it with
18471849
// reasonable defaults and prepare it to actually populate the pass
18481850
// manager.
18491851
let builder = llvm::LLVMPassManagerBuilderCreate();
1850-
let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
18511852
let opt_size = config.opt_size.unwrap_or(llvm::CodeGenOptSizeNone);
18521853
let inline_threshold = config.inline_threshold;
18531854

1854-
llvm::LLVMRustConfigurePassManagerBuilder(builder, opt_level,
1855+
llvm::LLVMRustConfigurePassManagerBuilder(builder,
1856+
opt_level,
18551857
config.merge_functions,
18561858
config.vectorize_slp,
18571859
config.vectorize_loop);

src/rustllvm/PassWrapper.cpp

+8-5
Original file line numberDiff line numberDiff line change
@@ -901,9 +901,7 @@ addPreservedGUID(const ModuleSummaryIndex &Index,
901901
}
902902
}
903903

904-
GlobalValueSummary *GVSummary = Summary.get();
905-
if (isa<FunctionSummary>(GVSummary)) {
906-
FunctionSummary *FS = cast<FunctionSummary>(GVSummary);
904+
if (auto *FS = dyn_cast<FunctionSummary>(Summary.get())) {
907905
for (auto &Call: FS->calls()) {
908906
if (Call.first.isGUID()) {
909907
addPreservedGUID(Index, Preserved, Call.first.getGUID());
@@ -916,6 +914,10 @@ addPreservedGUID(const ModuleSummaryIndex &Index,
916914
addPreservedGUID(Index, Preserved, GUID);
917915
}
918916
}
917+
if (auto *AS = dyn_cast<AliasSummary>(Summary.get())) {
918+
auto GUID = AS->getAliasee().getOriginalName();
919+
addPreservedGUID(Index, Preserved, GUID);
920+
}
919921
}
920922
}
921923

@@ -963,12 +965,13 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
963965
// combined index
964966
//
965967
// This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
966-
computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols);
968+
auto DeadSymbols = computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols);
967969
ComputeCrossModuleImport(
968970
Ret->Index,
969971
Ret->ModuleToDefinedGVSummaries,
970972
Ret->ImportLists,
971-
Ret->ExportLists
973+
Ret->ExportLists,
974+
&DeadSymbols
972975
);
973976

974977
// Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z thinlto -C codegen-units=8
12+
13+
#[inline]
14+
pub fn foo(b: u8) {
15+
b.to_string();
16+
}
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:dylib.rs
12+
// min-llvm-version 4.0
13+
14+
extern crate dylib;
15+
16+
fn main() {
17+
dylib::foo(1);
18+
}

0 commit comments

Comments
 (0)