https://github.com/sarnex updated https://github.com/llvm/llvm-project/pull/120145
>From e1b9b503b1e9b8ebf5a9c94dcefd0c47ab009019 Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Mon, 16 Dec 2024 09:25:44 -0800 Subject: [PATCH 01/11] [Driver][clang-linker-wrapper] Add initial support for OpenMP offloading to generic SPIR-V This is the first of a series of patches to add support for OpenMP offloading to SPIR-V through liboffload with the first intended target being Intel GPUs. This patch implements the basic driver and `clang-linker-wrapper` work for JIT mode. There are still many missing pieces, so this is not yet usable. We introduce `spirv64-intel-unknown` as the only currently supported triple. The user-facing argument to enable offloading will be `-fopenmp -fopenmp-targets=spirv64-intel` Add a new `SPIRVOpenMPToolChain` toolchain based on the existing general SPIR-V toolchain which will call all the required SPIR-V tools as well as add the device RTL as an argument to the linker. As there is no production quality SPIR-V linker available, manually create an ELF binary containing the offloading image in a way that fits into the existing `liboffload` infrastructure. This ELF will eventually be passed to a runtime plugin that interacts with the Intel GPU runtime. There is also a small fix to an issue I found when trying to assemble SPIR-V when in text format. Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- clang/include/clang/Driver/Options.td | 2 + clang/lib/Driver/CMakeLists.txt | 1 + clang/lib/Driver/Driver.cpp | 40 +++++++-- clang/lib/Driver/ToolChains/CommonArgs.cpp | 9 +- clang/lib/Driver/ToolChains/SPIRV.cpp | 5 +- clang/lib/Driver/ToolChains/SPIRV.h | 2 +- clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp | 36 ++++++++ clang/lib/Driver/ToolChains/SPIRVOpenMP.h | 29 +++++++ clang/lib/Frontend/CompilerInvocation.cpp | 1 + .../lib/libomptarget-spirv64-spirv64-intel.bc | 0 clang/test/Driver/spirv-openmp-toolchain.c | 71 +++++++++++++++ clang/test/Driver/spirv-toolchain.cl | 6 +- .../ClangLinkerWrapper.cpp | 17 ++-- .../llvm/Frontend/Offloading/Utility.h | 5 ++ llvm/include/llvm/TargetParser/Triple.h | 3 +- llvm/lib/Frontend/Offloading/CMakeLists.txt | 1 + llvm/lib/Frontend/Offloading/Utility.cpp | 86 +++++++++++++++++++ llvm/lib/TargetParser/Triple.cpp | 2 + 18 files changed, 296 insertions(+), 20 deletions(-) create mode 100644 clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp create mode 100644 clang/lib/Driver/ToolChains/SPIRVOpenMP.h create mode 100644 clang/test/Driver/Inputs/spirv-openmp/lib/libomptarget-spirv64-spirv64-intel.bc create mode 100644 clang/test/Driver/spirv-openmp-toolchain.c diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index bed2a56b003512..a46fa1353af587 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1493,6 +1493,8 @@ def libomptarget_amdgcn_bc_path_EQ : Joined<["--"], "libomptarget-amdgcn-bc-path HelpText<"Path to libomptarget-amdgcn bitcode library">, Alias<libomptarget_amdgpu_bc_path_EQ>; def libomptarget_nvptx_bc_path_EQ : Joined<["--"], "libomptarget-nvptx-bc-path=">, Group<i_Group>, HelpText<"Path to libomptarget-nvptx bitcode library">; +def libomptarget_spirv_bc_path_EQ : Joined<["--"], "libomptarget-spirv-bc-path=">, Group<i_Group>, + HelpText<"Path to libomptarget-spirv bitcode library">; def dD : Flag<["-"], "dD">, Group<d_Group>, Visibility<[ClangOption, CC1Option]>, HelpText<"Print macro definitions in -E mode in addition to normal output">; def dI : Flag<["-"], "dI">, Group<d_Group>, Visibility<[ClangOption, CC1Option]>, diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index 4fd10bf671512f..57d04c3fefa843 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -77,6 +77,7 @@ add_clang_library(clangDriver ToolChains/RISCVToolchain.cpp ToolChains/Solaris.cpp ToolChains/SPIRV.cpp + ToolChains/SPIRVOpenMP.cpp ToolChains/TCE.cpp ToolChains/UEFI.cpp ToolChains/VEToolchain.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index dc84c1b9d1cc4e..c74a474f487d95 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -43,6 +43,7 @@ #include "ToolChains/PS4CPU.h" #include "ToolChains/RISCVToolchain.h" #include "ToolChains/SPIRV.h" +#include "ToolChains/SPIRVOpenMP.h" #include "ToolChains/Solaris.h" #include "ToolChains/TCE.h" #include "ToolChains/UEFI.h" @@ -166,6 +167,20 @@ getHIPOffloadTargetTriple(const Driver &D, const ArgList &Args) { return std::nullopt; } +static std::optional<llvm::Triple> +getSPIRVOffloadTargetTriple(const Driver &D, const ArgList &Args) { + if (!Args.hasArg(options::OPT_offload_EQ)) + return llvm::Triple( + "spirv64-intel"); // Only vendor "intel" is currently supported. + auto TT = getOffloadTargetTriple(D, Args); + if (!TT) + return std::nullopt; + if ((*TT).isSPIRV() && (*TT).getVendor() == llvm::Triple::Intel) + return TT; + D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << TT->str(); + return std::nullopt; +} + // static std::string Driver::GetResourcesPath(StringRef BinaryPath) { // Since the resource directory is embedded in the module hash, it's important @@ -888,11 +903,12 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, auto AMDTriple = getHIPOffloadTargetTriple(*this, C.getInputArgs()); auto NVPTXTriple = getNVIDIAOffloadTargetTriple(*this, C.getInputArgs(), HostTC->getTriple()); + auto SPIRVTriple = getSPIRVOffloadTargetTriple(*this, C.getInputArgs()); // Attempt to deduce the offloading triple from the set of architectures. - // We can only correctly deduce NVPTX / AMDGPU triples currently. We need - // to temporarily create these toolchains so that we can access tools for - // inferring architectures. + // We can only correctly deduce NVPTX / AMDGPU / SPIR-V triples currently. + // We need to temporarily create these toolchains so that we can access + // tools for inferring architectures. llvm::DenseSet<StringRef> Archs; if (NVPTXTriple) { auto TempTC = std::make_unique<toolchains::CudaToolChain>( @@ -908,7 +924,16 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, C, C.getArgs(), Action::OFK_OpenMP, &*TempTC, true)) Archs.insert(Arch); } - if (!AMDTriple && !NVPTXTriple) { + + if (SPIRVTriple) { + auto TempTC = std::make_unique<toolchains::SPIRVOpenMPToolChain>( + *this, *SPIRVTriple, *HostTC, C.getInputArgs()); + for (StringRef Arch : getOffloadArchs( + C, C.getArgs(), Action::OFK_OpenMP, &*TempTC, true)) + Archs.insert(Arch); + } + + if (!AMDTriple && !NVPTXTriple && !SPIRVTriple) { for (StringRef Arch : getOffloadArchs(C, C.getArgs(), Action::OFK_OpenMP, nullptr, true)) Archs.insert(Arch); @@ -922,6 +947,8 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, IsAMDOffloadArch(StringToOffloadArch( getProcessorFromTargetID(*AMDTriple, Arch)))) { DerivedArchs[AMDTriple->getTriple()].insert(Arch); + } else if (SPIRVTriple && Arch == (*SPIRVTriple).str()) { + DerivedArchs[Arch].insert(Arch); } else { Diag(clang::diag::err_drv_failed_to_deduce_target_from_arch) << Arch; return; @@ -962,7 +989,7 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, const ToolChain *TC; // Device toolchains have to be selected differently. They pair host // and device in their implementation. - if (TT.isNVPTX() || TT.isAMDGCN()) { + if (TT.isNVPTX() || TT.isAMDGCN() || TT.isSPIRV()) { const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>(); assert(HostTC && "Host toolchain should be always defined."); @@ -975,6 +1002,9 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, else if (TT.isAMDGCN()) DeviceTC = std::make_unique<toolchains::AMDGPUOpenMPToolChain>( *this, TT, *HostTC, C.getInputArgs()); + else if (TT.isSPIRV()) + DeviceTC = std::make_unique<toolchains::SPIRVOpenMPToolChain>( + *this, TT, *HostTC, C.getInputArgs()); else assert(DeviceTC && "Device toolchain not defined."); } diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index ca675c117418cb..b8ab188a4efb35 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -2829,10 +2829,13 @@ void tools::addOpenMPDeviceRTL(const Driver &D, LibraryPaths.emplace_back(LibPath); OptSpecifier LibomptargetBCPathOpt = - Triple.isAMDGCN() ? options::OPT_libomptarget_amdgpu_bc_path_EQ - : options::OPT_libomptarget_nvptx_bc_path_EQ; + Triple.isAMDGCN() ? options::OPT_libomptarget_amdgpu_bc_path_EQ + : Triple.isNVPTX() ? options::OPT_libomptarget_nvptx_bc_path_EQ + : options::OPT_libomptarget_spirv_bc_path_EQ; - StringRef ArchPrefix = Triple.isAMDGCN() ? "amdgpu" : "nvptx"; + StringRef ArchPrefix = Triple.isAMDGCN() ? "amdgpu" + : Triple.isNVPTX() ? "nvptx" + : "spirv64"; std::string LibOmpTargetName = ("libomptarget-" + ArchPrefix + "-" + BitcodeSuffix + ".bc").str(); diff --git a/clang/lib/Driver/ToolChains/SPIRV.cpp b/clang/lib/Driver/ToolChains/SPIRV.cpp index 659da5c7f25aa9..37b544009869a1 100644 --- a/clang/lib/Driver/ToolChains/SPIRV.cpp +++ b/clang/lib/Driver/ToolChains/SPIRV.cpp @@ -28,8 +28,11 @@ void SPIRV::constructTranslateCommand(Compilation &C, const Tool &T, if (Input.getType() == types::TY_PP_Asm) CmdArgs.push_back("-to-binary"); + + // The text output from spirv-dis is not in the format expected + // by llvm-spirv, so use the text output from llvm-spirv. if (Output.getType() == types::TY_PP_Asm) - CmdArgs.push_back("--spirv-tools-dis"); + CmdArgs.push_back("--spirv-text"); CmdArgs.append({"-o", Output.getFilename()}); diff --git a/clang/lib/Driver/ToolChains/SPIRV.h b/clang/lib/Driver/ToolChains/SPIRV.h index d59a8c76ed4737..415f639bba3ecd 100644 --- a/clang/lib/Driver/ToolChains/SPIRV.h +++ b/clang/lib/Driver/ToolChains/SPIRV.h @@ -52,7 +52,7 @@ class LLVM_LIBRARY_VISIBILITY Linker final : public Tool { namespace toolchains { -class LLVM_LIBRARY_VISIBILITY SPIRVToolChain final : public ToolChain { +class LLVM_LIBRARY_VISIBILITY SPIRVToolChain : public ToolChain { mutable std::unique_ptr<Tool> Translator; public: diff --git a/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp b/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp new file mode 100644 index 00000000000000..5b9e20afa94d9d --- /dev/null +++ b/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp @@ -0,0 +1,36 @@ +//==- SPIRVOpenMP.cpp - SPIR-V OpenMP Tool Implementations --------*- C++ -*==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//==------------------------------------------------------------------------==// +#include "SPIRVOpenMP.h" +#include "CommonArgs.h" + +using namespace clang::driver; +using namespace clang::driver::toolchains; +using namespace clang::driver::tools; +using namespace llvm::opt; + +namespace clang::driver::toolchains { +SPIRVOpenMPToolChain::SPIRVOpenMPToolChain(const Driver &D, + const llvm::Triple &Triple, + const ToolChain &HostToolchain, + const ArgList &Args) + : SPIRVToolChain(D, Triple, Args), HostTC(HostToolchain) {} + +void SPIRVOpenMPToolChain::addClangTargetOptions( + const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind DeviceOffloadingKind) const { + + if (DeviceOffloadingKind != Action::OFK_OpenMP) + return; + + if (DriverArgs.hasArg(options::OPT_nogpulib)) + return; + Twine GpuArch = getTriple().getArchName() + "-" + getTriple().getVendorName(); + addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, GpuArch.str(), + getTriple(), HostTC); +} +} // namespace clang::driver::toolchains diff --git a/clang/lib/Driver/ToolChains/SPIRVOpenMP.h b/clang/lib/Driver/ToolChains/SPIRVOpenMP.h new file mode 100644 index 00000000000000..64404e2a28210a --- /dev/null +++ b/clang/lib/Driver/ToolChains/SPIRVOpenMP.h @@ -0,0 +1,29 @@ +//===--- SPIRVOpenMP.h - SPIR-V OpenMP Tool Implementations ------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_SPIRV_OPENMP_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_SPIRV_OPENMP_H + +#include "SPIRV.h" +#include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" + +namespace clang::driver::toolchains { +class LLVM_LIBRARY_VISIBILITY SPIRVOpenMPToolChain : public SPIRVToolChain { +public: + SPIRVOpenMPToolChain(const Driver &D, const llvm::Triple &Triple, + const ToolChain &HostTC, const llvm::opt::ArgList &Args); + + void addClangTargetOptions( + const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind DeviceOffloadingKind) const override; + + const ToolChain &HostTC; +}; +} // namespace clang::driver::toolchains +#endif diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 23906d5c06d380..c82c70228d6f43 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -4256,6 +4256,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, if (TT.getArch() == llvm::Triple::UnknownArch || !(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() || + TT.getArch() == llvm::Triple::spirv64 || TT.getArch() == llvm::Triple::systemz || TT.getArch() == llvm::Triple::nvptx || TT.getArch() == llvm::Triple::nvptx64 || diff --git a/clang/test/Driver/Inputs/spirv-openmp/lib/libomptarget-spirv64-spirv64-intel.bc b/clang/test/Driver/Inputs/spirv-openmp/lib/libomptarget-spirv64-spirv64-intel.bc new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/clang/test/Driver/spirv-openmp-toolchain.c b/clang/test/Driver/spirv-openmp-toolchain.c new file mode 100644 index 00000000000000..9a48ba69a3e36a --- /dev/null +++ b/clang/test/Driver/spirv-openmp-toolchain.c @@ -0,0 +1,71 @@ +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fopenmp -fopenmp-targets=spirv64-intel \ +// RUN: --libomptarget-spirv-bc-path=%t/ -nogpulib %s 2>&1 \ +// RUN: | FileCheck %s +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fopenmp --offload-arch=spirv64-intel \ +// RUN: --libomptarget-spirv-bc-path=%t/ -nogpulib %s 2>&1 \ +// RUN: | FileCheck %s + +// verify the tools invocations +// CHECK: "-cc1" "-triple" "x86_64-unknown-linux-gnu"{{.*}}"-emit-llvm-bc"{{.*}}"-x" "c" +// CHECK: "-cc1" "-triple" "spirv64-intel" "-aux-triple" "x86_64-unknown-linux-gnu" +// CHECK: llvm-spirv{{.*}} +// CHECK: "-cc1" "-triple" "x86_64-unknown-linux-gnu"{{.*}}"-emit-obj" +// CHECK: clang-linker-wrapper{{.*}} "-o" "a.out" + +// RUN: %clang -ccc-print-phases --target=x86_64-unknown-linux-gnu -fopenmp -fopenmp-targets=spirv64-intel %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-PHASES %s + +// CHECK-PHASES: 0: input, "[[INPUT:.+]]", c, (host-openmp) +// CHECK-PHASES: 1: preprocessor, {0}, cpp-output, (host-openmp) +// CHECK-PHASES: 2: compiler, {1}, ir, (host-openmp) +// CHECK-PHASES: 3: input, "[[INPUT]]", c, (device-openmp) +// CHECK-PHASES: 4: preprocessor, {3}, cpp-output, (device-openmp) +// CHECK-PHASES: 5: compiler, {4}, ir, (device-openmp) +// CHECK-PHASES: 6: offload, "host-openmp (x86_64-unknown-linux-gnu)" {2}, "device-openmp (spirv64-intel)" {5}, ir +// CHECK-PHASES: 7: backend, {6}, assembler, (device-openmp) +// CHECK-PHASES: 8: assembler, {7}, object, (device-openmp) +// CHECK-PHASES: 9: offload, "device-openmp (spirv64-intel)" {8}, object +// CHECK-PHASES: 10: clang-offload-packager, {9}, image, (device-openmp) +// CHECK-PHASES: 11: offload, "host-openmp (x86_64-unknown-linux-gnu)" {2}, "device-openmp (x86_64-unknown-linux-gnu)" {10}, ir +// CHECK-PHASES: 12: backend, {11}, assembler, (host-openmp) +// CHECK-PHASES: 13: assembler, {12}, object, (host-openmp) +// CHECK-PHASES: 14: clang-linker-wrapper, {13}, image, (host-openmp) + +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -ccc-print-bindings -fopenmp -fopenmp-targets=spirv64-intel -nogpulib %s 2>&1 | FileCheck %s --check-prefix=CHECK-BINDINGS +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -ccc-print-bindings -fopenmp -fopenmp-targets=spirv64-intel -nogpulib %s 2>&1 | FileCheck %s --check-prefix=CHECK-BINDINGS + +// CHECK-BINDINGS: "x86_64-unknown-linux-gnu" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[HOST_BC:.+]]" +// CHECK-BINDINGS: "spirv64-intel" - "clang", inputs: ["[[INPUT]]", "[[HOST_BC]]"], output: "[[DEVICE_TEMP_BC:.+]]" +// CHECK-BINDINGS: "spirv64-intel" - "SPIR-V::Translator", inputs: ["[[DEVICE_TEMP_BC]]"], output: "[[DEVICE_SPV:.+]]" +// CHECK-BINDINGS: "x86_64-unknown-linux-gnu" - "Offload::Packager", inputs: ["[[DEVICE_SPV]]"], output: "[[DEVICE_IMAGE:.+]]" +// CHECK-BINDINGS: "x86_64-unknown-linux-gnu" - "clang", inputs: ["[[HOST_BC]]", "[[DEVICE_IMAGE]]"], output: "[[HOST_OBJ:.+]]" +// CHECK-BINDINGS: "x86_64-unknown-linux-gnu" - "Offload::Linker", inputs: ["[[HOST_OBJ]]"], output: "a.out" + +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -ccc-print-bindings -save-temps -fopenmp -fopenmp-targets=spirv64-intel -nogpulib %s 2>&1 | FileCheck %s --check-prefix=CHECK-BINDINGS-TEMPS +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -ccc-print-bindings -save-temps -fopenmp -fopenmp-targets=spirv64-intel %s 2>&1 | FileCheck %s --check-prefix=CHECK-BINDINGS-TEMPS +// CHECK-BINDINGS-TEMPS: "x86_64-unknown-linux-gnu" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[HOST_PP:.+]]" +// CHECK-BINDINGS-TEMPS: "x86_64-unknown-linux-gnu" - "clang", inputs: ["[[HOST_PP]]"], output: "[[HOST_BC:.+]]" +// CHECK-BINDINGS-TEMPS: "spirv64-intel" - "clang", inputs: ["[[INPUT]]"], output: "[[DEVICE_PP:.+]]" +// CHECK-BINDINGS-TEMPS: "spirv64-intel" - "clang", inputs: ["[[DEVICE_PP]]", "[[HOST_BC]]"], output: "[[DEVICE_TEMP_BC:.+]]" +// CHECK-BINDINGS-TEMPS: "spirv64-intel" - "SPIR-V::Translator", inputs: ["[[DEVICE_TEMP_BC]]"], output: "[[DEVICE_ASM:.+]]" +// CHECK-BINDINGS-TEMPS: "spirv64-intel" - "SPIR-V::Translator", inputs: ["[[DEVICE_ASM]]"], output: "[[DEVICE_SPV:.+]]" +// CHECK-BINDINGS-TEMPS: "x86_64-unknown-linux-gnu" - "Offload::Packager", inputs: ["[[DEVICE_SPV]]"], output: "[[DEVICE_IMAGE:.+]]" +// CHECK-BINDINGS-TEMPS: "x86_64-unknown-linux-gnu" - "clang", inputs: ["[[HOST_BC]]", "[[DEVICE_IMAGE]]"], output: "[[HOST_ASM:.+]]" +// CHECK-BINDINGS-TEMPS: "x86_64-unknown-linux-gnu" - "clang::as", inputs: ["[[HOST_ASM]]"], output: "[[HOST_OBJ:.+]]" +// CHECK-BINDINGS-TEMPS: "x86_64-unknown-linux-gnu" - "Offload::Linker", inputs: ["[[HOST_OBJ]]"], output: "a.out" + +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -emit-llvm -S -fopenmp -fopenmp-targets=spirv64-intel -nogpulib %s 2>&1 | FileCheck %s --check-prefix=CHECK-EMIT-LLVM-IR +// CHECK-EMIT-LLVM-IR: "-cc1" "-triple" "spirv64-intel"{{.*}}"-emit-llvm-bc" + +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fopenmp -fopenmp-targets=spirv64-intel \ +// RUN: --sysroot=%S/Inputs/spirv-openmp/ %s 2>&1 | FileCheck --check-prefix=CHECK-GPULIB %s +// CHECK-GPULIB: "-cc1" "-triple" "spirv64-intel"{{.*}}"-mlink-builtin-bitcode" "{{.*}}libomptarget-spirv64-spirv64-intel.bc" + +// RUN: not %clang -### -target x86_64-pc-linux-gnu -fopenmp --offload-arch=spirv64-intel,spirv64-unknown-unknown -nogpulib %s 2>&1 | FileCheck %s --check-prefix=CHECK-TARGET-ID-ERROR +// CHECK-TARGET-ID-ERROR: error: failed to deduce triple for target architecture 'spirv64-unknown-unknown' + +// RUN: not %clang -### -target x86_64-pc-linux-gnu -fopenmp --offload-arch=spirv64-intel,spirv64 -nogpulib %s 2>&1 | FileCheck %s --check-prefix=CHECK-TARGET-ID-ERROR-2 +// CHECK-TARGET-ID-ERROR-2: error: failed to deduce triple for target architecture 'spirv64' + +// RUN: not %clang -target x86_64-pc-linux-gnu -fopenmp --offload-arch=spirv64-intel -nogpulib --offload=spir64 %s 2>&1 | FileCheck %s --check-prefix=CHECK-TARGET-ID-ERROR-3 +// CHECK-TARGET-ID-ERROR-3: error: invalid or unsupported offload target: 'spir64' diff --git a/clang/test/Driver/spirv-toolchain.cl b/clang/test/Driver/spirv-toolchain.cl index eff02f809ce83c..59c4c9c14724bf 100644 --- a/clang/test/Driver/spirv-toolchain.cl +++ b/clang/test/Driver/spirv-toolchain.cl @@ -28,7 +28,7 @@ // SPT64: "-cc1" "-triple" "spirv64" // SPT64-SAME: "-o" [[BC:".*bc"]] -// SPT64: {{llvm-spirv.*"}} [[BC]] "--spirv-tools-dis" "-o" {{".*s"}} +// SPT64: {{llvm-spirv.*"}} [[BC]] "--spirv-text" "-o" {{".*s"}} // RUN: %clang -### --target=spirv32 -x cl -S %s 2>&1 | FileCheck --check-prefix=SPT32 %s // RUN: %clang -### --target=spirv32 -x ir -S %s 2>&1 | FileCheck --check-prefix=SPT32 %s @@ -37,7 +37,7 @@ // SPT32: "-cc1" "-triple" "spirv32" // SPT32-SAME: "-o" [[BC:".*bc"]] -// SPT32: {{llvm-spirv.*"}} [[BC]] "--spirv-tools-dis" "-o" {{".*s"}} +// SPT32: {{llvm-spirv.*"}} [[BC]] "--spirv-text" "-o" {{".*s"}} //----------------------------------------------------------------------------- // Check assembly input -> object output @@ -55,7 +55,7 @@ // TMP: "-cc1" "-triple" "spirv64" // TMP-SAME: "-o" [[BC:".*bc"]] // TMP-SAME: [[I]] -// TMP: {{llvm-spirv.*"}} [[BC]] "--spirv-tools-dis" "-o" [[S:".*s"]] +// TMP: {{llvm-spirv.*"}} [[BC]] "--spirv-text" "-o" [[S:".*s"]] // TMP: {{llvm-spirv.*"}} [[S]] "-to-binary" "-o" {{".*o"}} //----------------------------------------------------------------------------- diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index fae32a3503c185..57b4cede353d82 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -504,14 +504,14 @@ Expected<StringRef> clang(ArrayRef<StringRef> InputFiles, const ArgList &Args) { {"-Xlinker", Args.MakeArgString("--plugin-opt=" + StringRef(Arg->getValue()))}); - if (!Triple.isNVPTX()) + if (!Triple.isNVPTX() && !Triple.isSPIRV()) CmdArgs.push_back("-Wl,--no-undefined"); for (StringRef InputFile : InputFiles) CmdArgs.push_back(InputFile); // If this is CPU offloading we copy the input libraries. - if (!Triple.isAMDGPU() && !Triple.isNVPTX()) { + if (!Triple.isAMDGPU() && !Triple.isNVPTX() && !Triple.isSPIRV()) { CmdArgs.push_back("-Wl,-Bsymbolic"); CmdArgs.push_back("-shared"); ArgStringList LinkerArgs; @@ -595,6 +595,7 @@ Expected<StringRef> linkDevice(ArrayRef<StringRef> InputFiles, case Triple::aarch64_be: case Triple::ppc64: case Triple::ppc64le: + case Triple::spirv64: case Triple::systemz: return generic::clang(InputFiles, Args); default: @@ -735,11 +736,15 @@ wrapDeviceImages(ArrayRef<std::unique_ptr<MemoryBuffer>> Buffers, } Expected<SmallVector<std::unique_ptr<MemoryBuffer>>> -bundleOpenMP(ArrayRef<OffloadingImage> Images) { +bundleOpenMP(SmallVectorImpl<OffloadingImage> &Images) { SmallVector<std::unique_ptr<MemoryBuffer>> Buffers; - for (const OffloadingImage &Image : Images) + for (OffloadingImage &Image : Images) { + llvm::Triple Triple(Image.StringData.lookup("triple")); + if (Triple.isSPIRV() && Triple.getVendor() == llvm::Triple::Intel) + offloading::intel::containerizeOpenMPSPIRVImage(Image); Buffers.emplace_back( MemoryBuffer::getMemBufferCopy(OffloadBinary::write(Image))); + } return std::move(Buffers); } @@ -793,8 +798,8 @@ bundleHIP(ArrayRef<OffloadingImage> Images, const ArgList &Args) { /// Transforms the input \p Images into the binary format the runtime expects /// for the given \p Kind. Expected<SmallVector<std::unique_ptr<MemoryBuffer>>> -bundleLinkedOutput(ArrayRef<OffloadingImage> Images, const ArgList &Args, - OffloadKind Kind) { +bundleLinkedOutput(SmallVectorImpl<OffloadingImage> &Images, + const ArgList &Args, OffloadKind Kind) { llvm::TimeTraceScope TimeScope("Bundle linked output"); switch (Kind) { case OFK_OpenMP: diff --git a/llvm/include/llvm/Frontend/Offloading/Utility.h b/llvm/include/llvm/Frontend/Offloading/Utility.h index abaea843848b21..b6872f4abffbec 100644 --- a/llvm/include/llvm/Frontend/Offloading/Utility.h +++ b/llvm/include/llvm/Frontend/Offloading/Utility.h @@ -133,6 +133,11 @@ Error getAMDGPUMetaDataFromImage(MemoryBufferRef MemBuffer, StringMap<AMDGPUKernelMetaData> &KernelInfoMap, uint16_t &ELFABIVersion); } // namespace amdgpu +namespace intel { +/// Containerizes an offloading image into the ELF binary format expected by +/// the Intel runtime offload plugin. +void containerizeOpenMPSPIRVImage(object::OffloadBinary::OffloadingImage &Img); +} // namespace intel } // namespace offloading } // namespace llvm diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index 3a1a962003abf5..bd4051d00edbab 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -193,7 +193,8 @@ class Triple { Mesa, SUSE, OpenEmbedded, - LastVendorType = OpenEmbedded + Intel, + LastVendorType = Intel }; enum OSType { UnknownOS, diff --git a/llvm/lib/Frontend/Offloading/CMakeLists.txt b/llvm/lib/Frontend/Offloading/CMakeLists.txt index ce445ad9cc4cb6..8e1ede9c72b391 100644 --- a/llvm/lib/Frontend/Offloading/CMakeLists.txt +++ b/llvm/lib/Frontend/Offloading/CMakeLists.txt @@ -12,6 +12,7 @@ add_llvm_component_library(LLVMFrontendOffloading Core BinaryFormat Object + ObjectYAML Support TransformUtils TargetParser diff --git a/llvm/lib/Frontend/Offloading/Utility.cpp b/llvm/lib/Frontend/Offloading/Utility.cpp index 9e85ffbfe22d70..4814734be48c3e 100644 --- a/llvm/lib/Frontend/Offloading/Utility.cpp +++ b/llvm/lib/Frontend/Offloading/Utility.cpp @@ -15,6 +15,8 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Value.h" #include "llvm/Object/ELFObjectFile.h" +#include "llvm/ObjectYAML/ELFYAML.h" +#include "llvm/ObjectYAML/yaml2obj.h" #include "llvm/Support/MemoryBufferRef.h" #include "llvm/Transforms/Utils/ModuleUtils.h" @@ -365,3 +367,87 @@ Error llvm::offloading::amdgpu::getAMDGPUMetaDataFromImage( } return Error::success(); } + +void offloading::intel::containerizeOpenMPSPIRVImage( + object::OffloadBinary::OffloadingImage &Img) { + constexpr char INTEL_ONEOMP_OFFLOAD_VERSION[] = "1.0"; + constexpr int NT_INTEL_ONEOMP_OFFLOAD_VERSION = 1; + constexpr int NT_INTEL_ONEOMP_OFFLOAD_IMAGE_COUNT = 2; + constexpr int NT_INTEL_ONEOMP_OFFLOAD_IMAGE_AUX = 3; + llvm::Triple Triple(Img.StringData.lookup("triple")); + assert((Triple.isSPIRV() && Triple.getVendor() == llvm::Triple::Intel) && + "Unexpected triple"); + + // Start creating notes for the ELF container. + std::vector<ELFYAML::NoteEntry> Notes; + std::string Version = toHex(INTEL_ONEOMP_OFFLOAD_VERSION); + Notes.emplace_back(ELFYAML::NoteEntry{"INTELONEOMPOFFLOAD", + yaml::BinaryRef(Version), + NT_INTEL_ONEOMP_OFFLOAD_VERSION}); + + // The AuxInfo string will hold auxiliary information for the image. + // ELFYAML::NoteEntry structures will hold references to the + // string, so we have to make sure the string is valid. + std::string AuxInfo; + + // TODO: Pass compile/link opts + StringRef CompileOpts = ""; + StringRef LinkOpts = ""; + + unsigned ImageFmt = 1; // SPIR-V format + + AuxInfo = toHex((Twine(0) + Twine('\0') + Twine(ImageFmt) + Twine('\0') + + CompileOpts + Twine('\0') + LinkOpts) + .str()); + Notes.emplace_back(ELFYAML::NoteEntry{"INTELONEOMPOFFLOAD", + yaml::BinaryRef(AuxInfo), + NT_INTEL_ONEOMP_OFFLOAD_IMAGE_AUX}); + + std::string ImgCount = toHex(Twine(1).str()); // always one image per ELF + Notes.emplace_back(ELFYAML::NoteEntry{"INTELONEOMPOFFLOAD", + yaml::BinaryRef(ImgCount), + NT_INTEL_ONEOMP_OFFLOAD_IMAGE_COUNT}); + + std::string YamlFile; + llvm::raw_string_ostream YamlFileStream(YamlFile); + + // Write YAML template file. + { + // We use 64-bit little-endian ELF currently. + ELFYAML::FileHeader Header{}; + Header.Class = ELF::ELFCLASS64; + Header.Data = ELF::ELFDATA2LSB; + Header.Type = ELF::ET_DYN; + // Use an existing Intel machine type as there is not one specifically for + // Intel GPUs. + Header.Machine = ELF::EM_IA_64; + + // Create a section with notes. + ELFYAML::NoteSection Section{}; + Section.Type = ELF::SHT_NOTE; + Section.AddressAlign = 0; + Section.Name = ".note.inteloneompoffload"; + Section.Notes.emplace(std::move(Notes)); + + ELFYAML::Object Object{}; + Object.Header = Header; + Object.Chunks.push_back( + std::make_unique<ELFYAML::NoteSection>(std::move(Section))); + + // Create the section that will hold the image + ELFYAML::RawContentSection ImageSection{}; + ImageSection.Type = ELF::SHT_PROGBITS; + ImageSection.AddressAlign = 0; + std::string Name = "__openmp_offload_spirv_0"; + ImageSection.Name = Name; + ImageSection.Content = + llvm::yaml::BinaryRef(arrayRefFromStringRef(Img.Image->getBuffer())); + Object.Chunks.push_back( + std::make_unique<ELFYAML::RawContentSection>(std::move(ImageSection))); + + llvm::yaml::yaml2elf( + Object, YamlFileStream, + [](const Twine &Msg) { llvm::report_fatal_error(Msg); }, UINT64_MAX); + } + Img.Image = MemoryBuffer::getMemBufferCopy(YamlFile); +} diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index faabaf18d80710..3b0620bf5ba044 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -241,6 +241,7 @@ StringRef Triple::getVendorTypeName(VendorType Kind) { case Freescale: return "fsl"; case IBM: return "ibm"; case ImaginationTechnologies: return "img"; + case Intel: return "intel"; case Mesa: return "mesa"; case MipsTechnologies: return "mti"; case NVIDIA: return "nvidia"; @@ -634,6 +635,7 @@ static Triple::VendorType parseVendor(StringRef VendorName) { .Case("fsl", Triple::Freescale) .Case("ibm", Triple::IBM) .Case("img", Triple::ImaginationTechnologies) + .Case("intel", Triple::Intel) .Case("mti", Triple::MipsTechnologies) .Case("nvidia", Triple::NVIDIA) .Case("csr", Triple::CSR) >From 5a93fdf1d556c2ad4680d0f2e174af52b8e0a388 Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Mon, 16 Dec 2024 13:06:39 -0800 Subject: [PATCH 02/11] clang format Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- llvm/lib/TargetParser/Triple.cpp | 35 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index 3b0620bf5ba044..26263d74634199 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -241,7 +241,8 @@ StringRef Triple::getVendorTypeName(VendorType Kind) { case Freescale: return "fsl"; case IBM: return "ibm"; case ImaginationTechnologies: return "img"; - case Intel: return "intel"; + case Intel: + return "intel"; case Mesa: return "mesa"; case MipsTechnologies: return "mti"; case NVIDIA: return "nvidia"; @@ -628,22 +629,22 @@ static Triple::ArchType parseArch(StringRef ArchName) { static Triple::VendorType parseVendor(StringRef VendorName) { return StringSwitch<Triple::VendorType>(VendorName) - .Case("apple", Triple::Apple) - .Case("pc", Triple::PC) - .Case("scei", Triple::SCEI) - .Case("sie", Triple::SCEI) - .Case("fsl", Triple::Freescale) - .Case("ibm", Triple::IBM) - .Case("img", Triple::ImaginationTechnologies) - .Case("intel", Triple::Intel) - .Case("mti", Triple::MipsTechnologies) - .Case("nvidia", Triple::NVIDIA) - .Case("csr", Triple::CSR) - .Case("amd", Triple::AMD) - .Case("mesa", Triple::Mesa) - .Case("suse", Triple::SUSE) - .Case("oe", Triple::OpenEmbedded) - .Default(Triple::UnknownVendor); + .Case("apple", Triple::Apple) + .Case("pc", Triple::PC) + .Case("scei", Triple::SCEI) + .Case("sie", Triple::SCEI) + .Case("fsl", Triple::Freescale) + .Case("ibm", Triple::IBM) + .Case("img", Triple::ImaginationTechnologies) + .Case("intel", Triple::Intel) + .Case("mti", Triple::MipsTechnologies) + .Case("nvidia", Triple::NVIDIA) + .Case("csr", Triple::CSR) + .Case("amd", Triple::AMD) + .Case("mesa", Triple::Mesa) + .Case("suse", Triple::SUSE) + .Case("oe", Triple::OpenEmbedded) + .Default(Triple::UnknownVendor); } static Triple::OSType parseOS(StringRef OSName) { >From 9a0a9f3f0c5039920dbc28fbe478e757073c3fb3 Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Mon, 16 Dec 2024 16:40:03 -0800 Subject: [PATCH 03/11] fix lit test Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp b/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp index 5b9e20afa94d9d..845ac1a209dc7a 100644 --- a/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp +++ b/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp @@ -29,8 +29,10 @@ void SPIRVOpenMPToolChain::addClangTargetOptions( if (DriverArgs.hasArg(options::OPT_nogpulib)) return; - Twine GpuArch = getTriple().getArchName() + "-" + getTriple().getVendorName(); - addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, GpuArch.str(), - getTriple(), HostTC); + std::string GpuArch = + Twine(getTriple().getArchName() + "-" + getTriple().getVendorName()) + .str(); + addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, GpuArch, getTriple(), + HostTC); } } // namespace clang::driver::toolchains >From 0557f8932f2c2276b99abc45935f7cec20c68799 Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Tue, 17 Dec 2024 07:52:27 -0800 Subject: [PATCH 04/11] remove spir-v fix Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- clang/lib/Driver/ToolChains/SPIRV.cpp | 4 +--- clang/test/Driver/spirv-toolchain.cl | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/clang/lib/Driver/ToolChains/SPIRV.cpp b/clang/lib/Driver/ToolChains/SPIRV.cpp index 37b544009869a1..fa2288ebd8e912 100644 --- a/clang/lib/Driver/ToolChains/SPIRV.cpp +++ b/clang/lib/Driver/ToolChains/SPIRV.cpp @@ -29,10 +29,8 @@ void SPIRV::constructTranslateCommand(Compilation &C, const Tool &T, if (Input.getType() == types::TY_PP_Asm) CmdArgs.push_back("-to-binary"); - // The text output from spirv-dis is not in the format expected - // by llvm-spirv, so use the text output from llvm-spirv. if (Output.getType() == types::TY_PP_Asm) - CmdArgs.push_back("--spirv-text"); + CmdArgs.push_back("--spirv-tools-dis"); CmdArgs.append({"-o", Output.getFilename()}); diff --git a/clang/test/Driver/spirv-toolchain.cl b/clang/test/Driver/spirv-toolchain.cl index 59c4c9c14724bf..eff02f809ce83c 100644 --- a/clang/test/Driver/spirv-toolchain.cl +++ b/clang/test/Driver/spirv-toolchain.cl @@ -28,7 +28,7 @@ // SPT64: "-cc1" "-triple" "spirv64" // SPT64-SAME: "-o" [[BC:".*bc"]] -// SPT64: {{llvm-spirv.*"}} [[BC]] "--spirv-text" "-o" {{".*s"}} +// SPT64: {{llvm-spirv.*"}} [[BC]] "--spirv-tools-dis" "-o" {{".*s"}} // RUN: %clang -### --target=spirv32 -x cl -S %s 2>&1 | FileCheck --check-prefix=SPT32 %s // RUN: %clang -### --target=spirv32 -x ir -S %s 2>&1 | FileCheck --check-prefix=SPT32 %s @@ -37,7 +37,7 @@ // SPT32: "-cc1" "-triple" "spirv32" // SPT32-SAME: "-o" [[BC:".*bc"]] -// SPT32: {{llvm-spirv.*"}} [[BC]] "--spirv-text" "-o" {{".*s"}} +// SPT32: {{llvm-spirv.*"}} [[BC]] "--spirv-tools-dis" "-o" {{".*s"}} //----------------------------------------------------------------------------- // Check assembly input -> object output @@ -55,7 +55,7 @@ // TMP: "-cc1" "-triple" "spirv64" // TMP-SAME: "-o" [[BC:".*bc"]] // TMP-SAME: [[I]] -// TMP: {{llvm-spirv.*"}} [[BC]] "--spirv-text" "-o" [[S:".*s"]] +// TMP: {{llvm-spirv.*"}} [[BC]] "--spirv-tools-dis" "-o" [[S:".*s"]] // TMP: {{llvm-spirv.*"}} [[S]] "-to-binary" "-o" {{".*o"}} //----------------------------------------------------------------------------- >From 64228dcbc9ef6360af33a36fdc57e7e03d8a8da4 Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Tue, 17 Dec 2024 07:56:05 -0800 Subject: [PATCH 05/11] remove containerization Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- .../ClangLinkerWrapper.cpp | 12 +-- .../llvm/Frontend/Offloading/Utility.h | 5 -- llvm/lib/Frontend/Offloading/Utility.cpp | 86 ------------------- 3 files changed, 4 insertions(+), 99 deletions(-) diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 57b4cede353d82..72b886669b4576 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -736,15 +736,11 @@ wrapDeviceImages(ArrayRef<std::unique_ptr<MemoryBuffer>> Buffers, } Expected<SmallVector<std::unique_ptr<MemoryBuffer>>> -bundleOpenMP(SmallVectorImpl<OffloadingImage> &Images) { +bundleOpenMP(ArrayRef<OffloadingImage> Images) { SmallVector<std::unique_ptr<MemoryBuffer>> Buffers; - for (OffloadingImage &Image : Images) { - llvm::Triple Triple(Image.StringData.lookup("triple")); - if (Triple.isSPIRV() && Triple.getVendor() == llvm::Triple::Intel) - offloading::intel::containerizeOpenMPSPIRVImage(Image); + for (const OffloadingImage &Image : Images) Buffers.emplace_back( MemoryBuffer::getMemBufferCopy(OffloadBinary::write(Image))); - } return std::move(Buffers); } @@ -798,8 +794,8 @@ bundleHIP(ArrayRef<OffloadingImage> Images, const ArgList &Args) { /// Transforms the input \p Images into the binary format the runtime expects /// for the given \p Kind. Expected<SmallVector<std::unique_ptr<MemoryBuffer>>> -bundleLinkedOutput(SmallVectorImpl<OffloadingImage> &Images, - const ArgList &Args, OffloadKind Kind) { +bundleLinkedOutput(ArrayRef<OffloadingImage> Images, const ArgList &Args, + OffloadKind Kind) { llvm::TimeTraceScope TimeScope("Bundle linked output"); switch (Kind) { case OFK_OpenMP: diff --git a/llvm/include/llvm/Frontend/Offloading/Utility.h b/llvm/include/llvm/Frontend/Offloading/Utility.h index b6872f4abffbec..abaea843848b21 100644 --- a/llvm/include/llvm/Frontend/Offloading/Utility.h +++ b/llvm/include/llvm/Frontend/Offloading/Utility.h @@ -133,11 +133,6 @@ Error getAMDGPUMetaDataFromImage(MemoryBufferRef MemBuffer, StringMap<AMDGPUKernelMetaData> &KernelInfoMap, uint16_t &ELFABIVersion); } // namespace amdgpu -namespace intel { -/// Containerizes an offloading image into the ELF binary format expected by -/// the Intel runtime offload plugin. -void containerizeOpenMPSPIRVImage(object::OffloadBinary::OffloadingImage &Img); -} // namespace intel } // namespace offloading } // namespace llvm diff --git a/llvm/lib/Frontend/Offloading/Utility.cpp b/llvm/lib/Frontend/Offloading/Utility.cpp index 4814734be48c3e..9e85ffbfe22d70 100644 --- a/llvm/lib/Frontend/Offloading/Utility.cpp +++ b/llvm/lib/Frontend/Offloading/Utility.cpp @@ -15,8 +15,6 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Value.h" #include "llvm/Object/ELFObjectFile.h" -#include "llvm/ObjectYAML/ELFYAML.h" -#include "llvm/ObjectYAML/yaml2obj.h" #include "llvm/Support/MemoryBufferRef.h" #include "llvm/Transforms/Utils/ModuleUtils.h" @@ -367,87 +365,3 @@ Error llvm::offloading::amdgpu::getAMDGPUMetaDataFromImage( } return Error::success(); } - -void offloading::intel::containerizeOpenMPSPIRVImage( - object::OffloadBinary::OffloadingImage &Img) { - constexpr char INTEL_ONEOMP_OFFLOAD_VERSION[] = "1.0"; - constexpr int NT_INTEL_ONEOMP_OFFLOAD_VERSION = 1; - constexpr int NT_INTEL_ONEOMP_OFFLOAD_IMAGE_COUNT = 2; - constexpr int NT_INTEL_ONEOMP_OFFLOAD_IMAGE_AUX = 3; - llvm::Triple Triple(Img.StringData.lookup("triple")); - assert((Triple.isSPIRV() && Triple.getVendor() == llvm::Triple::Intel) && - "Unexpected triple"); - - // Start creating notes for the ELF container. - std::vector<ELFYAML::NoteEntry> Notes; - std::string Version = toHex(INTEL_ONEOMP_OFFLOAD_VERSION); - Notes.emplace_back(ELFYAML::NoteEntry{"INTELONEOMPOFFLOAD", - yaml::BinaryRef(Version), - NT_INTEL_ONEOMP_OFFLOAD_VERSION}); - - // The AuxInfo string will hold auxiliary information for the image. - // ELFYAML::NoteEntry structures will hold references to the - // string, so we have to make sure the string is valid. - std::string AuxInfo; - - // TODO: Pass compile/link opts - StringRef CompileOpts = ""; - StringRef LinkOpts = ""; - - unsigned ImageFmt = 1; // SPIR-V format - - AuxInfo = toHex((Twine(0) + Twine('\0') + Twine(ImageFmt) + Twine('\0') + - CompileOpts + Twine('\0') + LinkOpts) - .str()); - Notes.emplace_back(ELFYAML::NoteEntry{"INTELONEOMPOFFLOAD", - yaml::BinaryRef(AuxInfo), - NT_INTEL_ONEOMP_OFFLOAD_IMAGE_AUX}); - - std::string ImgCount = toHex(Twine(1).str()); // always one image per ELF - Notes.emplace_back(ELFYAML::NoteEntry{"INTELONEOMPOFFLOAD", - yaml::BinaryRef(ImgCount), - NT_INTEL_ONEOMP_OFFLOAD_IMAGE_COUNT}); - - std::string YamlFile; - llvm::raw_string_ostream YamlFileStream(YamlFile); - - // Write YAML template file. - { - // We use 64-bit little-endian ELF currently. - ELFYAML::FileHeader Header{}; - Header.Class = ELF::ELFCLASS64; - Header.Data = ELF::ELFDATA2LSB; - Header.Type = ELF::ET_DYN; - // Use an existing Intel machine type as there is not one specifically for - // Intel GPUs. - Header.Machine = ELF::EM_IA_64; - - // Create a section with notes. - ELFYAML::NoteSection Section{}; - Section.Type = ELF::SHT_NOTE; - Section.AddressAlign = 0; - Section.Name = ".note.inteloneompoffload"; - Section.Notes.emplace(std::move(Notes)); - - ELFYAML::Object Object{}; - Object.Header = Header; - Object.Chunks.push_back( - std::make_unique<ELFYAML::NoteSection>(std::move(Section))); - - // Create the section that will hold the image - ELFYAML::RawContentSection ImageSection{}; - ImageSection.Type = ELF::SHT_PROGBITS; - ImageSection.AddressAlign = 0; - std::string Name = "__openmp_offload_spirv_0"; - ImageSection.Name = Name; - ImageSection.Content = - llvm::yaml::BinaryRef(arrayRefFromStringRef(Img.Image->getBuffer())); - Object.Chunks.push_back( - std::make_unique<ELFYAML::RawContentSection>(std::move(ImageSection))); - - llvm::yaml::yaml2elf( - Object, YamlFileStream, - [](const Twine &Msg) { llvm::report_fatal_error(Msg); }, UINT64_MAX); - } - Img.Image = MemoryBuffer::getMemBufferCopy(YamlFile); -} >From 1c53aaa69fbe404eb7f21c745b2f4aef1d36a8a7 Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Tue, 17 Dec 2024 10:57:19 -0800 Subject: [PATCH 06/11] remove --offload-arch changes Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- clang/lib/Driver/Driver.cpp | 15 ++------------- clang/test/Driver/spirv-openmp-toolchain.c | 8 +++++--- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index c74a474f487d95..6843658efacc59 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -903,10 +903,9 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, auto AMDTriple = getHIPOffloadTargetTriple(*this, C.getInputArgs()); auto NVPTXTriple = getNVIDIAOffloadTargetTriple(*this, C.getInputArgs(), HostTC->getTriple()); - auto SPIRVTriple = getSPIRVOffloadTargetTriple(*this, C.getInputArgs()); // Attempt to deduce the offloading triple from the set of architectures. - // We can only correctly deduce NVPTX / AMDGPU / SPIR-V triples currently. + // We can only correctly deduce NVPTX / AMDGPU triples currently. // We need to temporarily create these toolchains so that we can access // tools for inferring architectures. llvm::DenseSet<StringRef> Archs; @@ -925,15 +924,7 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, Archs.insert(Arch); } - if (SPIRVTriple) { - auto TempTC = std::make_unique<toolchains::SPIRVOpenMPToolChain>( - *this, *SPIRVTriple, *HostTC, C.getInputArgs()); - for (StringRef Arch : getOffloadArchs( - C, C.getArgs(), Action::OFK_OpenMP, &*TempTC, true)) - Archs.insert(Arch); - } - - if (!AMDTriple && !NVPTXTriple && !SPIRVTriple) { + if (!AMDTriple && !NVPTXTriple) { for (StringRef Arch : getOffloadArchs(C, C.getArgs(), Action::OFK_OpenMP, nullptr, true)) Archs.insert(Arch); @@ -947,8 +938,6 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, IsAMDOffloadArch(StringToOffloadArch( getProcessorFromTargetID(*AMDTriple, Arch)))) { DerivedArchs[AMDTriple->getTriple()].insert(Arch); - } else if (SPIRVTriple && Arch == (*SPIRVTriple).str()) { - DerivedArchs[Arch].insert(Arch); } else { Diag(clang::diag::err_drv_failed_to_deduce_target_from_arch) << Arch; return; diff --git a/clang/test/Driver/spirv-openmp-toolchain.c b/clang/test/Driver/spirv-openmp-toolchain.c index 9a48ba69a3e36a..a59f25f6919bf9 100644 --- a/clang/test/Driver/spirv-openmp-toolchain.c +++ b/clang/test/Driver/spirv-openmp-toolchain.c @@ -1,9 +1,6 @@ // RUN: %clang -### --target=x86_64-unknown-linux-gnu -fopenmp -fopenmp-targets=spirv64-intel \ // RUN: --libomptarget-spirv-bc-path=%t/ -nogpulib %s 2>&1 \ // RUN: | FileCheck %s -// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fopenmp --offload-arch=spirv64-intel \ -// RUN: --libomptarget-spirv-bc-path=%t/ -nogpulib %s 2>&1 \ -// RUN: | FileCheck %s // verify the tools invocations // CHECK: "-cc1" "-triple" "x86_64-unknown-linux-gnu"{{.*}}"-emit-llvm-bc"{{.*}}"-x" "c" @@ -69,3 +66,8 @@ // RUN: not %clang -target x86_64-pc-linux-gnu -fopenmp --offload-arch=spirv64-intel -nogpulib --offload=spir64 %s 2>&1 | FileCheck %s --check-prefix=CHECK-TARGET-ID-ERROR-3 // CHECK-TARGET-ID-ERROR-3: error: invalid or unsupported offload target: 'spir64' + +// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -fopenmp --offload-arch=spirv64-intel \ +// RUN: --libomptarget-spirv-bc-path=%t/ -nogpulib %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-OFFLOAD-ARCH-ERROR +// CHECK-OFFLOAD-ARCH-ERROR: error: failed to deduce triple for target architecture 'spirv64-intel'; specify the triple using '-fopenmp-targets' and '-Xopenmp-target' instead >From ee7ba6839c7619f0b1fb74cb09633c816e380de2 Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Tue, 17 Dec 2024 11:17:40 -0800 Subject: [PATCH 07/11] missed stuff Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- clang/lib/Driver/Driver.cpp | 1 - clang/lib/Driver/ToolChains/SPIRV.cpp | 1 - llvm/lib/Frontend/Offloading/CMakeLists.txt | 1 - 3 files changed, 3 deletions(-) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 6843658efacc59..326531080ef6fc 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -923,7 +923,6 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, C, C.getArgs(), Action::OFK_OpenMP, &*TempTC, true)) Archs.insert(Arch); } - if (!AMDTriple && !NVPTXTriple) { for (StringRef Arch : getOffloadArchs(C, C.getArgs(), Action::OFK_OpenMP, nullptr, true)) diff --git a/clang/lib/Driver/ToolChains/SPIRV.cpp b/clang/lib/Driver/ToolChains/SPIRV.cpp index fa2288ebd8e912..659da5c7f25aa9 100644 --- a/clang/lib/Driver/ToolChains/SPIRV.cpp +++ b/clang/lib/Driver/ToolChains/SPIRV.cpp @@ -28,7 +28,6 @@ void SPIRV::constructTranslateCommand(Compilation &C, const Tool &T, if (Input.getType() == types::TY_PP_Asm) CmdArgs.push_back("-to-binary"); - if (Output.getType() == types::TY_PP_Asm) CmdArgs.push_back("--spirv-tools-dis"); diff --git a/llvm/lib/Frontend/Offloading/CMakeLists.txt b/llvm/lib/Frontend/Offloading/CMakeLists.txt index 8e1ede9c72b391..ce445ad9cc4cb6 100644 --- a/llvm/lib/Frontend/Offloading/CMakeLists.txt +++ b/llvm/lib/Frontend/Offloading/CMakeLists.txt @@ -12,7 +12,6 @@ add_llvm_component_library(LLVMFrontendOffloading Core BinaryFormat Object - ObjectYAML Support TransformUtils TargetParser >From 261547cd3b1d2088d5a2ed4a07487fbd8aabf59e Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Tue, 17 Dec 2024 11:20:07 -0800 Subject: [PATCH 08/11] dead code Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- clang/lib/Driver/Driver.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 326531080ef6fc..bc5ce9f14ab698 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -167,20 +167,6 @@ getHIPOffloadTargetTriple(const Driver &D, const ArgList &Args) { return std::nullopt; } -static std::optional<llvm::Triple> -getSPIRVOffloadTargetTriple(const Driver &D, const ArgList &Args) { - if (!Args.hasArg(options::OPT_offload_EQ)) - return llvm::Triple( - "spirv64-intel"); // Only vendor "intel" is currently supported. - auto TT = getOffloadTargetTriple(D, Args); - if (!TT) - return std::nullopt; - if ((*TT).isSPIRV() && (*TT).getVendor() == llvm::Triple::Intel) - return TT; - D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << TT->str(); - return std::nullopt; -} - // static std::string Driver::GetResourcesPath(StringRef BinaryPath) { // Since the resource directory is embedded in the module hash, it's important >From 9c97a922ce8545537a42cd7b3081c8225cce0390 Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Tue, 17 Dec 2024 13:40:42 -0800 Subject: [PATCH 09/11] remove invalid tests Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- clang/test/Driver/spirv-openmp-toolchain.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/clang/test/Driver/spirv-openmp-toolchain.c b/clang/test/Driver/spirv-openmp-toolchain.c index a59f25f6919bf9..4c9df1bb3974de 100644 --- a/clang/test/Driver/spirv-openmp-toolchain.c +++ b/clang/test/Driver/spirv-openmp-toolchain.c @@ -58,15 +58,6 @@ // RUN: --sysroot=%S/Inputs/spirv-openmp/ %s 2>&1 | FileCheck --check-prefix=CHECK-GPULIB %s // CHECK-GPULIB: "-cc1" "-triple" "spirv64-intel"{{.*}}"-mlink-builtin-bitcode" "{{.*}}libomptarget-spirv64-spirv64-intel.bc" -// RUN: not %clang -### -target x86_64-pc-linux-gnu -fopenmp --offload-arch=spirv64-intel,spirv64-unknown-unknown -nogpulib %s 2>&1 | FileCheck %s --check-prefix=CHECK-TARGET-ID-ERROR -// CHECK-TARGET-ID-ERROR: error: failed to deduce triple for target architecture 'spirv64-unknown-unknown' - -// RUN: not %clang -### -target x86_64-pc-linux-gnu -fopenmp --offload-arch=spirv64-intel,spirv64 -nogpulib %s 2>&1 | FileCheck %s --check-prefix=CHECK-TARGET-ID-ERROR-2 -// CHECK-TARGET-ID-ERROR-2: error: failed to deduce triple for target architecture 'spirv64' - -// RUN: not %clang -target x86_64-pc-linux-gnu -fopenmp --offload-arch=spirv64-intel -nogpulib --offload=spir64 %s 2>&1 | FileCheck %s --check-prefix=CHECK-TARGET-ID-ERROR-3 -// CHECK-TARGET-ID-ERROR-3: error: invalid or unsupported offload target: 'spir64' - // RUN: not %clang -### --target=x86_64-unknown-linux-gnu -fopenmp --offload-arch=spirv64-intel \ // RUN: --libomptarget-spirv-bc-path=%t/ -nogpulib %s 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-OFFLOAD-ARCH-ERROR >From eb408e9368bdefee7dfd6aaafe6d3baac14e39b1 Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Mon, 30 Dec 2024 13:48:25 -0800 Subject: [PATCH 10/11] fix test after libomptarget change Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- ...ptarget-spirv64-spirv64-intel.bc => libomptarget-spirv64.bc} | 0 clang/test/Driver/spirv-openmp-toolchain.c | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename clang/test/Driver/Inputs/spirv-openmp/lib/{libomptarget-spirv64-spirv64-intel.bc => libomptarget-spirv64.bc} (100%) diff --git a/clang/test/Driver/Inputs/spirv-openmp/lib/libomptarget-spirv64-spirv64-intel.bc b/clang/test/Driver/Inputs/spirv-openmp/lib/libomptarget-spirv64.bc similarity index 100% rename from clang/test/Driver/Inputs/spirv-openmp/lib/libomptarget-spirv64-spirv64-intel.bc rename to clang/test/Driver/Inputs/spirv-openmp/lib/libomptarget-spirv64.bc diff --git a/clang/test/Driver/spirv-openmp-toolchain.c b/clang/test/Driver/spirv-openmp-toolchain.c index 4c9df1bb3974de..3eb1f22a03ed0a 100644 --- a/clang/test/Driver/spirv-openmp-toolchain.c +++ b/clang/test/Driver/spirv-openmp-toolchain.c @@ -56,7 +56,7 @@ // RUN: %clang -### --target=x86_64-unknown-linux-gnu -fopenmp -fopenmp-targets=spirv64-intel \ // RUN: --sysroot=%S/Inputs/spirv-openmp/ %s 2>&1 | FileCheck --check-prefix=CHECK-GPULIB %s -// CHECK-GPULIB: "-cc1" "-triple" "spirv64-intel"{{.*}}"-mlink-builtin-bitcode" "{{.*}}libomptarget-spirv64-spirv64-intel.bc" +// CHECK-GPULIB: "-cc1" "-triple" "spirv64-intel"{{.*}}"-mlink-builtin-bitcode" "{{.*}}libomptarget-spirv64.bc" // RUN: not %clang -### --target=x86_64-unknown-linux-gnu -fopenmp --offload-arch=spirv64-intel \ // RUN: --libomptarget-spirv-bc-path=%t/ -nogpulib %s 2>&1 \ >From 476414806964bbc87d98199afe430946282fd4ee Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Mon, 30 Dec 2024 13:57:55 -0800 Subject: [PATCH 11/11] format Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp b/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp index 990d9bcc107dbe..1f27245e2839cd 100644 --- a/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp +++ b/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp @@ -29,7 +29,6 @@ void SPIRVOpenMPToolChain::addClangTargetOptions( if (DriverArgs.hasArg(options::OPT_nogpulib)) return; - addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, "", getTriple(), - HostTC); + addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, "", getTriple(), HostTC); } } // namespace clang::driver::toolchains _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits