diff options
Diffstat (limited to 'lib/CodeGen/BackendUtil.cpp')
-rw-r--r-- | lib/CodeGen/BackendUtil.cpp | 282 |
1 files changed, 183 insertions, 99 deletions
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index e2349da5f0a46..415bd9626220a 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -26,6 +26,7 @@ #include "llvm/Bitcode/BitcodeWriterPass.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LegacyPassManager.h" @@ -44,17 +45,19 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/Transforms/Coroutines.h" #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/InstCombine/InstCombine.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Instrumentation/BoundsChecking.h" +#include "llvm/Transforms/Instrumentation/GCOVProfiler.h" #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar/GVN.h" +#include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Utils/NameAnonGlobals.h" #include "llvm/Transforms/Utils/SymbolRewriter.h" #include <memory> @@ -101,7 +104,18 @@ class EmitAssemblyHelper { /// /// \return True on success. bool AddEmitPasses(legacy::PassManager &CodeGenPasses, BackendAction Action, - raw_pwrite_stream &OS); + raw_pwrite_stream &OS, raw_pwrite_stream *DwoOS); + + std::unique_ptr<llvm::ToolOutputFile> openOutputFile(StringRef Path) { + std::error_code EC; + auto F = llvm::make_unique<llvm::ToolOutputFile>(Path, EC, + llvm::sys::fs::F_None); + if (EC) { + Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message(); + F.reset(); + } + return F; + } public: EmitAssemblyHelper(DiagnosticsEngine &_Diags, @@ -231,10 +245,9 @@ static void addAddressSanitizerPasses(const PassManagerBuilder &Builder, static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { PM.add(createAddressSanitizerFunctionPass( - /*CompileKernel*/ true, - /*Recover*/ true, /*UseAfterScope*/ false)); - PM.add(createAddressSanitizerModulePass(/*CompileKernel*/true, - /*Recover*/true)); + /*CompileKernel*/ true, /*Recover*/ true, /*UseAfterScope*/ false)); + PM.add(createAddressSanitizerModulePass( + /*CompileKernel*/ true, /*Recover*/ true)); } static void addHWAddressSanitizerPasses(const PassManagerBuilder &Builder, @@ -243,7 +256,13 @@ static void addHWAddressSanitizerPasses(const PassManagerBuilder &Builder, static_cast<const PassManagerBuilderWrapper &>(Builder); const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::HWAddress); - PM.add(createHWAddressSanitizerPass(Recover)); + PM.add(createHWAddressSanitizerPass(/*CompileKernel*/ false, Recover)); +} + +static void addKernelHWAddressSanitizerPasses(const PassManagerBuilder &Builder, + legacy::PassManagerBase &PM) { + PM.add(createHWAddressSanitizerPass( + /*CompileKernel*/ true, /*Recover*/ true)); } static void addMemorySanitizerPass(const PassManagerBuilder &Builder, @@ -361,21 +380,6 @@ getCodeModel(const CodeGenOptions &CodeGenOpts) { return static_cast<llvm::CodeModel::Model>(CodeModel); } -static llvm::Reloc::Model getRelocModel(const CodeGenOptions &CodeGenOpts) { - // Keep this synced with the equivalent code in - // lib/Frontend/CompilerInvocation.cpp - llvm::Optional<llvm::Reloc::Model> RM; - RM = llvm::StringSwitch<llvm::Reloc::Model>(CodeGenOpts.RelocationModel) - .Case("static", llvm::Reloc::Static) - .Case("pic", llvm::Reloc::PIC_) - .Case("ropi", llvm::Reloc::ROPI) - .Case("rwpi", llvm::Reloc::RWPI) - .Case("ropi-rwpi", llvm::Reloc::ROPI_RWPI) - .Case("dynamic-no-pic", llvm::Reloc::DynamicNoPIC); - assert(RM.hasValue() && "invalid PIC model!"); - return *RM; -} - static TargetMachine::CodeGenFileType getCodeGenFileType(BackendAction Action) { if (Action == Backend_EmitObj) return TargetMachine::CGFT_ObjectFile; @@ -447,7 +451,10 @@ static void initTargetOptions(llvm::TargetOptions &Options, Options.DataSections = CodeGenOpts.DataSections; Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames; Options.EmulatedTLS = CodeGenOpts.EmulatedTLS; + Options.ExplicitEmulatedTLS = CodeGenOpts.ExplicitEmulatedTLS; Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning(); + Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection; + Options.EmitAddrsig = CodeGenOpts.Addrsig; if (CodeGenOpts.EnableSplitDwarf) Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile; @@ -470,6 +477,23 @@ static void initTargetOptions(llvm::TargetOptions &Options, Options.MCOptions.IASSearchPaths.push_back( Entry.IgnoreSysRoot ? Entry.Path : HSOpts.Sysroot + Entry.Path); } +static Optional<GCOVOptions> getGCOVOptions(const CodeGenOptions &CodeGenOpts) { + if (CodeGenOpts.DisableGCov) + return None; + if (!CodeGenOpts.EmitGcovArcs && !CodeGenOpts.EmitGcovNotes) + return None; + // Not using 'GCOVOptions::getDefault' allows us to avoid exiting if + // LLVM's -default-gcov-version flag is set to something invalid. + GCOVOptions Options; + Options.EmitNotes = CodeGenOpts.EmitGcovNotes; + Options.EmitData = CodeGenOpts.EmitGcovArcs; + llvm::copy(CodeGenOpts.CoverageVersion, std::begin(Options.Version)); + Options.UseCfgChecksum = CodeGenOpts.CoverageExtraChecksum; + Options.NoRedZone = CodeGenOpts.DisableRedZone; + Options.FunctionNamesInData = !CodeGenOpts.CoverageNoFunctionNamesInData; + Options.ExitBlockBeforeBody = CodeGenOpts.CoverageExitBlockBeforeBody; + return Options; +} void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, legacy::FunctionPassManager &FPM) { @@ -501,7 +525,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, PMBuilder.Inliner = createFunctionInliningPass( CodeGenOpts.OptimizationLevel, CodeGenOpts.OptimizeSize, (!CodeGenOpts.SampleProfileFile.empty() && - CodeGenOpts.EmitSummaryIndex)); + CodeGenOpts.PrepareForThinLTO)); } PMBuilder.OptLevel = CodeGenOpts.OptimizationLevel; @@ -511,7 +535,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops; PMBuilder.MergeFunctions = CodeGenOpts.MergeFunctions; - PMBuilder.PrepareForThinLTO = CodeGenOpts.EmitSummaryIndex; + PMBuilder.PrepareForThinLTO = CodeGenOpts.PrepareForThinLTO; PMBuilder.PrepareForLTO = CodeGenOpts.PrepareForLTO; PMBuilder.RerollLoops = CodeGenOpts.RerollLoops; @@ -535,6 +559,9 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, addObjCARCOptPass); } + if (LangOpts.CoroutinesTS) + addCoroutinePassesToExtensionPoints(PMBuilder); + if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds)) { PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate, addBoundsCheckingPass); @@ -572,6 +599,13 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, addHWAddressSanitizerPasses); } + if (LangOpts.Sanitize.has(SanitizerKind::KernelHWAddress)) { + PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, + addKernelHWAddressSanitizerPasses); + PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, + addKernelHWAddressSanitizerPasses); + } + if (LangOpts.Sanitize.has(SanitizerKind::Memory)) { PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, addMemorySanitizerPass); @@ -593,9 +627,6 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, addDataFlowSanitizerPass); } - if (LangOpts.CoroutinesTS) - addCoroutinePassesToExtensionPoints(PMBuilder); - if (LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) { PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, addEfficiencySanitizerPass); @@ -612,20 +643,8 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, if (!CodeGenOpts.RewriteMapFiles.empty()) addSymbolRewriterPass(CodeGenOpts, &MPM); - if (!CodeGenOpts.DisableGCov && - (CodeGenOpts.EmitGcovArcs || CodeGenOpts.EmitGcovNotes)) { - // Not using 'GCOVOptions::getDefault' allows us to avoid exiting if - // LLVM's -default-gcov-version flag is set to something invalid. - GCOVOptions Options; - Options.EmitNotes = CodeGenOpts.EmitGcovNotes; - Options.EmitData = CodeGenOpts.EmitGcovArcs; - memcpy(Options.Version, CodeGenOpts.CoverageVersion, 4); - Options.UseCfgChecksum = CodeGenOpts.CoverageExtraChecksum; - Options.NoRedZone = CodeGenOpts.DisableRedZone; - Options.FunctionNamesInData = - !CodeGenOpts.CoverageNoFunctionNamesInData; - Options.ExitBlockBeforeBody = CodeGenOpts.CoverageExitBlockBeforeBody; - MPM.add(createGCOVProfilerPass(Options)); + if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts)) { + MPM.add(createGCOVProfilerPass(*Options)); if (CodeGenOpts.getDebugInfo() == codegenoptions::NoDebugInfo) MPM.add(createStripSymbolsPass(true)); } @@ -664,8 +683,6 @@ static void setCommandLineOpts(const CodeGenOptions &CodeGenOpts) { BackendArgs.push_back("-limit-float-precision"); BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str()); } - for (const std::string &BackendOption : CodeGenOpts.BackendOptions) - BackendArgs.push_back(BackendOption.c_str()); BackendArgs.push_back(nullptr); llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, BackendArgs.data()); @@ -685,7 +702,7 @@ void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) { Optional<llvm::CodeModel::Model> CM = getCodeModel(CodeGenOpts); std::string FeaturesStr = llvm::join(TargetOpts.Features.begin(), TargetOpts.Features.end(), ","); - llvm::Reloc::Model RM = getRelocModel(CodeGenOpts); + llvm::Reloc::Model RM = CodeGenOpts.RelocationModel; CodeGenOpt::Level OptLevel = getCGOptLevel(CodeGenOpts); llvm::TargetOptions Options; @@ -696,7 +713,8 @@ void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) { bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses, BackendAction Action, - raw_pwrite_stream &OS) { + raw_pwrite_stream &OS, + raw_pwrite_stream *DwoOS) { // Add LibraryInfo. llvm::Triple TargetTriple(TheModule->getTargetTriple()); std::unique_ptr<TargetLibraryInfoImpl> TLII( @@ -713,7 +731,7 @@ bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses, if (CodeGenOpts.OptimizationLevel > 0) CodeGenPasses.add(createObjCARCContractPass()); - if (TM->addPassesToEmitFile(CodeGenPasses, OS, CGFT, + if (TM->addPassesToEmitFile(CodeGenPasses, OS, DwoOS, CGFT, /*DisableVerify=*/!CodeGenOpts.VerifyModule)) { Diags.Report(diag::err_fe_unable_to_interface_with_target); return false; @@ -724,7 +742,7 @@ bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses, void EmitAssemblyHelper::EmitAssembly(BackendAction Action, std::unique_ptr<raw_pwrite_stream> OS) { - TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr); + TimeRegion Region(FrontendTimesIsEnabled ? &CodeGenerationTime : nullptr); setCommandLineOpts(CodeGenOpts); @@ -752,31 +770,35 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, CodeGenPasses.add( createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); - std::unique_ptr<raw_fd_ostream> ThinLinkOS; + std::unique_ptr<llvm::ToolOutputFile> ThinLinkOS, DwoOS; switch (Action) { case Backend_EmitNothing: break; case Backend_EmitBC: - if (CodeGenOpts.EmitSummaryIndex) { + if (CodeGenOpts.PrepareForThinLTO) { if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { - std::error_code EC; - ThinLinkOS.reset(new llvm::raw_fd_ostream( - CodeGenOpts.ThinLinkBitcodeFile, EC, - llvm::sys::fs::F_None)); - if (EC) { - Diags.Report(diag::err_fe_unable_to_open_output) << CodeGenOpts.ThinLinkBitcodeFile - << EC.message(); + ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile); + if (!ThinLinkOS) return; - } } + PerModulePasses.add(createWriteThinLTOBitcodePass( + *OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr)); + } else { + // Emit a module summary by default for Regular LTO except for ld64 + // targets + bool EmitLTOSummary = + (CodeGenOpts.PrepareForLTO && + llvm::Triple(TheModule->getTargetTriple()).getVendor() != + llvm::Triple::Apple); + if (EmitLTOSummary && !TheModule->getModuleFlag("ThinLTO")) + TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0)); + PerModulePasses.add( - createWriteThinLTOBitcodePass(*OS, ThinLinkOS.get())); + createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, + EmitLTOSummary)); } - else - PerModulePasses.add( - createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists)); break; case Backend_EmitLL: @@ -785,7 +807,13 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, break; default: - if (!AddEmitPasses(CodeGenPasses, Action, *OS)) + if (!CodeGenOpts.SplitDwarfFile.empty()) { + DwoOS = openOutputFile(CodeGenOpts.SplitDwarfFile); + if (!DwoOS) + return; + } + if (!AddEmitPasses(CodeGenPasses, Action, *OS, + DwoOS ? &DwoOS->os() : nullptr)) return; } @@ -814,6 +842,11 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, PrettyStackTraceString CrashInfo("Code generation"); CodeGenPasses.run(*TheModule); } + + if (ThinLinkOS) + ThinLinkOS->keep(); + if (DwoOS) + DwoOS->keep(); } static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) { @@ -827,7 +860,7 @@ static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) { case 2: switch (Opts.OptimizeSize) { default: - llvm_unreachable("Invalide optimization level for size!"); + llvm_unreachable("Invalid optimization level for size!"); case 0: return PassBuilder::O2; @@ -854,7 +887,7 @@ static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) { /// `EmitAssembly` at some point in the future when the default switches. void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( BackendAction Action, std::unique_ptr<raw_pwrite_stream> OS) { - TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr); + TimeRegion Region(FrontendTimesIsEnabled ? &CodeGenerationTime : nullptr); setCommandLineOpts(CodeGenOpts); // The new pass manager always makes a target machine available to passes @@ -913,10 +946,13 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( ModulePassManager MPM(CodeGenOpts.DebugPassManager); if (!CodeGenOpts.DisableLLVMPasses) { - bool IsThinLTO = CodeGenOpts.EmitSummaryIndex; + bool IsThinLTO = CodeGenOpts.PrepareForThinLTO; bool IsLTO = CodeGenOpts.PrepareForLTO; if (CodeGenOpts.OptimizationLevel == 0) { + if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts)) + MPM.addPass(GCOVProfilerPass(*Options)); + // Build a minimal pipeline based on the semantics required by Clang, // which is just that always inlining occurs. MPM.addPass(AlwaysInlinerPass()); @@ -925,8 +961,8 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds)) MPM.addPass(createModuleToFunctionPassAdaptor(BoundsCheckingPass())); - // Lastly, add a semantically necessary pass for ThinLTO. - if (IsThinLTO) + // Lastly, add a semantically necessary pass for LTO. + if (IsLTO || IsThinLTO) MPM.addPass(NameAnonGlobalPass()); } else { // Map our optimization levels into one of the distinct levels used to @@ -940,6 +976,10 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { FPM.addPass(BoundsCheckingPass()); }); + if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts)) + PB.registerPipelineStartEPCallback([Options](ModulePassManager &MPM) { + MPM.addPass(GCOVProfilerPass(*Options)); + }); if (IsThinLTO) { MPM = PB.buildThinLTOPreLinkDefaultPipeline( @@ -948,6 +988,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( } else if (IsLTO) { MPM = PB.buildLTOPreLinkDefaultPipeline(Level, CodeGenOpts.DebugPassManager); + MPM.addPass(NameAnonGlobalPass()); } else { MPM = PB.buildPerModuleDefaultPipeline(Level, CodeGenOpts.DebugPassManager); @@ -959,7 +1000,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( // create that pass manager here and use it as needed below. legacy::PassManager CodeGenPasses; bool NeedCodeGen = false; - Optional<raw_fd_ostream> ThinLinkOS; + std::unique_ptr<llvm::ToolOutputFile> ThinLinkOS, DwoOS; // Append any output we need to the pass manager. switch (Action) { @@ -967,23 +1008,26 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( break; case Backend_EmitBC: - if (CodeGenOpts.EmitSummaryIndex) { + if (CodeGenOpts.PrepareForThinLTO) { 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(); + ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile); + if (!ThinLinkOS) return; - } } - MPM.addPass( - ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &*ThinLinkOS : nullptr)); + MPM.addPass(ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &ThinLinkOS->os() + : nullptr)); } else { + // Emit a module summary by default for Regular LTO except for ld64 + // targets + bool EmitLTOSummary = + (CodeGenOpts.PrepareForLTO && + llvm::Triple(TheModule->getTargetTriple()).getVendor() != + llvm::Triple::Apple); + if (EmitLTOSummary && !TheModule->getModuleFlag("ThinLTO")) + TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0)); + MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, - CodeGenOpts.EmitSummaryIndex, - CodeGenOpts.EmitSummaryIndex)); + EmitLTOSummary)); } break; @@ -997,7 +1041,13 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( NeedCodeGen = true; CodeGenPasses.add( createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); - if (!AddEmitPasses(CodeGenPasses, Action, *OS)) + if (!CodeGenOpts.SplitDwarfFile.empty()) { + DwoOS = openOutputFile(CodeGenOpts.SplitDwarfFile); + if (!DwoOS) + return; + } + if (!AddEmitPasses(CodeGenPasses, Action, *OS, + DwoOS ? &DwoOS->os() : nullptr)) // FIXME: Should we handle this error differently? return; break; @@ -1017,6 +1067,11 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( PrettyStackTraceString CrashInfo("Code generation"); CodeGenPasses.run(*TheModule); } + + if (ThinLinkOS) + ThinLinkOS->keep(); + if (DwoOS) + DwoOS->keep(); } Expected<BitcodeModule> clang::FindThinLTOModule(MemoryBufferRef MBRef) { @@ -1026,16 +1081,22 @@ Expected<BitcodeModule> clang::FindThinLTOModule(MemoryBufferRef MBRef) { // The bitcode file may contain multiple modules, we want the one that is // marked as being the ThinLTO module. - for (BitcodeModule &BM : *BMsOrErr) { - Expected<BitcodeLTOInfo> LTOInfo = BM.getLTOInfo(); - if (LTOInfo && LTOInfo->IsThinLTO) - return BM; - } + if (const BitcodeModule *Bm = FindThinLTOModule(*BMsOrErr)) + return *Bm; return make_error<StringError>("Could not find module summary", inconvertibleErrorCode()); } +BitcodeModule *clang::FindThinLTOModule(MutableArrayRef<BitcodeModule> BMs) { + for (BitcodeModule &BM : BMs) { + Expected<BitcodeLTOInfo> LTOInfo = BM.getLTOInfo(); + if (LTOInfo && LTOInfo->IsThinLTO) + return &BM; + } + return nullptr; +} + static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, const HeaderSearchOptions &HeaderOpts, const CodeGenOptions &CGOpts, @@ -1067,9 +1128,8 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, // e.g. record required linkage changes. if (Summary->modulePath() == M->getModuleIdentifier()) continue; - // Doesn't matter what value we plug in to the map, just needs an entry - // to provoke importing by thinBackend. - ImportList[Summary->modulePath()][GUID] = 1; + // Add an entry to provoke importing by thinBackend. + ImportList[Summary->modulePath()].insert(GUID); } std::vector<std::unique_ptr<llvm::MemoryBuffer>> OwnedImports; @@ -1100,15 +1160,27 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, return llvm::make_unique<lto::NativeObjectStream>(std::move(OS)); }; lto::Config Conf; + if (CGOpts.SaveTempsFilePrefix != "") { + if (Error E = Conf.addSaveTemps(CGOpts.SaveTempsFilePrefix + ".", + /* UseInputModulePath */ false)) { + handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) { + errs() << "Error setting up ThinLTO save-temps: " << EIB.message() + << '\n'; + }); + } + } Conf.CPU = TOpts.CPU; Conf.CodeModel = getCodeModel(CGOpts); Conf.MAttrs = TOpts.Features; - Conf.RelocModel = getRelocModel(CGOpts); + Conf.RelocModel = CGOpts.RelocationModel; Conf.CGOptLevel = getCGOptLevel(CGOpts); initTargetOptions(Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts); Conf.SampleProfile = std::move(SampleProfile); Conf.UseNewPM = CGOpts.ExperimentalNewPassManager; Conf.DebugPassManager = CGOpts.DebugPassManager; + Conf.RemarksWithHotness = CGOpts.DiagnosticsWithHotness; + Conf.RemarksFilename = CGOpts.OptRecordFile; + Conf.DwoPath = CGOpts.SplitDwarfFile; switch (Action) { case Backend_EmitNothing: Conf.PreCodeGenModuleHook = [](size_t Task, const Module &Mod) { @@ -1123,7 +1195,7 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, break; case Backend_EmitBC: Conf.PreCodeGenModuleHook = [&](size_t Task, const Module &Mod) { - WriteBitcodeToFile(M, *OS, CGOpts.EmitLLVMUseLists); + WriteBitcodeToFile(*M, *OS, CGOpts.EmitLLVMUseLists); return false; }; break; @@ -1132,7 +1204,7 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, break; } if (Error E = thinBackend( - Conf, 0, AddStream, *M, *CombinedIndex, ImportList, + Conf, -1, AddStream, *M, *CombinedIndex, ImportList, ModuleToDefinedGVSummaries[M->getModuleIdentifier()], ModuleMap)) { handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) { errs() << "Error running ThinLTO backend: " << EIB.message() << '\n'; @@ -1148,6 +1220,7 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags, const llvm::DataLayout &TDesc, Module *M, BackendAction Action, std::unique_ptr<raw_pwrite_stream> OS) { + std::unique_ptr<llvm::Module> EmptyModule; if (!CGOpts.ThinLTOIndexFile.empty()) { // If we are performing a ThinLTO importing compile, load the function index // into memory and pass it into runThinLTOBackend, which will run the @@ -1165,11 +1238,22 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags, // A null CombinedIndex means we should skip ThinLTO compilation // (LLVM will optionally ignore empty index files, returning null instead // of an error). - bool DoThinLTOBackend = CombinedIndex != nullptr; - if (DoThinLTOBackend) { - runThinLTOBackend(CombinedIndex.get(), M, HeaderOpts, CGOpts, TOpts, - LOpts, std::move(OS), CGOpts.SampleProfileFile, Action); - return; + if (CombinedIndex) { + if (!CombinedIndex->skipModuleByDistributedBackend()) { + runThinLTOBackend(CombinedIndex.get(), M, HeaderOpts, CGOpts, TOpts, + LOpts, std::move(OS), CGOpts.SampleProfileFile, + Action); + return; + } + // Distributed indexing detected that nothing from the module is needed + // for the final linking. So we can skip the compilation. We sill need to + // output an empty object file to make sure that a linker does not fail + // trying to read it. Also for some features, like CFI, we must skip + // the compilation as CombinedIndex does not contain all required + // information. + EmptyModule = llvm::make_unique<llvm::Module>("empty", M->getContext()); + EmptyModule->setTargetTriple(M->getTargetTriple()); + M = EmptyModule.get(); } } @@ -1228,7 +1312,7 @@ void clang::EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts, // Save llvm.compiler.used and remote it. SmallVector<Constant*, 2> UsedArray; - SmallSet<GlobalValue*, 4> UsedGlobals; + SmallPtrSet<GlobalValue*, 4> UsedGlobals; Type *UsedElementType = Type::getInt8Ty(M->getContext())->getPointerTo(0); GlobalVariable *Used = collectUsedGlobalVariables(*M, UsedGlobals, true); for (auto *GV : UsedGlobals) { @@ -1253,7 +1337,7 @@ void clang::EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts, // If the input is LLVM Assembly, bitcode is produced by serializing // the module. Use-lists order need to be perserved in this case. llvm::raw_string_ostream OS(Data); - llvm::WriteBitcodeToFile(M, OS, /* ShouldPreserveUseListOrder */ true); + llvm::WriteBitcodeToFile(*M, OS, /* ShouldPreserveUseListOrder */ true); ModuleData = ArrayRef<uint8_t>((const uint8_t *)OS.str().data(), OS.str().size()); } else |