diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index e4807f10805c9..c1f247d8a3223 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -603,6 +603,19 @@ struct LLVMRustSanitizerOptions { extern "C" typedef void (*registerEnzymeAndPassPipelineFn)( llvm::PassBuilder &PB, bool augment); +/// Forces the bitcode writer to emit full LTO summary instead of thin LTO +/// summary for embedded bitcode under Fat LTO. +/// +/// Note the bitcode writer will only emit the full LTO block ID if the +/// "ThinLTO" metadata is defined and explicitly set to zero. Otherwise, +/// the thin LTO block ID will be emitted. +static void forceFullLTOSummary(Module *M) { + assert(!M->getModuleFlag("ThinLTO")); + + auto *Zero = ConstantInt::get(Type::getInt32Ty(M->getContext()), 0); + M->addModuleFlag(Module::Error, "ThinLTO", Zero); +} + extern "C" LLVMRustResult LLVMRustOptimize( LLVMModuleRef ModuleRef, LLVMTargetMachineRef TMRef, LLVMRustPassBuilderOptLevel OptLevelRust, LLVMRustOptStage OptStage, @@ -950,7 +963,10 @@ extern "C" LLVMRustResult LLVMRustOptimize( ThinLTODataOS, ThinLTOSummaryBufferRef ? &ThinLinkDataOS : nullptr)); } else { - MPM.addPass(BitcodeWriterPass(ThinLTODataOS)); + forceFullLTOSummary(TheModule); + MPM.addPass(BitcodeWriterPass(ThinLTODataOS, + /*ShouldPreserveUseListOrder=*/false, + /*EmitSummaryIndex=*/true)); } *ThinLTOBufferRef = ThinLTOBuffer.release(); if (ThinLTOSummaryBufferRef) { @@ -1469,26 +1485,30 @@ extern "C" LLVMRustBuffer *LLVMRustModuleSerialize(LLVMModuleRef M, { auto OS = raw_string_ostream(Ret->data); { - if (is_thin) { - PassBuilder PB; - LoopAnalysisManager LAM; - FunctionAnalysisManager FAM; - CGSCCAnalysisManager CGAM; - ModuleAnalysisManager MAM; - PB.registerModuleAnalyses(MAM); - PB.registerCGSCCAnalyses(CGAM); - PB.registerFunctionAnalyses(FAM); - PB.registerLoopAnalyses(LAM); - PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); - ModulePassManager MPM; + PassBuilder PB; + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + PB.registerModuleAnalyses(MAM); + PB.registerCGSCCAnalyses(CGAM); + PB.registerFunctionAnalyses(FAM); + PB.registerLoopAnalyses(LAM); + PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); + + ModulePassManager MPM; #if LLVM_VERSION_GE(23, 0) - MPM.addPass(AssignGUIDPass()); + MPM.addPass(AssignGUIDPass()); #endif + + if (is_thin) { MPM.addPass(ThinLTOBitcodeWriterPass(OS, nullptr)); - MPM.run(*unwrap(M), MAM); } else { - WriteBitcodeToFile(*unwrap(M), OS); + forceFullLTOSummary(unwrap(M)); + MPM.addPass(BitcodeWriterPass(OS, /*ShouldPreserveUseListOrder=*/false, + /*EmitSummaryIndex=*/true)); } + MPM.run(*unwrap(M), MAM); } } return Ret.release(); diff --git a/tests/run-make/fat-lto-module-summary/foo.rs b/tests/run-make/fat-lto-module-summary/foo.rs new file mode 100644 index 0000000000000..b76b4321d62aa --- /dev/null +++ b/tests/run-make/fat-lto-module-summary/foo.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/tests/run-make/fat-lto-module-summary/rmake.rs b/tests/run-make/fat-lto-module-summary/rmake.rs new file mode 100644 index 0000000000000..f04416c68fd96 --- /dev/null +++ b/tests/run-make/fat-lto-module-summary/rmake.rs @@ -0,0 +1,10 @@ +use run_make_support::{llvm_bcanalyzer, rustc}; + +fn main() { + rustc().input("foo.rs").crate_type("lib").arg("-Clto=fat").arg("--emit=llvm-bc").run(); + + llvm_bcanalyzer() + .input("foo.bc") + .run() + .assert_stdout_contains("FULL_LTO_GLOBALVAL_SUMMARY_BLOCK"); +}