From 7cab8f14662bfeb0f7fc8507f09421123c5c9474 Mon Sep 17 00:00:00 2001 From: Samuel Antao Date: Thu, 27 Oct 2016 18:04:42 +0000 Subject: [PATCH] [Driver][OpenMP] Add support to create jobs for bundling actions. Summary: This patch adds the support to create a job for the `OffloadBundlingAction` which will invoke the `clang-offload-bundler` tool. Reviewers: echristo, tra, jlebar, ABataev, hfinkel Subscribers: whchung, mehdi_amini, cfe-commits, Hahnfeld, andreybokhanko, arpith-jacob, carlo.bertolli, caomhin Differential Revision: https://reviews.llvm.org/D21856 llvm-svn: 285325 --- clang/include/clang/Driver/Action.h | 2 + clang/include/clang/Driver/ToolChain.h | 2 + clang/lib/Driver/Action.cpp | 17 +++++++ clang/lib/Driver/ToolChain.cpp | 9 +++- clang/lib/Driver/Tools.cpp | 66 ++++++++++++++++++++++++++ clang/lib/Driver/Tools.h | 13 +++++ clang/test/Driver/openmp-offload.c | 34 +++++++++++++ 7 files changed, 141 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Driver/Action.h b/clang/include/clang/Driver/Action.h index 38a651299ced..e2749a429229 100644 --- a/clang/include/clang/Driver/Action.h +++ b/clang/include/clang/Driver/Action.h @@ -160,6 +160,8 @@ public: /// files for each offloading kind. std::string getOffloadingFileNamePrefix(llvm::StringRef NormalizedTriple) const; + /// Return a string containing a offload kind name. + static StringRef GetOffloadKindName(OffloadKind Kind); /// Set the device offload info of this action and propagate it to its /// dependences. diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index 0ce5915a981e..79708ab9a8fd 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -85,10 +85,12 @@ private: mutable std::unique_ptr Clang; mutable std::unique_ptr Assemble; mutable std::unique_ptr Link; + mutable std::unique_ptr OffloadBundler; Tool *getClang() const; Tool *getAssemble() const; Tool *getLink() const; Tool *getClangAs() const; + Tool *getOffloadBundler() const; mutable std::unique_ptr SanitizerArguments; diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp index 79e3da37baf9..ad6fb718101f 100644 --- a/clang/lib/Driver/Action.cpp +++ b/clang/lib/Driver/Action.cpp @@ -9,6 +9,7 @@ #include "clang/Driver/Action.h" #include "clang/Driver/ToolChain.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Regex.h" @@ -128,6 +129,22 @@ Action::getOffloadingFileNamePrefix(llvm::StringRef NormalizedTriple) const { return Res; } +/// Return a string with the offload kind name. If that is not defined, we +/// assume 'host'. +llvm::StringRef Action::GetOffloadKindName(OffloadKind Kind) { + switch (Kind) { + case OFK_None: + case OFK_Host: + return "host"; + case OFK_Cuda: + return "cuda"; + case OFK_OpenMP: + return "openmp"; + + // TODO: Add other programming models here. + } +} + void InputAction::anchor() {} InputAction::InputAction(const Arg &_Input, types::ID _Type) diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 93c6f7810998..f640a85f4cf5 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -239,6 +239,12 @@ Tool *ToolChain::getLink() const { return Link.get(); } +Tool *ToolChain::getOffloadBundler() const { + if (!OffloadBundler) + OffloadBundler.reset(new tools::OffloadBundler(*this)); + return OffloadBundler.get(); +} + Tool *ToolChain::getTool(Action::ActionClass AC) const { switch (AC) { case Action::AssembleJobClass: @@ -266,8 +272,7 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const { case Action::OffloadBundlingJobClass: case Action::OffloadUnbundlingJobClass: - // FIXME: Add a tool for the bundling actions. - return nullptr; + return getOffloadBundler(); } llvm_unreachable("Invalid tool kind."); diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 33f2473b6511..e7a9380d628a 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -7053,6 +7053,72 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, SplitDebugName(Args, Input)); } +void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const { + assert(isa(JA) && "Expecting bundling job!"); + + // The bundling command looks like this: + // clang-offload-bundler -type=bc + // -targets=host-triple,openmp-triple1,openmp-triple2 + // -outputs=input_file + // -inputs=unbundle_file_host,unbundle_file_tgt1,unbundle_file_tgt2" + + ArgStringList CmdArgs; + + // Get the type. + CmdArgs.push_back(TCArgs.MakeArgString( + Twine("-type=") + types::getTypeTempSuffix(Output.getType()))); + + assert(JA.getInputs().size() == Inputs.size() && + "Not have inputs for all dependence actions??"); + + // Get the targets. + SmallString<128> Triples; + Triples += "-targets="; + for (unsigned I = 0; I < Inputs.size(); ++I) { + if (I) + Triples += ','; + + Action::OffloadKind CurKind = Action::OFK_Host; + const ToolChain *CurTC = &getToolChain(); + const Action *CurDep = JA.getInputs()[I]; + + if (const auto *OA = dyn_cast(CurDep)) { + OA->doOnEachDependence([&](Action *A, const ToolChain *TC, const char *) { + CurKind = A->getOffloadingDeviceKind(); + CurTC = TC; + }); + } + Triples += Action::GetOffloadKindName(CurKind); + Triples += '-'; + Triples += CurTC->getTriple().normalize(); + } + CmdArgs.push_back(TCArgs.MakeArgString(Triples)); + + // Get bundled file command. + CmdArgs.push_back( + TCArgs.MakeArgString(Twine("-outputs=") + Output.getFilename())); + + // Get unbundled files command. + SmallString<128> UB; + UB += "-inputs="; + for (unsigned I = 0; I < Inputs.size(); ++I) { + if (I) + UB += ','; + UB += Inputs[I].getFilename(); + } + CmdArgs.push_back(TCArgs.MakeArgString(UB)); + + // All the inputs are encoded as commands. + C.addCommand(llvm::make_unique( + JA, *this, + TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), + CmdArgs, None)); +} + void GnuTool::anchor() {} void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, diff --git a/clang/lib/Driver/Tools.h b/clang/lib/Driver/Tools.h index 724b82932b11..9ee3011ff7d7 100644 --- a/clang/lib/Driver/Tools.h +++ b/clang/lib/Driver/Tools.h @@ -137,6 +137,19 @@ public: const char *LinkingOutput) const override; }; +/// Offload bundler tool. +class LLVM_LIBRARY_VISIBILITY OffloadBundler final : public Tool { +public: + OffloadBundler(const ToolChain &TC) + : Tool("offload bundler", "clang-offload-bundler", TC) {} + + bool hasIntegratedCPP() const override { return false; } + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; + /// \brief Base class for all GNU tools that provide the same behavior when /// it comes to response files support class LLVM_LIBRARY_VISIBILITY GnuTool : public Tool { diff --git a/clang/test/Driver/openmp-offload.c b/clang/test/Driver/openmp-offload.c index f3c5e07be2f2..a2e15e0114ed 100644 --- a/clang/test/Driver/openmp-offload.c +++ b/clang/test/Driver/openmp-offload.c @@ -355,3 +355,37 @@ // CHK-UBUACTIONS: 14: assembler, {13}, object, (host-openmp) // CHK-UBUACTIONS: 15: clang-offload-bundler, {7, 12, 14}, object, (host-openmp) +/// ########################################################################### + +/// Check separate compilation with offloading - bundling jobs construct +// RUN: %clang -### -fopenmp -c -o %t.o -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-BUJOBS %s +// RUN: %clang -### -fopenmp -c -o %t.o -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -save-temps 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-BUJOBS-ST %s + +// Create host BC. +// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "[[HOSTBC:.+\.bc]]" "-x" "c" "[[INPUT:.+\.c]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" + +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "[[HOSTPP:.+\.i]]" "-x" "c" "[[INPUT:.+\.c]]" +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "[[HOSTBC:.+\.bc]]" "-x" "cpp-output" "[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" + +// Create target 1 object. +// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "[[T1OBJ:.+\.o]]" "-x" "c" "[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "[[HOSTBC]]" +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "[[T1PP:.+\.i]]" "-x" "c" "[[INPUT]]" +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "[[T1BC:.+\.bc]]" "-x" "cpp-output" "[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "[[HOSTBC]]" +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "[[T1ASM:.+\.s]]" "-x" "ir" "[[T1BC]]" +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" "[[T1OBJ:.+\.o]]" "[[T1ASM]]" + +// Create target 2 object. +// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "[[T2OBJ:.+\.o]]" "-x" "c" "[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "[[HOSTBC]]" +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "[[T2PP:.+\.i]]" "-x" "c" "[[INPUT]]" +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "[[T2BC:.+\.bc]]" "-x" "cpp-output" "[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "[[HOSTBC]]" +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "[[T2ASM:.+\.s]]" "-x" "ir" "[[T2BC]]" +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" "[[T2OBJ:.+\.o]]" "[[T2ASM]]" + +// Create host object and bundle. +// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "[[HOSTOBJ:.+\.o]]" "-x" "ir" "[[HOSTBC]]" +// CHK-BUJOBS: clang-offload-bundler" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le--linux" "-outputs=[[RES:.+\.o]]" "-inputs=[[T1OBJ]],[[T2OBJ]],[[HOSTOBJ]]" +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "[[HOSTASM:.+\.s]]" "-x" "ir" "[[HOSTBC]]" +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le--linux" "-filetype" "obj" {{.*}}"-o" "[[HOSTOBJ:.+\.o]]" "[[HOSTASM]]" +// CHK-BUJOBS-ST: clang-offload-bundler" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le--linux" "-outputs=[[RES:.+\.o]]" "-inputs=[[T1OBJ]],[[T2OBJ]],[[HOSTOBJ]]"