jhuber6 created this revision.
jhuber6 added reviewers: jdoerfert, ronlieb, gregrodgers, JonChesterfield.
Herald added subscribers: ormris, dang, steven_wu, guansong, hiraditya, yaxunl.
jhuber6 requested review of this revision.
Herald added subscribers: llvm-commits, cfe-commits, sstefan1.
Herald added projects: clang, LLVM.

Summary;
This patch adds support for embedding device images via the
`fopenmp-target-jit` command to be used for JIT compilation. This is
used in conjunction with `-foffload-lto` to do bitcode linking and
embedding of the device image in the final executable rather than
creating an exectuable. This will be used for JIT in the future.

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D117049

Files:
  clang/include/clang/Basic/DiagnosticDriverKinds.td
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
  llvm/include/llvm/LTO/LTO.h
  llvm/lib/LTO/LTO.cpp

Index: llvm/lib/LTO/LTO.cpp
===================================================================
--- llvm/lib/LTO/LTO.cpp
+++ llvm/lib/LTO/LTO.cpp
@@ -958,6 +958,8 @@
   return RegularLTO.ParallelCodeGenParallelismLevel + ModuleCount;
 }
 
+Config &LTO::getLTOConfig() { return Conf; }
+
 // If only some of the modules were split, we cannot correctly handle
 // code that contains type tests or type checked loads.
 Error LTO::checkPartiallySplit() {
Index: llvm/include/llvm/LTO/LTO.h
===================================================================
--- llvm/include/llvm/LTO/LTO.h
+++ llvm/include/llvm/LTO/LTO.h
@@ -259,6 +259,9 @@
   /// full description of tasks see LTOBackend.h.
   unsigned getMaxTasks() const;
 
+  /// Returns the current configuration for the LTO object.
+  Config &getLTOConfig();
+
   /// Runs the LTO pipeline. This function calls the supplied AddStream
   /// function to add native object files to the link.
   ///
Index: clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
===================================================================
--- clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -76,6 +76,11 @@
                    cl::desc("Path for the target bitcode library"),
                    cl::cat(ClangLinkerWrapperCategory));
 
+static cl::opt<bool> EmbedBC(
+    "target-embed-bc", cl::ZeroOrMore,
+    cl::desc("Embed linked bitcode instead of an executable device image."),
+    cl::init(true), cl::cat(ClangLinkerWrapperCategory));
+
 // Do not parse linker options.
 static cl::list<std::string>
     HostLinkerArgs(cl::Sink, cl::desc("<options to be passed to linker>..."));
@@ -422,8 +427,8 @@
 
   std::unique_ptr<MemoryBuffer> Buffer =
       MemoryBuffer::getMemBuffer(Library.getMemoryBufferRef(), false);
-  if (Error Err = writeArchive(TempFile, Members, true, Library.kind(),
-                                    true, Library.isThin(), std::move(Buffer)))
+  if (Error Err = writeArchive(TempFile, Members, true, Library.kind(), true,
+                               Library.isThin(), std::move(Buffer)))
     return std::move(Err);
 
   return static_cast<std::string>(TempFile);
@@ -748,6 +753,12 @@
       return std::move(Err);
   }
 
+  auto HandleError = [&](std::error_code EC) {
+    logAllUnhandledErrors(errorCodeToError(EC),
+                          WithColor::error(errs(), LinkerExecutable));
+    exit(1);
+  };
+
   // Run the LTO job to compile the bitcode.
   size_t MaxTasks = LTOBackend->getMaxTasks();
   std::vector<SmallString<128>> Files(MaxTasks);
@@ -757,16 +768,36 @@
     StringRef Extension = (TheTriple.isNVPTX()) ? "s" : "o";
     if (std::error_code EC = sys::fs::createTemporaryFile(
             "lto-" + TheTriple.getTriple(), Extension, FD, TempFile))
-      return nullptr;
+      HandleError(EC);
     TempFiles.push_back(static_cast<std::string>(TempFile));
     return std::make_unique<CachedFileStream>(
         std::make_unique<llvm::raw_fd_ostream>(FD, true));
   };
