about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2018-05-12 14:07:20 +0200
committerNikita Popov <nikita.ppv@gmail.com>2018-05-12 14:07:20 +0200
commita70ef4cb49295563a09b254de4751c016c79e262 (patch)
tree9f326ad2710a9d1d9d698ec6096a3a9a11a38264
parentc705877b1df780acfb2dcba4ebca6f30102dd8a2 (diff)
downloadrust-a70ef4cb49295563a09b254de4751c016c79e262.tar.gz
rust-a70ef4cb49295563a09b254de4751c016c79e262.zip
Set PrepareForThinLTO flag when using ThinLTO
The LLVM PassManager has a PrepareForThinLTO flag, which is intended
when compilation occurs in conjunction with linking by ThinLTO. The
flag has two effects:

 * The NameAnonGlobal pass is run after all other passes, which
   ensures that all globals have a name.
 * In optimized builds, a number of late passes (mainly related to
   vectorization and unrolling) are disabled, on the rationale that
   these a) will increase codesize of the intermediate artifacts
   and b) will be run by ThinLTO again anyway.

This patch enables the use of PrepareForThinLTO if Thin or ThinLocal
linking is used.

The background for this change is the CI failure in #49479, which
we assume to be caused by the NameAnonGlobal pass not being run.
As this changes which passes LLVM runs, this might have performance
(or other) impact, so we want to land this separately.
-rw-r--r--src/librustc_llvm/ffi.rs1
-rw-r--r--src/librustc_trans/back/lto.rs2
-rw-r--r--src/librustc_trans/back/write.rs5
-rw-r--r--src/rustllvm/PassWrapper.cpp5
4 files changed, 10 insertions, 3 deletions
diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs
index dba2e918f6f..c1e32c7c022 100644
--- a/src/librustc_llvm/ffi.rs
+++ b/src/librustc_llvm/ffi.rs
@@ -1651,6 +1651,7 @@ extern "C" {
                                                MergeFunctions: bool,
                                                SLPVectorize: bool,
                                                LoopVectorize: bool,
+                                               PrepareForThinLTO: bool,
                                                PGOGenPath: *const c_char,
                                                PGOUsePath: *const c_char);
     pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef,
diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs
index 2a473f1ecbc..bbb5f7eecc8 100644
--- a/src/librustc_trans/back/lto.rs
+++ b/src/librustc_trans/back/lto.rs
@@ -482,7 +482,7 @@ fn run_pass_manager(cgcx: &CodegenContext,
             llvm::CodeGenOptLevel::None => llvm::CodeGenOptLevel::Less,
             level => level,
         };
-        with_llvm_pmb(llmod, config, opt_level, &mut |b| {
+        with_llvm_pmb(llmod, config, opt_level, false, &mut |b| {
             if thin {
                 if !llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm) {
                     panic!("this version of LLVM does not support ThinLTO");
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 64876e82309..57fe0729375 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -547,7 +547,8 @@ unsafe fn optimize(cgcx: &CodegenContext,
             llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
             llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
             let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
-            with_llvm_pmb(llmod, &config, opt_level, &mut |b| {
+            let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal;
+            with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| {
                 llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
                 llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
             })
@@ -2042,6 +2043,7 @@ pub fn run_assembler(cgcx: &CodegenContext, handler: &Handler, assembly: &Path,
 pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
                             config: &ModuleConfig,
                             opt_level: llvm::CodeGenOptLevel,
+                            prepare_for_thin_lto: bool,
                             f: &mut FnMut(llvm::PassManagerBuilderRef)) {
     use std::ptr;
 
@@ -2069,6 +2071,7 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
         config.merge_functions,
         config.vectorize_slp,
         config.vectorize_loop,
+        prepare_for_thin_lto,
         pgo_gen_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
         pgo_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
     );
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 382ef2cc407..8593f543619 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -428,13 +428,16 @@ extern "C" void LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
 
 extern "C" void LLVMRustConfigurePassManagerBuilder(
     LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
-    bool MergeFunctions, bool SLPVectorize, bool LoopVectorize,
+    bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO,
     const char* PGOGenPath, const char* PGOUsePath) {
   // Ignore mergefunc for now as enabling it causes crashes.
   // unwrap(PMBR)->MergeFunctions = MergeFunctions;
   unwrap(PMBR)->SLPVectorize = SLPVectorize;
   unwrap(PMBR)->OptLevel = fromRust(OptLevel);
   unwrap(PMBR)->LoopVectorize = LoopVectorize;
+#if LLVM_VERSION_GE(4, 0)
+  unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO;
+#endif
 
 #ifdef PGO_AVAILABLE
   if (PGOGenPath) {