Skip to content

Commit 936881a

Browse files
authored
[Driver][SYCL] Add support for -fsyclbin (#17252)
Adds support for the -fsyclbin option. This option allows for creation of a SYCL device specific binary. The binary is created via a device compilation before being packaged and sent to the clang-linker-wrapper. The clang-linker-wrapper is responsible to take the device 'object' and create the corresponding .syclbin file.
1 parent 883911a commit 936881a

File tree

5 files changed

+110
-13
lines changed

5 files changed

+110
-13
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7273,6 +7273,8 @@ defm sycl_allow_device_image_dependencies: BoolOptionWithoutMarshalling<"f", "sy
72737273
def fsycl_dump_device_code_EQ : Joined<["-"], "fsycl-dump-device-code=">,
72747274
Flags<[NoXarchOption]>,
72757275
HelpText<"Dump device code into the user provided directory.">;
7276+
def fsyclbin : Flag<["-"], "fsyclbin">,
7277+
HelpText<"Create a SYCLBIN file">;
72767278
} // let Group = sycl_Group
72777279

72787280
// FIXME: -fsycl-explicit-simd is deprecated. remove it when support is dropped.

clang/lib/Driver/Driver.cpp

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,9 +1221,11 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
12211221
// We need to generate a SYCL toolchain if the user specified -fsycl.
12221222
// If -fsycl is supplied without any of these we will assume SPIR-V.
12231223
// Use of -fsycl-device-only overrides -fsycl.
1224+
// Use of -fsyclbin enables SYCL device compilation.
12241225
bool IsSYCL = C.getInputArgs().hasFlag(options::OPT_fsycl,
12251226
options::OPT_fno_sycl, false) ||
1226-
C.getInputArgs().hasArg(options::OPT_fsycl_device_only);
1227+
C.getInputArgs().hasArgNoClaim(options::OPT_fsycl_device_only,
1228+
options::OPT_fsyclbin);
12271229

12281230
auto argSYCLIncompatible = [&](OptSpecifier OptId) {
12291231
if (!IsSYCL)
@@ -3464,7 +3466,7 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
34643466
Arg *InputTypeArg = nullptr;
34653467
bool IsSYCL =
34663468
Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false) ||
3467-
Args.hasArg(options::OPT_fsycl_device_only);
3469+
Args.hasArgNoClaim(options::OPT_fsycl_device_only, options::OPT_fsyclbin);
34683470

34693471
// The last /TC or /TP option sets the input type to C or C++ globally.
34703472
if (Arg *TCTP = Args.getLastArgNoClaim(options::OPT__SLASH_TC,
@@ -7929,6 +7931,19 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
79297931
C.MakeAction<LinkJobAction>(OffloadActions, types::TY_HIP_FATBIN);
79307932
DDep.add(*FatbinAction, *C.getSingleOffloadToolChain<Action::OFK_HIP>(),
79317933
nullptr, Action::OFK_HIP);
7934+
} else if (C.isOffloadingHostKind(Action::OFK_SYCL) &&
7935+
Args.hasArg(options::OPT_fsyclbin)) {
7936+
// With '-fsyclbin', package all the offloading actions into a single output
7937+
// that is sent to the clang-linker-wrapper.
7938+
Action *PackagerAction =
7939+
C.MakeAction<OffloadPackagerJobAction>(OffloadActions, types::TY_Image);
7940+
ActionList PackagerActions;
7941+
PackagerActions.push_back(PackagerAction);
7942+
Action *LinkAction =
7943+
C.MakeAction<LinkerWrapperJobAction>(PackagerActions, types::TY_Image);
7944+
DDep.add(*LinkAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
7945+
nullptr, C.getActiveOffloadKinds());
7946+
return C.MakeAction<OffloadAction>(DDep, types::TY_Nothing);
79327947
} else {
79337948
// Package all the offloading actions into a single output that can be
79347949
// embedded in the host and linked.
@@ -9336,8 +9351,10 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
93369351
if (AtTopLevel && !isa<DsymutilJobAction>(JA) && !isa<VerifyJobAction>(JA)) {
93379352
if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
93389353
return C.addResultFile(FinalOutput->getValue(), &JA);
9339-
// Output to destination for -fsycl-device-only and Windows -o
9340-
if (offloadDeviceOnly() && JA.getOffloadingDeviceKind() == Action::OFK_SYCL)
9354+
// Output to destination for -fsycl-device-only/-fsyclbin and Windows -o
9355+
if ((offloadDeviceOnly() ||
9356+
C.getArgs().hasArgNoClaim(options::OPT_fsyclbin)) &&
9357+
JA.getOffloadingDeviceKind() == Action::OFK_SYCL)
93419358
if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT__SLASH_o))
93429359
return C.addResultFile(FinalOutput->getValue(), &JA);
93439360
}
@@ -9506,6 +9523,20 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
95069523
else
95079524
BaseName = llvm::sys::path::filename(BasePath);
95089525

