Skip to content

Commit

Permalink
rustc: Fix some ThinLTO internalization
Browse files Browse the repository at this point in the history
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
  • Loading branch information
alexcrichton committed Oct 15, 2017
1 parent df095ce commit 2e1c4cd
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 10 deletions.
20 changes: 19 additions & 1 deletion src/librustc_trans/back/lto.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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");
Expand Down
10 changes: 6 additions & 4 deletions src/librustc_trans/back/write.rs
Expand Up @@ -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>,
Expand Down Expand Up @@ -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);
})
Expand Down Expand Up @@ -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);
Expand Down
13 changes: 8 additions & 5 deletions src/rustllvm/PassWrapper.cpp
Expand Up @@ -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());
Expand All @@ -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);
}
}
}

Expand Down Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions src/test/run-pass/thinlto/auxiliary/dylib.rs
@@ -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 changes: 18 additions & 0 deletions src/test/run-pass/thinlto/dylib-works.rs
@@ -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);
}
File renamed without changes.
File renamed without changes.

0 comments on commit 2e1c4cd

Please sign in to comment.