Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -49,6 +49,7 @@ #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" @@ -898,6 +899,7 @@ // create that pass manager here and use it as needed below. legacy::PassManager CodeGenPasses; bool NeedCodeGen = false; + Optional ThinLinkOS; // Append any output we need to the pass manager. switch (Action) { @@ -905,9 +907,24 @@ break; case Backend_EmitBC: - MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, - CodeGenOpts.EmitSummaryIndex, - CodeGenOpts.EmitSummaryIndex)); + if (CodeGenOpts.EmitSummaryIndex) { + if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { + std::error_code EC; + ThinLinkOS.emplace(CodeGenOpts.ThinLinkBitcodeFile, EC, + llvm::sys::fs::F_None); + if (EC) { + Diags.Report(diag::err_fe_unable_to_open_output) + << CodeGenOpts.ThinLinkBitcodeFile << EC.message(); + return; + } + } + MPM.addPass( + ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &*ThinLinkOS : nullptr)); + } else { + MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, + CodeGenOpts.EmitSummaryIndex, + CodeGenOpts.EmitSummaryIndex)); + } break; case Backend_EmitLL: Index: clang/test/CodeGen/thin_link_bitcode.c =================================================================== --- clang/test/CodeGen/thin_link_bitcode.c +++ clang/test/CodeGen/thin_link_bitcode.c @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -o %t -flto=thin -fthin-link-bitcode=%t.nodebug -triple x86_64-unknown-linux-gnu -emit-llvm-bc -debug-info-kind=limited %s // RUN: llvm-bcanalyzer -dump %t | FileCheck %s // RUN: llvm-bcanalyzer -dump %t.nodebug | FileCheck %s --check-prefix=NO_DEBUG +// RUN: %clang_cc1 -o %t.newpm -flto=thin -fexperimental-new-pass-manager -fthin-link-bitcode=%t.newpm.nodebug -triple x86_64-unknown-linux-gnu -emit-llvm-bc -debug-info-kind=limited %s +// RUN: llvm-bcanalyzer -dump %t.newpm | FileCheck %s +// RUN: llvm-bcanalyzer -dump %t.newpm.nodebug | FileCheck %s --check-prefix=NO_DEBUG int main (void) { return 0; } Index: llvm/include/llvm/Transforms/IPO/ThinLTOBitcodeWriter.h =================================================================== --- /dev/null +++ llvm/include/llvm/Transforms/IPO/ThinLTOBitcodeWriter.h @@ -0,0 +1,39 @@ +//===- ThinLTOBitcodeWriter.h - Bitcode writing pass for ThinLTO ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass prepares a module containing type metadata for ThinLTO by splitting +// it into regular and thin LTO parts if possible, and writing both parts to +// a multi-module bitcode file. Modules that do not contain type metadata are +// written unmodified as a single module. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_THINLTOBITCODEWRITER_H +#define LLVM_TRANSFORMS_IPO_THINLTOBITCODEWRITER_H + +#include +#include + +namespace llvm { + +class ThinLTOBitcodeWriterPass + : public PassInfoMixin { + raw_ostream &OS; + raw_ostream *ThinLinkOS; + +public: + ThinLTOBitcodeWriterPass(raw_ostream &OS, raw_ostream *ThinLinkOS) + : OS(OS), ThinLinkOS(ThinLinkOS) {} + + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // namespace llvm + +#endif Index: llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp =================================================================== --- llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -7,13 +7,11 @@ // //===----------------------------------------------------------------------===// // -// This pass prepares a module containing type metadata for ThinLTO by splitting -// it into regular and thin LTO parts if possible, and writing both parts to -// a multi-module bitcode file. Modules that do not contain type metadata are -// written unmodified as a single module. +// Pass implementation. // //===----------------------------------------------------------------------===// +#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" #include "llvm/Analysis/BasicAliasAnalysis.h" #include "llvm/Analysis/ModuleSummaryAnalysis.h" #include "llvm/Analysis/ProfileSummaryInfo.h" @@ -436,3 +434,15 @@ raw_ostream *ThinLinkOS) { return new WriteThinLTOBitcode(Str, ThinLinkOS); } + +PreservedAnalyses +llvm::ThinLTOBitcodeWriterPass::run(Module &M, ModuleAnalysisManager &AM) { + FunctionAnalysisManager &FAM = + AM.getResult(M).getManager(); + writeThinLTOBitcode(OS, ThinLinkOS, + [&FAM](Function &F) -> AAResults & { + return FAM.getResult(F); + }, + M, &AM.getResult(M)); + return PreservedAnalyses::all(); +} Index: llvm/test/Transforms/ThinLTOBitcodeWriter/new-pm.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/ThinLTOBitcodeWriter/new-pm.ll @@ -0,0 +1,9 @@ +; RUN: opt -passes='lto' -debug-pass-manager -thinlto-bc -thin-link-bitcode-file=%t2 -o %t %s 2>&1 | FileCheck %s --check-prefix=DEBUG_PM +; RUN: llvm-bcanalyzer -dump %t2 | FileCheck %s --check-prefix=BITCODE + +; DEBUG_PM: ThinLTOBitcodeWriterPass +; BITCODE: Foo + +define void @Foo() { + ret void +} Index: llvm/tools/opt/NewPMDriver.h =================================================================== --- llvm/tools/opt/NewPMDriver.h +++ llvm/tools/opt/NewPMDriver.h @@ -21,6 +21,8 @@ #ifndef LLVM_TOOLS_OPT_NEWPMDRIVER_H #define LLVM_TOOLS_OPT_NEWPMDRIVER_H +#include + namespace llvm { class StringRef; class LLVMContext; @@ -47,13 +49,16 @@ /// inclusion of the new pass manager headers and the old headers into the same /// file. It's interface is consequentially somewhat ad-hoc, but will go away /// when the transition finishes. -bool runPassPipeline(StringRef Arg0, Module &M, - TargetMachine *TM, tool_output_file *Out, - StringRef PassPipeline, opt_tool::OutputKind OK, - opt_tool::VerifierKind VK, +/// +/// ThinLTOBC indicates whether to use ThinLTO's bitcode writer, and if so, +/// the optional link file path. +bool runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM, + tool_output_file *Out, StringRef PassPipeline, + opt_tool::OutputKind OK, opt_tool::VerifierKind VK, bool ShouldPreserveAssemblyUseListOrder, bool ShouldPreserveBitcodeUseListOrder, - bool EmitSummaryIndex, bool EmitModuleHash); + bool EmitSummaryIndex, bool EmitModuleHash, + Optional ThinLTOBC); } #endif Index: llvm/tools/opt/NewPMDriver.cpp =================================================================== --- llvm/tools/opt/NewPMDriver.cpp +++ llvm/tools/opt/NewPMDriver.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" #include "llvm/Transforms/Scalar/LoopPassManager.h" using namespace llvm; @@ -47,13 +48,13 @@ "pipeline for handling managed aliasing queries"), cl::Hidden); -bool llvm::runPassPipeline(StringRef Arg0, Module &M, - TargetMachine *TM, tool_output_file *Out, - StringRef PassPipeline, OutputKind OK, - VerifierKind VK, +bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM, + tool_output_file *Out, StringRef PassPipeline, + OutputKind OK, VerifierKind VK, bool ShouldPreserveAssemblyUseListOrder, bool ShouldPreserveBitcodeUseListOrder, - bool EmitSummaryIndex, bool EmitModuleHash) { + bool EmitSummaryIndex, bool EmitModuleHash, + Optional ThinLTOBC) { PassBuilder PB(TM); // Specially handle the alias analysis manager so that we can register @@ -101,8 +102,12 @@ PrintModulePass(Out->os(), "", ShouldPreserveAssemblyUseListOrder)); break; case OK_OutputBitcode: - MPM.addPass(BitcodeWriterPass(Out->os(), ShouldPreserveBitcodeUseListOrder, - EmitSummaryIndex, EmitModuleHash)); + if (ThinLTOBC) + MPM.addPass(ThinLTOBitcodeWriterPass( + Out->os(), *ThinLTOBC ? &(*ThinLTOBC)->os() : nullptr)); + else + MPM.addPass(BitcodeWriterPass( + Out->os(), ShouldPreserveBitcodeUseListOrder, false, EmitModuleHash)); break; } Index: llvm/tools/opt/opt.cpp =================================================================== --- llvm/tools/opt/opt.cpp +++ llvm/tools/opt/opt.cpp @@ -529,12 +529,19 @@ // The user has asked to use the new pass manager and provided a pipeline // string. Hand off the rest of the functionality to the new code for that // layer. - return runPassPipeline(argv[0], *M, TM.get(), Out.get(), - PassPipeline, OK, VK, PreserveAssemblyUseListOrder, - PreserveBitcodeUseListOrder, EmitSummaryIndex, - EmitModuleHash) - ? 0 - : 1; + Optional ThinLTOBC; + if (OutputThinLTOBC) + ThinLTOBC.emplace(ThinLinkOut.get()); + if (!runPassPipeline(argv[0], *M, TM.get(), Out.get(), PassPipeline, OK, VK, + PreserveAssemblyUseListOrder, + PreserveBitcodeUseListOrder, EmitSummaryIndex, + EmitModuleHash, ThinLTOBC)) + return 1; + + if (ThinLinkOut) + ThinLinkOut->keep(); + + return 0; } // Create a PassManager to hold and optimize the collection of passes we are