Index: include/clang/CodeGen/BackendUtil.h =================================================================== --- include/clang/CodeGen/BackendUtil.h +++ include/clang/CodeGen/BackendUtil.h @@ -37,10 +37,15 @@ void EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts, const TargetOptions &TOpts, const LangOptions &LOpts, const llvm::DataLayout &TDesc, llvm::Module *M, - BackendAction Action, raw_pwrite_stream *OS); + BackendAction Action, raw_pwrite_stream *OS, + bool SetLLVMOpts = true); void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts, llvm::MemoryBufferRef Buf); -} + void PerformPrelinkPasses(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts, + const TargetOptions &TOpts, const LangOptions &LOpts, + const llvm::DataLayout &TDesc, llvm::Module *M, + BackendAction Action); +} #endif Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -59,8 +59,10 @@ const LangOptions &LangOpts; Module *TheModule; + Timer PreLinkTime; Timer CodeGenerationTime; + mutable legacy::PassManager *PreLinkPasses; mutable legacy::PassManager *CodeGenPasses; mutable legacy::PassManager *PerModulePasses; mutable legacy::FunctionPassManager *PerFunctionPasses; @@ -100,8 +102,14 @@ return PerFunctionPasses; } - /// Set LLVM command line options passed through -backend-option. - void setCommandLineOpts(); + legacy::PassManager *getPreLinkPasses() const { + if (!PreLinkPasses) { + PreLinkPasses = new legacy::PassManager(); + PreLinkPasses->add( + createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); + } + return PreLinkPasses; + } void CreatePasses(ModuleSummaryIndex *ModuleSummary); @@ -120,16 +128,21 @@ /// \return True on success. bool AddEmitPasses(BackendAction Action, raw_pwrite_stream &OS); + /// Add target specific pre-linking passes. + void AddPreLinkPasses(); + public: EmitAssemblyHelper(DiagnosticsEngine &_Diags, const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts, const LangOptions &LOpts, Module *M) : Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts), LangOpts(LOpts), - TheModule(M), CodeGenerationTime("Code Generation Time"), + TheModule(M), PreLinkTime("Pre-Linking Passes Time"), + CodeGenerationTime("Code Generation Time"), PreLinkPasses(nullptr), CodeGenPasses(nullptr), PerModulePasses(nullptr), PerFunctionPasses(nullptr) {} ~EmitAssemblyHelper() { + delete PreLinkPasses; delete CodeGenPasses; delete PerModulePasses; delete PerFunctionPasses; @@ -140,6 +153,14 @@ std::unique_ptr TM; void EmitAssembly(BackendAction Action, raw_pwrite_stream *OS); + void DoPreLinkPasses(); + + /// Set LLVM command line options passed through -backend-option. + void setCommandLineOpts(); + + /// Set up target for target specific pre-linking passes and LLVM code + /// generation. + void setTarget(BackendAction Action); }; // We need this wrapper to access LangOpts and CGOpts from extension functions @@ -515,6 +536,14 @@ BackendArgs.data()); } +void EmitAssemblyHelper::setTarget(BackendAction Action) { + bool UsesCodeGen = (Action != Backend_EmitNothing && + Action != Backend_EmitBC && + Action != Backend_EmitLL); + if (!TM) + TM.reset(CreateTargetMachine(UsesCodeGen)); +} + TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) { // Create the TargetMachine for generating code. std::string Error; @@ -674,17 +703,18 @@ return true; } +void EmitAssemblyHelper::AddPreLinkPasses() { + legacy::PassManager *PM = getPreLinkPasses(); + TM->addPreLinkPasses(*PM); +} + void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_pwrite_stream *OS) { TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr); - setCommandLineOpts(); - bool UsesCodeGen = (Action != Backend_EmitNothing && Action != Backend_EmitBC && Action != Backend_EmitLL); - if (!TM) - TM.reset(CreateTargetMachine(UsesCodeGen)); if (UsesCodeGen && !TM) return; @@ -760,14 +790,35 @@ } } +void EmitAssemblyHelper::DoPreLinkPasses() { + TimeRegion Region(llvm::TimePassesIsEnabled ? &PreLinkTime : nullptr); + + if (!TM) + return; + + AddPreLinkPasses(); + + // Before executing passes, print the final values of the LLVM options. + cl::PrintOptionValues(); + + if (PreLinkPasses) { + PrettyStackTraceString CrashInfo("Pre-linking passes"); + PreLinkPasses->run(*TheModule); + } +} + void clang::EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts, const LangOptions &LOpts, const llvm::DataLayout &TDesc, Module *M, BackendAction Action, - raw_pwrite_stream *OS) { + raw_pwrite_stream *OS, + bool SetLLVMOpts) { EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M); + if (SetLLVMOpts) + AsmHelper.setCommandLineOpts(); + AsmHelper.setTarget(Action); AsmHelper.EmitAssembly(Action, OS); // Verify clang's TargetInfo DataLayout against the LLVM TargetMachine's @@ -783,6 +834,18 @@ } } +void clang::PerformPrelinkPasses(DiagnosticsEngine &Diags, + const CodeGenOptions &CGOpts, + const clang::TargetOptions &TOpts, + const LangOptions &LOpts, const llvm::DataLayout &TDesc, + Module *M, BackendAction Action) { + EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M); + + AsmHelper.setCommandLineOpts(); + AsmHelper.setTarget(Action); + AsmHelper.DoPreLinkPasses(); +} + static const char* getSectionNameForBitcode(const Triple &T) { switch (T.getObjectFormat()) { case Triple::MachO: Index: lib/CodeGen/CodeGenAction.cpp =================================================================== --- lib/CodeGen/CodeGenAction.cpp +++ lib/CodeGen/CodeGenAction.cpp @@ -165,6 +165,10 @@ void *OldDiagnosticContext = Ctx.getDiagnosticContext(); Ctx.setDiagnosticHandler(DiagnosticHandler, this); + PerformPrelinkPasses(Diags, CodeGenOpts, TargetOpts, LangOpts, + C.getTargetInfo().getDataLayout(), + getModule(), Action); + // Link LinkModule into this module if present, preserving its validity. for (auto &I : LinkModules) { unsigned LinkFlags = I.first; @@ -177,7 +181,8 @@ EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts, C.getTargetInfo().getDataLayout(), - getModule(), Action, AsmOutStream); + getModule(), Action, AsmOutStream, + false /* SetLLVMOpts */); Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);