9526+
// When compiling with -fsyclbin, maintain a simple output file name for the
9527+
// resulting image. A '.syclbin' extension is used to represent the resulting
9528+
// output file.
9529+
if (JA.getOffloadingDeviceKind() == Action::OFK_SYCL &&
9530+
C.getArgs().hasArgNoClaim(options::OPT_fsyclbin) &&
9531+
JA.getType() == types::TY_Image) {
9532+
SmallString<128> SYCLBinOutput(getDefaultImageName());
9533+
if (IsCLMode())
9534+
// Use BaseName for the syclbin output name.
9535+
SYCLBinOutput = BaseName;
9536+
llvm::sys::path::replace_extension(SYCLBinOutput, ".syclbin");
9537+
return C.addResultFile(C.getArgs().MakeArgString(SYCLBinOutput), &JA);
9538+
}
9539+
95099540
// Determine what the derived output name should be.
95109541
const char *NamedOutput;
95119542

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11465,6 +11465,9 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
1146511465
CmdArgs.push_back(
1146611466
Args.MakeArgString("--sycl-target-link-options=" + LinkOptString));
1146711467
}
11468+
// Add option to enable creating of the .syclbin file.
11469+
if (Args.hasArg(options::OPT_fsyclbin))
11470+
CmdArgs.push_back(Args.MakeArgString("--syclbin"));
1146811471
}
1146911472

1147011473
// Construct the link job so we can wrap around it.

