jhuber6 created this revision.
jhuber6 added reviewers: jdoerfert, MaskRay, fhahn, tra, yaxunl, 
JonChesterfield, tianshilei1992.
Herald added subscribers: ormris, StephenFan, steven_wu, hiraditya, inglorion.
Herald added a project: All.
jhuber6 requested review of this revision.
Herald added projects: clang, LLVM.
Herald added subscribers: llvm-commits, cfe-commits.

The LTO pass currently only offers assembly or object file outputs. We
can obtain the final LLVM output using the hooks, but is inconvenient
and disrupts the flow of the compilation. This patch proposes adding a
convenience function to perform this if the user requires it. We would
like this for the desire to retain the post-optimized LTO bitcode for
LLVM offloading compileations, such as JIT, builtin linking, or
performing a relocatable link on LLVM-IR.

Depends on D152442 <https://reviews.llvm.org/D152442>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D152461

Files:
  clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
  llvm/include/llvm/LTO/Config.h
  llvm/lib/LTO/LTOBackend.cpp

Index: llvm/lib/LTO/LTOBackend.cpp
===================================================================
--- llvm/lib/LTO/LTOBackend.cpp
+++ llvm/lib/LTO/LTOBackend.cpp
@@ -366,6 +366,17 @@
   if (Conf.PreCodeGenModuleHook && !Conf.PreCodeGenModuleHook(Task, Mod))
     return;
 
+  if (Conf.OutputPreCodegenBitcode) {
+    Expected<std::unique_ptr<CachedFileStream>> StreamOrErr =
+        AddStream(Task, Mod.getModuleIdentifier());
+    if (Error Err = StreamOrErr.takeError())
+      report_fatal_error(std::move(Err));
+    std::unique_ptr<CachedFileStream> &Stream = *StreamOrErr;
+
+    WriteBitcodeToFile(Mod, *Stream->OS);
+    return;
+  }
+
   if (EmbedBitcode == LTOBitcodeEmbedding::EmbedOptimized)
     llvm::embedBitcodeInModule(Mod, llvm::MemoryBufferRef(),
                                /*EmbedBitcode*/ true,
Index: llvm/include/llvm/LTO/Config.h
===================================================================
--- llvm/include/llvm/LTO/Config.h
+++ llvm/include/llvm/LTO/Config.h
@@ -84,6 +84,10 @@
   /// want to know a priori all possible output files.
   bool AlwaysEmitRegularLTOObj = false;
 
+  /// Write the pre-codegen module to the output without performing codegen.
+  /// Useful for post-processing on the fully linked LTO module.
+  bool OutputPreCodegenBitcode = false;
+
   /// Allows non-imported definitions to get the potentially more constraining
   /// visibility from the prevailing definition. FromPrevailing is the default
   /// because it works for many binary formats. ELF can use the more optimized
Index: clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
===================================================================
--- clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -509,10 +509,8 @@
   return UnifiedFeatures;
 }
 
-template <typename ModuleHook = function_ref<bool(size_t, const Module &)>>
-std::unique_ptr<lto::LTO> createLTO(
-    const ArgList &Args, const std::vector<std::string> &Features,
-    ModuleHook Hook = [](size_t, const Module &) { return true; }) {
+std::unique_ptr<lto::LTO> createLTO(const ArgList &Args,
+                                    const std::vector<std::string> &Features) {
   const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
   StringRef Arch = Args.getLastArgValue(OPT_arch_EQ);
   lto::Config Conf;
@@ -566,7 +564,9 @@
       return true;
     };
   }
-  Conf.PostOptModuleHook = Hook;
+  Conf.OutputPreCodegenBitcode = Args.hasArg(OPT_embed_bitcode) ||
+                                 Args.hasArg(OPT_builtin_bitcode_EQ) ||
+                                 Args.hasArg(OPT_clang_backend);
   Conf.CGFileType =
       (Triple.isNVPTX() || SaveTemps) ? CGFT_AssemblyFile : CGFT_ObjectFile;
 
@@ -639,31 +639,9 @@
   // Remove all the bitcode files that we moved from the original input.
   llvm::erase_if(InputFiles, [](OffloadFile &F) { return !F.getBinary(); });
 
