yaxunl created this revision.
yaxunl added reviewers: rsmith, Anastasia.
yaxunl added subscribers: cfe-commits, tstellarAMD.

Sometimes a backend needs to apply certain target-specific passes before 
linking. This patch attempts to add that.

It depends on a new virtual member function addPreLinkPasses to be added to 
TargetMachine, which will be implemented by a separate patch for llvm.

http://reviews.llvm.org/D20681

Files:
  include/clang/CodeGen/BackendUtil.h
  lib/CodeGen/BackendUtil.cpp
  lib/CodeGen/CodeGenAction.cpp

Index: lib/CodeGen/CodeGenAction.cpp
===================================================================
--- lib/CodeGen/CodeGenAction.cpp
+++ lib/CodeGen/CodeGenAction.cpp
@@ -165,19 +165,20 @@
       void *OldDiagnosticContext = Ctx.getDiagnosticContext();
       Ctx.setDiagnosticHandler(DiagnosticHandler, this);
 
-      // Link LinkModule into this module if present, preserving its validity.
-      for (auto &I : LinkModules) {
-        unsigned LinkFlags = I.first;
-        CurLinkModule = I.second.get();
-        if (Linker::linkModules(*getModule(), std::move(I.second), LinkFlags))
-          return;
-      }
-
-      EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef());
-
+      std::function<bool(llvm::Module*)>
+        LinkCallBack = [=](llvm::Module *M)->bool {
+        // Link LinkModule into this module if present, preserving its validity.
+        for (auto &I : LinkModules) {
+          unsigned LinkFlags = I.first;
+          CurLinkModule = I.second.get();
+          if (Linker::linkModules(*getModule(), std::move(I.second), LinkFlags))
+            return true;
+        }
+        return false;
+      };
       EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts,
                         C.getTargetInfo().getDataLayout(),
-                        getModule(), Action, AsmOutStream);
+                        getModule(), Action, AsmOutStream, &LinkCallBack);
 
       Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);
 
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(raw_pwrite_stream &OS);
+
 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<TargetMachine> TM;
 
   void EmitAssembly(BackendAction Action, raw_pwrite_stream *OS);
+  void DoPreLinkPasses(raw_pwrite_stream *OS);
+
+  /// 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
@@ -504,6 +525,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;
@@ -625,6 +654,7 @@
   return TM;
 }
 
+
 bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action,
                                        raw_pwrite_stream &OS) {
 
@@ -662,17 +692,18 @@
   return true;
 }
 
+void EmitAssemblyHelper::AddPreLinkPasses(raw_pwrite_stream &OS) {
+  legacy::PassManager *PM = getPreLinkPasses();
+  TM->addPreLinkPasses(*PM, OS);
+}
+
 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;
@@ -748,14 +779,42 @@
   }
 }
 
-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) {
+void EmitAssemblyHelper::DoPreLinkPasses(raw_pwrite_stream *OS) {
+  TimeRegion Region(llvm::TimePassesIsEnabled ? &PreLinkTime : nullptr);
+
+  if (!TM)
+    return;
+
+  AddPreLinkPasses(*OS);
+
+  // 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,
+  std::function<bool(Module *)> *LinkCallBack) {
   EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M);
 
+  AsmHelper.setCommandLineOpts();
+  AsmHelper.setTarget(Action);
+
+  if (LinkCallBack) {
+    AsmHelper.DoPreLinkPasses(OS);
+    if ((*LinkCallBack)(M))
+      return;
+  }
+
+  EmbedBitcode(M, CGOpts, llvm::MemoryBufferRef());
+
   AsmHelper.EmitAssembly(Action, OS);
 
   // Verify clang's TargetInfo DataLayout against the LLVM TargetMachine's
Index: include/clang/CodeGen/BackendUtil.h
===================================================================
--- include/clang/CodeGen/BackendUtil.h
+++ include/clang/CodeGen/BackendUtil.h
@@ -12,6 +12,7 @@
 
 #include "clang/Basic/LLVM.h"
 #include "llvm/IR/ModuleSummaryIndex.h"
+#include <functional>
 #include <memory>
 
 namespace llvm {
@@ -34,10 +35,14 @@
     Backend_EmitObj        ///< Emit native object files
   };
 
-  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);
+  // LinkCallBack is a call back function for linking the input module with
+  // other modules.
+  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,
+    std::function<bool(llvm::Module *)> *LinkCallBack = nullptr);
 
   void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,
                     llvm::MemoryBufferRef Buf);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to