clang/test/Driver/fsyclbin.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/// Tests behaviors of -fsyclbin
2+
3+
/// -fsyclbin is only used with the new offloading model.
4+
// RUN: %clangxx -fsycl -fsyclbin --no-offload-new-driver %s -### 2>&1 \
5+
// RUN: | FileCheck %s --check-prefix=UNUSED
6+
// UNUSED: warning: argument unused during compilation: '-fsyclbin'
7+
8+
/// -fsyclbin -fsycl-device-only usage. -fsycl-device-only will 'win' and
9+
/// -fsyclbin is effectively ignored.
10+
// RUN: %clangxx -fsycl-device-only -fsyclbin --offload-new-driver %s -### 2>&1 \
11+
// RUN: | FileCheck %s --check-prefix=SYCLBIN_UNUSED
12+
// RUN: %clang_cl -fsycl-device-only -fsyclbin --offload-new-driver %s -### 2>&1 \
13+
// RUN: | FileCheck %s --check-prefix=SYCLBIN_UNUSED
14+
// SYCLBIN_UNUSED: warning: argument unused during compilation: '-fsyclbin'
15+
16+
/// Check tool invocation contents.
17+
// RUN: %clangxx -fsycl -fsyclbin --offload-new-driver %s -### 2>&1 \
18+
// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS
19+
// RUN: %clangxx -fsyclbin --offload-new-driver %s -### 2>&1 \
20+
// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS
21+
// RUN: %clang_cl -fsycl -fsyclbin --offload-new-driver %s -### 2>&1 \
22+
// RUN: | FileCheck %s --check-prefix=CHECK_TOOLS
23+
// CHECK_TOOLS: clang-offload-packager
24+
// CHECK_TOOLS-SAME: --image=file={{.*}}.bc,triple=spir64-unknown-unknown
25+
// CHECK_TOOLS-SAME: kind=sycl
26+
// CHECK_TOOLS: clang-linker-wrapper
27+
// CHECK_TOOLS-SAME: --syclbin
28+
29+
/// Check compilation phases, only device compile should be performed
30+
// RUN: %clangxx --target=x86_64-unknown-linux-gnu -fsycl -fsyclbin \
31+
// RUN: --offload-new-driver %s -ccc-print-phases 2>&1 \
32+
// RUN: | FileCheck %s --check-prefix=CHECK_PHASES
33+
// RUN: %clangxx --target=x86_64-unknown-linux-gnu -fsyclbin \
34+
// RUN: --offload-new-driver %s -ccc-print-phases 2>&1 \
35+
// RUN: | FileCheck %s --check-prefix=CHECK_PHASES
36+
// CHECK_PHASES: 0: input, "{{.*}}", c++, (device-sycl)
37+
// CHECK_PHASES: 1: preprocessor, {0}, c++-cpp-output, (device-sycl)
38+
// CHECK_PHASES: 2: compiler, {1}, ir, (device-sycl)
39+
// CHECK_PHASES: 3: backend, {2}, ir, (device-sycl)
40+
// CHECK_PHASES: 4: offload, "device-sycl (spir64-unknown-unknown)" {3}, ir
41+
// CHECK_PHASES: 5: clang-offload-packager, {4}, image, (device-sycl)
42+
// CHECK_PHASES: 6: clang-linker-wrapper, {5}, image, (device-sycl)
43+
// CHECK_PHASES: 7: offload, "device-sycl (x86_64-unknown-linux-gnu)" {6}, none
44+
45+
/// Check the output file names (file.syclbin, or -o <file>)
46+
// RUN: %clangxx --target=x86_64-unknown-linux-gnu -fsyclbin \
47+
// RUN: --offload-new-driver -o file.syclbin %s -### 2>&1 \
48+
// RUN: | FileCheck %s --check-prefix=CHECK_NAMED_OUTPUT
49+
// CHECK_NAMED_OUTPUT: clang-linker-wrapper
50+
// CHECK_NAMED_OUTPUT-SAME: "-o" "file.syclbin"
51+
52+
// RUN: %clang_cl -fsyclbin --offload-new-driver -o file.syclbin %s -### 2>&1 \
53+
// RUN: | FileCheck %s --check-prefix=CHECK_NAMED_OUTPUT_WIN
54+
// CHECK_NAMED_OUTPUT_WIN: clang-linker-wrapper
55+
// CHECK_NAMED_OUTPUT_WIN-SAME: "-out:file.syclbin"
56+
57+
/// For Linux - the default is 'a.out' so the syclbin file is 'a.syclbin'
58+
// RUN: %clangxx --target=x86_64-unknown-linux-gnu -fsyclbin \
59+
// RUN: --offload-new-driver %s -### 2>&1 \
60+
// RUN: | FileCheck %s --check-prefix=CHECK_LINUX_DEFAULT_OUTPUT
61+
// CHECK_LINUX_DEFAULT_OUTPUT: clang-linker-wrapper
62+
// CHECK_LINUX_DEFAULT_OUTPUT-SAME: "-o" "a.syclbin"
63+
64+
/// For Windows - the default is based on the source file so the syclbin file
65+
/// is 'fsyclbin.syclbin'
66+
// RUN: %clang_cl -fsyclbin --offload-new-driver %s -### 2>&1 \
67+
// RUN: | FileCheck %s --check-prefix=CHECK_WIN_DEFAULT_OUTPUT
68+
// CHECK_WIN_DEFAULT_OUTPUT: clang-linker-wrapper
69+
// CHECK_WIN_DEFAULT_OUTPUT-SAME: "-out:{{.*}}fsyclbin.syclbin"

sycl/test/syclbin/simple_kernel.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,8 @@
1-
// RUN: %clangxx -fsycl-device-only -Xclang -emit-llvm-bc -o %t.bc %s
2-
// RUN: clang-offload-packager -o %t.out "--image=file=%t.bc,triple=spir64-unknown-unknown,arch=,kind=sycl,compile-opts="
3-
// RUN: clang-linker-wrapper --syclbin --host-triple=x86_64-unknown-linux-gnu -sycl-device-libraries="libsycl-crt.new.o" -sycl-device-library-location=%sycl_libs_dir --sycl-post-link-options="-device-globals" --llvm-spirv-options=-spirv-max-version=1.4 -o %t.syclbin %t.out
1+
// RUN: %clangxx --offload-new-driver -fsyclbin -o %t.syclbin %s
42
// RUN: syclbin-dump %t.syclbin | FileCheck %s
53

64
// Checks the generated SYCLBIN contents of a simple SYCL free function kernel.
75

8-
// TODO: Replace clang tooling invocation with -fsyclbin clang driver command
9-
// when available. Once this is in place, Windows should also be
10-
// supported.
11-
// UNSUPPORTED: windows
12-
// UNSUPPORTED-TRACKER: CMPLRLLVM-65259
13-
146
#include <sycl/sycl.hpp>
157

168
extern "C" {

0 commit comments

Comments
 (0)