-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Driver][clang-linker-wrapper] Add initial support for OpenMP offloading to generic SPIR-V #120145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e1b9b50
5a93fdf
9a0a9f3
0557f89
64228dc
a5b980b
1c53aaa
0eb76b4
ee7ba68
261547c
9c97a92
1d927ee
eb408e9
4764148
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
//==- 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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we truly need a separate OpenMP version of the toolchain? I don't know the details of SPIR-V or Intel's stack. It's relevant if we want OpenMP pulling in different libraries or something, like with AMDGPU's OpenMP skipping some of the HIP libraries. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right now the only thing we are doing here is pulling in the OpenMP device RTL, but in the future I expect the final version of Intel's OpenMP support to have somewhat complicated logic here pulling in various things, and other vendors could also have some custom stuff, so I think it makes sense to have a new toolchain for now to not bog down the generic SPIR-V toolchain. |
||
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; | ||
addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, "", getTriple(), HostTC); | ||
} | ||
} // namespace clang::driver::toolchains |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4263,6 +4263,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 || | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Honestly the more I see added to this big if statement the more I'm convinced it doesn't need to exist. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right now it's at least throwing an error if the triple doesn't match the list, so there might be some case where removing the error will break something, so I'd prefer to not potentially introduce a bug in a possibly untested area. |
||
TT.getArch() == llvm::Triple::systemz || | ||
TT.getArch() == llvm::Triple::loongarch64 || | ||
TT.getArch() == llvm::Triple::nvptx || | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// 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 | ||
|
||
// 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.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 \ | ||
// 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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some recent changes here for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will do, thanks |
||
case Triple::systemz: | ||
case Triple::loongarch64: | ||
return generic::clang(InputFiles, Args); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does SPIR-V still rely on the
mlink-builtin-bitcode
hack instead of LTO? The SPIR-V backend should be usable soon from what I hear, so that's the ideal going forward.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we're linking the DeviceRTL using
mlink-builtin-bitcode
today, but we definitely want to use LTO in the future, both for OpenMP and SYCL.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a patch for the DeviceRTL build? I've been meaning to gut a lot of that starting with #119091 and soon removing the whole bundling thing so it's more like
libc.a
. ideally we'd havelib/spirv64-intel-unknown/libomp.a
and the driver just passes-Xoffload-linker -lomp
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not yet, we hit some issues in the front end generating OpenMP device code with the SPIR-V target, so we can't build it yet because it doesn't make it through the compiler. Any change should be with fine with us, we should be able to adapt to whatever infrastructure there is to build the DeviceRTL. thanks.