+  auto LinkOnly = [&](size_t Task, const Module &M) {
+    int FD = -1;
+    Files.resize(1);
+    auto &TempFile = Files.front();
+    if (std::error_code EC = sys::fs::createTemporaryFile(
+            "jit-" + TheTriple.getTriple(), "bc", FD, TempFile))
+      HandleError(EC);
+    std::error_code EC;
+    raw_fd_ostream LinkedBitcode(TempFile, EC, sys::fs::OF_None);
+    if (EC)
+      HandleError(EC);
+    WriteBitcodeToFile(M, LinkedBitcode);
+    TempFiles.push_back(static_cast<std::string>(TempFile));
+    return false;
+  };
+
+  // If we are doing JIT, stop after the module has been sompletely linked.
+  if (EmbedBC)
+    LTOBackend->getLTOConfig().PostInternalizeModuleHook = LinkOnly;
+
   if (Error Err = LTOBackend->run(AddStream))
     return std::move(Err);
 
   for (auto &File : Files) {
-    if (!TheTriple.isNVPTX())
+    if (!TheTriple.isNVPTX() || EmbedBC)
       continue;
 
     auto FileOrErr = nvptx::assemble(File, TheTriple, Arch);
@@ -794,11 +825,16 @@
     Triple TheTriple(TargetFeatures.first);
     StringRef Arch(TargetFeatures.second);
 
-    // TODO: Run LTO or bitcode linking before the final link job.
     auto ObjectOrErr =
         linkBitcodeFiles(LinkerInput.getValue(), TheTriple, Arch);
     if (!ObjectOrErr)
       return ObjectOrErr.takeError();
+
+    if (EmbedBC) {
+      LinkedImages.push_back(**ObjectOrErr);
+      continue;
+    }
+
     if ((*ObjectOrErr).hasValue())
       LinkerInput.getValue() = {**ObjectOrErr};
 
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -8133,6 +8133,12 @@
                                  const char *LinkingOutput) const {
   ArgStringList CmdArgs;
 
+  if (!C.getDriver().isUsingLTO(/* IsOffload */ true) &&
+      Args.hasFlag(options::OPT_fopenmp_target_jit,
+                   options::OPT_fno_openmp_target_jit, /*Default*/ false)) {
+    C.getDriver().Diag(clang::diag::err_drv_openmp_jit_without_lto);
+  }
+
   if (getToolChain().getDriver().isUsingLTO(/* IsOffload */ true)) {
     // Pass in target features for each toolchain.
     auto OpenMPTCRange = C.getOffloadToolChains<Action::OFK_OpenMP>();
@@ -8192,6 +8198,11 @@
       if (!OOpt.empty())
         CmdArgs.push_back(Args.MakeArgString(Twine("-opt-level=O") + OOpt));
     }
+
+    if (Args.hasFlag(options::OPT_fopenmp_target_jit,
+                     options::OPT_fno_openmp_target_jit,
+                     /*Default=*/false))
+      CmdArgs.push_back(Args.MakeArgString("-target-embed-bc"));
   }
 
   // Construct the link job so we can wrap around it.
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2460,6 +2460,10 @@
   Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
 def fno_openmp_assume_threads_oversubscription : Flag<["-"], "fno-openmp-assume-threads-oversubscription">,
   Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
+def fopenmp_target_jit : Flag<["-"], "fopenmp-target-jit">, Group<f_Group>,
+  HelpText<"Enable JIT comilation for OpenMP Offloading">, Flags<[ NoArgumentUnused]>;
+def fno_openmp_target_jit : Flag<["-"], "fno-openmp-target-jit">, Group<f_Group>,
+  Flags<[NoArgumentUnused, HelpHidden]>;
 defm openmp_target_new_runtime: BoolFOption<"openmp-target-new-runtime",
   LangOpts<"OpenMPTargetNewRuntime">, DefaultTrue,
   PosFlag<SetTrue, [CC1Option], "Use the new bitcode library for OpenMP offloading">,
Index: clang/include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -161,6 +161,8 @@
   "invalid Xarch argument: '%0', options requiring arguments are unsupported">;
 def err_drv_Xopenmp_target_missing_triple : Error<
   "cannot deduce implicit triple value for -Xopenmp-target, specify triple using -Xopenmp-target=<triple>">;
+def err_drv_openmp_jit_without_lto : Error<
+  "cannot enable OpenMP offloading JIT, specify bitcode compilation with '-foffload-lto'">;
 def err_drv_invalid_Xopenmp_target_with_args : Error<
   "invalid -Xopenmp-target argument: '%0', options requiring arguments are unsupported">;
 def err_drv_argument_only_allowed_with : Error<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to