Skip to content

Commit eff4a03

Browse files
committed
[Clang][SYCL] Introduce clang-sycl-link-wrapper to link SYCL offloading device code
This PR is one of the many PRs in the SYCL upstreaming effort focusing on device code linking during the SYCL offload compilation process. RFC: https://discourse.llvm.org/t/rfc-offloading-design-for-sycl-offload-kind-and-spir-targets/74088 In this PR, we introduce a new tool that will be used to perform device code linking for SYCL offload kind. It accepts SYCL device objects in LLVM IR bitcode format and will generate a fully linked device object that can then be wrapped and linked into the host object. A primary use case for this tool is to perform device code linking for objects with SYCL offload kind inside the clang-linker-wrapper. It can also be invoked via clang driver as follows: `clang --target=spirv64 --sycl-link input.bc` Device code linking for SYCL offloading kind has a number of known quirks that makes it difficult to use in a unified offloading setting. Two of the primary issues are: 1. Several finalization steps are required to be run on the fully-linked LLVM IR bitcode to gaurantee conformance to SYCL standards. This step is unique to SYCL offloading compilation flow. 2. SPIR-V LLVM Translator tool is an extenal tool and hence SPIR-V IR code generation cannot be done as part of LTO. This limitation will be lifted once SPIR-V backend is available as a viable LLVM backend. Hence, we introduce this new tool to provide a clean wrapper to perform SYCL device linking. Thanks Signed-off-by: Arvind Sudarsanam <[email protected]>
1 parent 24d707e commit eff4a03

File tree

14 files changed

+727
-3
lines changed

14 files changed

+727
-3
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
=======================
2+
Clang SYCL Link Wrapper
3+
=======================
4+
5+
.. contents::
6+
:local:
7+
8+
.. _clang-sycl-link-wrapper:
9+
10+
Introduction
11+
============
12+
13+
This tool works as a wrapper around the SYCL device code linking process.
14+
The purpose of this wrapper is to provide an interface to link SYCL device
15+
bitcode in LLVM IR format, SYCL device bitcode in SPIR-V IR format, and native
16+
binary objects, and then use the SPIR-V LLVM Translator tool on fully linked
17+
device objects to produce the final output.
18+
After the linking stage, the fully linked device code in LLVM IR format may
19+
undergo several SYCL-specific finalization steps before the SPIR-V code
20+
generation step.
21+
The wrapper will also support the Ahead-Of-Time (AOT) compilation flow. AOT
22+
compilation is the process of invoking the back-end at compile time to produce
23+
the final binary, as opposed to just-in-time (JIT) compilation when final code
24+
generation is deferred until application runtime.
25+
26+
Device code linking for SYCL offloading has several known quirks that
27+
make it difficult to use in a unified offloading setting. Two of the primary
28+
issues are:
29+
1. Several finalization steps are required to be run on the fully linked LLVM
30+
IR bitcode to guarantee conformance to SYCL standards. This step is unique to
31+
the SYCL offloading compilation flow.
32+
2. The SPIR-V LLVM Translator tool is an external tool and hence SPIR-V IR code
33+
generation cannot be done as part of LTO. This limitation can be lifted once
34+
the SPIR-V backend is available as a viable LLVM backend.
35+
36+
This tool has been proposed to work around these issues.
37+
38+
Usage
39+
=====
40+
41+
This tool can be used with the following options. Several of these options will
42+
be passed down to downstream tools like 'llvm-link', 'llvm-spirv', etc.
43+
44+
.. code-block:: console
45+
46+
OVERVIEW: A utility that wraps around the SYCL device code linking process.
47+
This enables linking and code generation for SPIR-V JIT targets and AOT
48+
targets.
49+
50+
USAGE: clang-sycl-link-wrapper [options]
51+
52+
OPTIONS:
53+
--arch <value> Specify the name of the target architecture.
54+
--dry-run Print generated commands without running.
55+
-g Specify that this was a debug compile.
56+
-help-hidden Display all available options
57+
-help Display available options (--help-hidden for more)
58+
--library-path=<dir> Set the library path for SYCL device libraries
59+
-o <path> Path to file to write output
60+
--save-temps Save intermediate results
61+
--triple <value> Specify the target triple.
62+
--version Display the version number and exit
63+
-v Print verbose information
64+
-spirv-dump-device-code=<dir> Directory to dump SPIR-V IR code into
65+
-is-windows-msvc-env Specify if we are compiling under windows environment
66+
-llvm-spirv-options=<value> Pass options to llvm-spirv tool
67+
68+
Example
69+
=======
70+
71+
This tool is intended to be invoked when targeting any of the target offloading
72+
toolchains. When the --sycl-link option is passed to the clang driver, the
73+
driver will invoke the linking job of the target offloading toolchain, which in
74+
turn will invoke this tool. This tool can be used to create one or more fully
75+
linked device images that are ready to be wrapped and linked with host code to
76+
generate the final executable.
77+
78+
.. code-block:: console
79+
80+
clang-sycl-link-wrapper --triple spirv64 --arch native input.bc

clang/docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ Using Clang Tools
9797
ClangOffloadBundler
9898
ClangOffloadPackager
9999
ClangRepl
100+
ClangSYCLLinkWrapper
100101

101102
Design Documents
102103
================