-  // LTO Module hook to output bitcode without running the backend.
-  SmallVector<StringRef> BitcodeOutput;
-  auto OutputBitcode = [&](size_t, const Module &M) {
-    auto TempFileOrErr = createOutputFile(sys::path::filename(ExecutableName) +
-                                              "-jit-" + Triple.getTriple(),
-                                          "bc");
-    if (!TempFileOrErr)
-      reportError(TempFileOrErr.takeError());
-
-    std::error_code EC;
-    raw_fd_ostream LinkedBitcode(*TempFileOrErr, EC, sys::fs::OF_None);
-    if (EC)
-      reportError(errorCodeToError(EC));
-    WriteBitcodeToFile(M, LinkedBitcode);
-    BitcodeOutput.push_back(*TempFileOrErr);
-    return false;
-  };
-
   // We assume visibility of the whole program if every input file was bitcode.
   auto Features = getTargetFeatures(BitcodeInputFiles);
-  auto LTOBackend = Args.hasArg(OPT_embed_bitcode) ||
-                            Args.hasArg(OPT_builtin_bitcode_EQ) ||
-                            Args.hasArg(OPT_clang_backend)
-                        ? createLTO(Args, Features, OutputBitcode)
-                        : createLTO(Args, Features);
+  auto LTOBackend = createLTO(Args, Features);
 
   // We need to resolve the symbols so the LTO backend knows which symbols need
   // to be kept or can be internalized. This is a simplified symbol resolution
@@ -736,9 +714,18 @@
   auto AddStream =
       [&](size_t Task,
           const Twine &ModuleName) -> std::unique_ptr<CachedFileStream> {
+    bool OutputBitcode = Args.hasArg(OPT_embed_bitcode) ||
+                         Args.hasArg(OPT_builtin_bitcode_EQ) ||
+                         Args.hasArg(OPT_clang_backend);
     int FD = -1;
     auto &TempFile = Files[Task];
-    StringRef Extension = (Triple.isNVPTX() || SaveTemps) ? "s" : "o";
+    StringRef Extension;
+    if (OutputBitcode)
+      Extension = "bc";
+    else if (Triple.isNVPTX() || SaveTemps)
+      Extension = "s";
+    else
+      Extension = "o";
     std::string TaskStr = Task ? "." + std::to_string(Task) : "";
     auto TempFileOrErr =
         createOutputFile(sys::path::filename(ExecutableName) + "." +
@@ -747,6 +734,7 @@
     if (!TempFileOrErr)
       reportError(TempFileOrErr.takeError());
     TempFile = *TempFileOrErr;
+    llvm::errs() << "!!! " << TempFile << "\n";
     if (std::error_code EC = sys::fs::openFileForWrite(TempFile, FD))
       reportError(errorCodeToError(EC));
     return std::make_unique<CachedFileStream>(
@@ -760,22 +748,13 @@
     return createStringError(inconvertibleErrorCode(),
                              "Errors encountered inside the LTO pipeline.");
 
-  // If we are embedding bitcode we only need the intermediate output.
-  bool SingleOutput = Files.size() == 1;
-  if (Args.hasArg(OPT_embed_bitcode)) {
-    if (BitcodeOutput.size() != 1 || !SingleOutput)
+  if (Args.hasArg(OPT_embed_bitcode))
+    if (Files.size() != 1)
       return createStringError(inconvertibleErrorCode(),
                                "Cannot embed bitcode with multiple files.");
-    OutputFiles.push_back(Args.MakeArgString(BitcodeOutput.front()));
-    return Error::success();
-  }
 
-  // Append the new inputs to the device linker input. If the user requested an
-  // internalizing link we need to pass the bitcode to clang.
-  for (StringRef File :
-       Args.hasArg(OPT_clang_backend) || Args.hasArg(OPT_builtin_bitcode_EQ)
-           ? BitcodeOutput
-           : Files)
+  // Append the new inputs to the device linker input.
+  for (StringRef File : Files)
     OutputFiles.push_back(File);
 
   return Error::success();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D152461: [LTO] Add a ... Joseph Huber via Phabricator via cfe-commits

Reply via email to