[clang] 24ecafb - [OpenMP] Add support for CPU offloading in new driver

Joseph Huber via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 15 12:05:46 PST 2022


Author: Joseph Huber
Date: 2022-02-15T15:05:30-05:00
New Revision: 24ecafb4132704db513d550f2edfe875d353287f

URL: https://github.com/llvm/llvm-project/commit/24ecafb4132704db513d550f2edfe875d353287f
DIFF: https://github.com/llvm/llvm-project/commit/24ecafb4132704db513d550f2edfe875d353287f.diff

LOG: [OpenMP] Add support for CPU offloading in new driver

This patch adds support for linking CPU offloading applications in the
linker wrapper. We generate the necessary linking job using the host
linker's path and library arguments. This may not be true for more
complex offloading schemes, but this is sufficient for now.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D119613

Added: 
    

Modified: 
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/test/Driver/openmp-offload.c
    clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index f87ce3701136..945f62697779 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -8200,14 +8200,19 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
       ArgStringList FeatureArgs;
       TC->addClangTargetOptions(TCArgs, FeatureArgs, Action::OFK_OpenMP);
       auto FeatureIt = llvm::find(FeatureArgs, "-target-feature");
-      CmdArgs.push_back(Args.MakeArgString(
-          "-target-feature=" + TC->getTripleString() + "=" + *(FeatureIt + 1)));
+      if (FeatureIt != FeatureArgs.end())
+        CmdArgs.push_back(
+            Args.MakeArgString("-target-feature=" + TC->getTripleString() +
+                               "=" + *(FeatureIt + 1)));
     }
 
     // Pass in the bitcode library to be linked during LTO.
     for (auto &I :
          llvm::make_range(OpenMPTCRange.first, OpenMPTCRange.second)) {
       const ToolChain *TC = I.second;
+      if (!(TC->getTriple().isNVPTX() || TC->getTriple().isAMDGPU()))
+        continue;
+
       const Driver &TCDriver = TC->getDriver();
       const ArgList &TCArgs = C.getArgsForToolChain(TC, "", Action::OFK_OpenMP);
       StringRef Arch = TCArgs.getLastArgValue(options::OPT_march_EQ);

diff  --git a/clang/test/Driver/openmp-offload.c b/clang/test/Driver/openmp-offload.c
index 699a31276d6f..424b484df99b 100644
--- a/clang/test/Driver/openmp-offload.c
+++ b/clang/test/Driver/openmp-offload.c
@@ -657,3 +657,9 @@
 // RUN:   | FileCheck -check-prefix=CHK-FOPENMP-IS-DEVICE %s
 
 // CHK-FOPENMP-IS-DEVICE: clang{{.*}} "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" {{.*}}.c"
+
+/// Check arguments to the linker wrapper
+// RUN:   %clang -### -no-canonical-prefixes -target powerpc64le-linux -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -fopenmp-new-driver %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHK-NEW-DRIVER %s
+
+// CHK-NEW-DRIVER: clang-linker-wrapper{{.*}}"-host-triple" "powerpc64le-unknown-linux"{{.*}}--{{.*}}"-lomp"{{.*}}"-lomptarget"

diff  --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index 65c9a87edf3f..3e3506e05d74 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -646,6 +646,83 @@ Expected<std::string> link(ArrayRef<std::string> InputFiles, Triple TheTriple,
 }
 } // namespace amdgcn
 
+namespace generic {
+
+const char *getLDMOption(const llvm::Triple &T) {
+  switch (T.getArch()) {
+  case llvm::Triple::x86:
+    if (T.isOSIAMCU())
+      return "elf_iamcu";
+    return "elf_i386";
+  case llvm::Triple::aarch64:
+    return "aarch64linux";
+  case llvm::Triple::aarch64_be:
+    return "aarch64linuxb";
+  case llvm::Triple::ppc64:
+    return "elf64ppc";
+  case llvm::Triple::ppc64le:
+    return "elf64lppc";
+  case llvm::Triple::x86_64:
+    if (T.isX32())
+      return "elf32_x86_64";
+    return "elf_x86_64";
+  case llvm::Triple::ve:
+    return "elf64ve";
+  default:
+    return nullptr;
+  }
+}
+
+Expected<std::string> link(ArrayRef<std::string> InputFiles, Triple TheTriple,
+                           StringRef Arch) {
+  // Create a new file to write the linked device image to.
+  SmallString<128> TempFile;
+  if (Error Err = createOutputFile(sys::path::filename(ExecutableName) + "-" +
+                                       TheTriple.getArchName() + "-" + Arch,
+                                   "out", TempFile))
+    return std::move(Err);
+
+  // Use the host linker to perform generic offloading. Use the same libraries
+  // and paths as the host application does.
+  SmallVector<StringRef, 16> CmdArgs;
+  CmdArgs.push_back(LinkerUserPath);
+  CmdArgs.push_back("-m");
+  CmdArgs.push_back(getLDMOption(TheTriple));
+  CmdArgs.push_back("-shared");
+  for (auto AI = HostLinkerArgs.begin(), AE = HostLinkerArgs.end(); AI != AE;
+       ++AI) {
+    StringRef Arg = *AI;
+    if (Arg.startswith("-L"))
+      CmdArgs.push_back(Arg);
+    else if (Arg.startswith("-l"))
+      CmdArgs.push_back(Arg);
+    else if (Arg.startswith("--as-needed"))
+      CmdArgs.push_back(Arg);
+    else if (Arg.startswith("--no-as-needed"))
+      CmdArgs.push_back(Arg);
+    else if (Arg.startswith("-rpath")) {
+      CmdArgs.push_back(Arg);
+      CmdArgs.push_back(*(AI + 1));
+    } else if (Arg.startswith("-dynamic-linker")) {
+      CmdArgs.push_back(Arg);
+      CmdArgs.push_back(*(AI + 1));
+    }
+  }
+  CmdArgs.push_back("-Bsymbolic");
+  CmdArgs.push_back("-o");
+  CmdArgs.push_back(TempFile);
+
+  // Add extracted input files.
+  for (StringRef Input : InputFiles)
+    CmdArgs.push_back(Input);
+
+  if (sys::ExecuteAndWait(LinkerUserPath, CmdArgs))
+    return createStringError(inconvertibleErrorCode(), "'linker' failed");
+
+  return static_cast<std::string>(TempFile);
+}
+} // namespace generic
+
 Expected<std::string> linkDevice(ArrayRef<std::string> InputFiles,
                                  Triple TheTriple, StringRef Arch) {
   switch (TheTriple.getArch()) {
@@ -656,7 +733,11 @@ Expected<std::string> linkDevice(ArrayRef<std::string> InputFiles,
     return amdgcn::link(InputFiles, TheTriple, Arch);
   case Triple::x86:
   case Triple::x86_64:
-    // TODO: x86 linking support.
+  case Triple::aarch64:
+  case Triple::aarch64_be:
+  case Triple::ppc64:
+  case Triple::ppc64le:
+    return generic::link(InputFiles, TheTriple, Arch);
   default:
     return createStringError(inconvertibleErrorCode(),
                              TheTriple.getArchName() +


        


More information about the cfe-commits mailing list