clang/include/clang/Driver/Options.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6728,7 +6728,10 @@ def fsycl : Flag<["-"], "fsycl">,
67286728
def fno_sycl : Flag<["-"], "fno-sycl">,
67296729
Visibility<[ClangOption, CLOption]>,
67306730
Group<sycl_Group>, HelpText<"Disables SYCL kernels compilation for device">;
6731-
6731+
def sycl_link : Flag<["--"], "sycl-link">, Flags<[HelpHidden]>,
6732+
Visibility<[ClangOption, CLOption]>,
6733+
Group<sycl_Group>, HelpText<"Perform link through clang-sycl-link-wrapper via the target "
6734+
"offloading toolchain.">;
67326735
// OS-specific options
67336736
let Flags = [TargetSpecific] in {
67346737
defm android_pad_segment : BooleanFFlag<"android-pad-segment">, Group<f_Group>;

clang/lib/Driver/Driver.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4780,6 +4780,11 @@ Action *Driver::ConstructPhaseAction(
47804780
if (Phase == phases::Assemble && Input->getType() != types::TY_PP_Asm)
47814781
return Input;
47824782

4783+
// Use of --sycl-link will only allow for the link phase to occur. This is
4784+
// for all input files.
4785+
if (Args.hasArg(options::OPT_sycl_link) && Phase != phases::Link)
4786+
return Input;
4787+
47834788
// Build the appropriate action.
47844789
switch (Phase) {
47854790
case phases::Link:

clang/lib/Driver/ToolChains/SPIRV.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,19 @@ void SPIRV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
9595
CmdArgs.push_back("-o");
9696
CmdArgs.push_back(Output.getFilename());
9797

98+
// Use of --sycl-link will call the clang-sycl-link-wrapper instead of
99+
// the default linker (spirv-link).
100+
if (Args.hasArg(options::OPT_sycl_link))
101+
Linker = ToolChain.GetProgramPath("clang-sycl-link-wrapper");
98102
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
99103
Args.MakeArgString(Linker), CmdArgs,
100104
Inputs, Output));
101105
}
106+
107+
SPIRVToolChain::SPIRVToolChain(const Driver &D, const llvm::Triple &Triple,
108+
const ArgList &Args)
109+
: ToolChain(D, Triple, Args) {
110+
NativeLLVMSupport = Args.hasArg(options::OPT_sycl_link);
111+
}
112+
113+
bool SPIRVToolChain::HasNativeLLVMSupport() const { return NativeLLVMSupport; }

clang/lib/Driver/ToolChains/SPIRV.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ class LLVM_LIBRARY_VISIBILITY SPIRVToolChain final : public ToolChain {
5757

5858
public:
5959
SPIRVToolChain(const Driver &D, const llvm::Triple &Triple,
60-
const llvm::opt::ArgList &Args)
61-
: ToolChain(D, Triple, Args) {}
60+
const llvm::opt::ArgList &Args);
6261

6362
bool useIntegratedAs() const override { return true; }
6463

@@ -72,6 +71,7 @@ class LLVM_LIBRARY_VISIBILITY SPIRVToolChain final : public ToolChain {
7271
}
7372
bool isPICDefaultForced() const override { return false; }
7473
bool SupportsProfiling() const override { return false; }
74+
bool HasNativeLLVMSupport() const override;
7575

7676
clang::driver::Tool *SelectTool(const JobAction &JA) const override;
7777

@@ -81,6 +81,7 @@ class LLVM_LIBRARY_VISIBILITY SPIRVToolChain final : public ToolChain {
8181

8282
private:
8383
clang::driver::Tool *getTranslator() const;
84+
bool NativeLLVMSupport;
8485
};
8586

8687
} // namespace toolchains

clang/test/Driver/Inputs/libsycl-complex.bc

Whitespace-only changes.

clang/test/Driver/Inputs/libsycl-crt.bc

Whitespace-only changes.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Tests the clang-sycl-link-wrapper tool
2+
//
3+
// Test a simple case without arguments
4+
// RUN: %clangxx -fsycl -emit-llvm -c %s -o %t.bc
5+
// RUN: clang-sycl-link-wrapper --dry-run -triple spirv64 %t.bc --library-path=%S/Inputs -o a.spv 2>&1 \
6+
// RUN: | FileCheck %s --check-prefix=CMDS
7+
// CMDS: "{{.*}}llvm-link{{.*}}" {{.*}}.bc -o [[FIRSTLLVMLINKOUT:.*]].bc --suppress-warnings
8+
// CMDS-NEXT: "{{.*}}llvm-link{{.*}}" -only-needed [[FIRSTLLVMLINKOUT]].bc {{.*}}libsycl-crt.bc {{.*}}libsycl-complex.bc -o [[SECONDLLVMLINKOUT:.*]].bc --suppress-warnings
9+
// CMDS-NEXT: "{{.*}}llvm-spirv{{.*}}" {{.*}}-o a.spv [[SECONDLLVMLINKOUT]].bc
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Tests the driver when linking LLVM IR bitcode files and targeting SPIR-V
2+
// architecture.
3+
//
4+
// RUN: touch %t.bc
5+
// RUN: %clangxx --target=spirv64 --sycl-link -### %t.bc 2>&1 \
6+
// RUN: | FileCheck %s -check-prefix=LINK
7+
// LINK: "{{.*}}clang-sycl-link-wrapper{{.*}}" "{{.*}}.bc" "-o" "a.out"

0 commit comments

Comments
 (0)