Skip to content

Commit 643abde

Browse files
authored
[SYCL][New offload] Add support for -fsycl-link in new offload model (#19434)
This PR adds support for -fsycl-link in the compilation flow for the new offloading model. Specifically, we pass a new option "--sycl-device-link" to clang-linker-wrapper. We DO NOT call the final host linker if the option is set. Thanks --------- Signed-off-by: Arvind Sudarsanam <[email protected]>
1 parent 353a2ea commit 643abde

File tree

6 files changed

+63
-3
lines changed

6 files changed

+63
-3
lines changed

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11222,6 +11222,10 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
1122211222

1122311223
// Add any SYCL offloading specific options to the clang-linker-wrapper
1122411224
if (C.hasOffloadToolChain<Action::OFK_SYCL>()) {
11225+
11226+
if (Args.hasArg(options::OPT_fsycl_link_EQ))
11227+
CmdArgs.push_back(Args.MakeArgString("--sycl-device-link"));
11228+
1122511229
// -sycl-device-libraries=<comma separated list> contains all of the SYCL
1122611230
// device specific libraries that are needed. This generic list will be
1122711231
// populated with device binaries for all target triples in the current

clang/test/Driver/sycl-linker-wrapper-win.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,15 @@
130130
// CHK-CMDS-DEVICE-LIB-DIR-NEXT: "{{.*}}llvm-link.exe" {{.*}} --suppress-warnings
131131
// CHK-CMDS-DEVICE-LIB-DIR-NEXT: "{{.*}}llvm-link.exe" -only-needed {{.*}} --suppress-warnings
132132
// CHK-CMDS-DEVICE-LIB-DIR-NEXT: "{{.*}}sycl-post-link.exe"{{.*}} --device-lib-dir={{.*}}/Inputs/SYCL/lib {{.*}} SYCL_POST_LINK_OPTIONS {{.*}}
133+
134+
// Verify that host linker is not called when --sycl-device-link is passed to clang-linker-wrapper
135+
// RUN: clang-linker-wrapper --sycl-device-link -sycl-device-libraries=%t.devicelib.o -sycl-post-link-options="SYCL_POST_LINK_OPTIONS" -llvm-spirv-options="LLVM_SPIRV_OPTIONS" "--host-triple=x86_64-pc-windows-msvc" "--linker-path=/usr/bin/ld" "--" HOST_LINKER_FLAGS "-dynamic-linker" HOST_DYN_LIB "-o" "a.exe" HOST_LIB_PATH HOST_STAT_LIB %t.o --dry-run 2>&1 | FileCheck -check-prefix=CHK-DEVLINK-CMDS %s
136+
// CHK-DEVLINK-CMDS: "{{.*}}spirv-to-ir-wrapper.exe" {{.*}} -o [[FIRSTLLVMLINKIN:.*]].bc --llvm-spirv-opts --spirv-preserve-auxdata --spirv-target-env=SPV-IR --spirv-builtin-format=global
137+
// CHK-DEVLINK-CMDS-NEXT: "{{.*}}llvm-link.exe" [[FIRSTLLVMLINKIN:.*]].bc -o [[FIRSTLLVMLINKOUT:.*]].bc --suppress-warnings
138+
// CHK-DEVLINK-CMDS-NEXT: "{{.*}}llvm-link.exe" -only-needed [[FIRSTLLVMLINKOUT]].bc {{.*}}.bc -o [[SECONDLLVMLINKOUT:.*]].bc --suppress-warnings
139+
// CHK-DEVLINK-CMDS-NEXT: "{{.*}}sycl-post-link.exe"{{.*}} SYCL_POST_LINK_OPTIONS -o [[SYCLPOSTLINKOUT:.*]].table [[SECONDLLVMLINKOUT]].bc
140+
// CHK-DEVLINK-CMDS-NEXT: "{{.*}}llvm-spirv.exe"{{.*}} LLVM_SPIRV_OPTIONS -o {{.*}}
141+
// CHK-DEVLINK-CMDS-NEXT: offload-wrapper: input: {{.*}}, output: [[WRAPPEROUT:.*]].bc
142+
// CHK-DEVLINK-CMDS-NEXT: "{{.*}}clang.exe"{{.*}} -c -o {{.*}} [[WRAPPEROUT]].bc
143+
// CHK-DEVLINK-CMDS-NEXT: "{{.*}}copy"{{.*}} {{.*}} a.exe
144+
// CHK-DEVLINK-CMDS-NOT: "{{.*}}ld"

clang/test/Driver/sycl-linker-wrapper.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,15 @@
216216
// CHK-CMDS-NATIVE-CPU-NEXT: offload-wrapper: input: [[OUT1]], output: [[OUT2:.*\.bc]]
217217
// CHK-CMDS-NATIVE-CPU-NEXT: "{{.*}}clang" --target=x86_64-unknown-linux-gnu -c -o [[OUT3:.*\.o]] [[OUT2]]
218218
// CHK-CMDS-NATIVE-CPU-NEXT: "{{.*}}ld" -- HOST_LINKER_FLAGS -dynamic-linker HOST_DYN_LIB -o a.out [[OUT1]] [[OUT3]] {{.*\.o}}
219+
220+
// Verify that host linker is not called when --sycl-device-link is passed to clang-linker-wrapper
221+
// RUN: clang-linker-wrapper --sycl-device-link -sycl-device-libraries=%t.devicelib.o -sycl-post-link-options="SYCL_POST_LINK_OPTIONS" -llvm-spirv-options="LLVM_SPIRV_OPTIONS" "--host-triple=x86_64-unknown-linux-gnu" "--linker-path=/usr/bin/ld" "--" HOST_LINKER_FLAGS "-dynamic-linker" HOST_DYN_LIB "-o" "a.out" HOST_LIB_PATH HOST_STAT_LIB %t.o --dry-run 2>&1 | FileCheck -check-prefix=CHK-DEVLINK-CMDS %s
222+
// CHK-DEVLINK-CMDS: "{{.*}}spirv-to-ir-wrapper" {{.*}} -o [[FIRSTLLVMLINKIN:.*]].bc --llvm-spirv-opts --spirv-preserve-auxdata --spirv-target-env=SPV-IR --spirv-builtin-format=global
223+
// CHK-DEVLINK-CMDS-NEXT: "{{.*}}llvm-link" [[FIRSTLLVMLINKIN]].bc -o [[FIRSTLLVMLINKOUT:.*]].bc --suppress-warnings
224+
// CHK-DEVLINK-CMDS-NEXT: "{{.*}}llvm-link" -only-needed [[FIRSTLLVMLINKOUT]].bc {{.*}}.bc -o [[SECONDLLVMLINKOUT:.*]].bc --suppress-warnings
225+
// CHK-DEVLINK-CMDS-NEXT: "{{.*}}sycl-post-link"{{.*}} SYCL_POST_LINK_OPTIONS -o [[SYCLPOSTLINKOUT:.*]].table [[SECONDLLVMLINKOUT]].bc
226+
// CHK-DEVLINK-CMDS-NEXT: "{{.*}}llvm-spirv"{{.*}} LLVM_SPIRV_OPTIONS -o {{.*}}
227+
// CHK-DEVLINK-CMDS-NEXT: offload-wrapper: input: {{.*}}, output: [[WRAPPEROUT:.*]].bc
228+
// CHK-DEVLINK-CMDS-NEXT: "{{.*}}clang"{{.*}} -c -o [[CLANGOUT:.*]] [[WRAPPEROUT]].bc
229+
// CHK-DEVLINK-CMDS-NEXT: "{{.*}}cp"{{.*}} [[CLANGOUT]] a.out
230+
// CHK-DEVLINK-CMDS-NOT: "{{.*}}/ld"

clang/test/Driver/sycl-offload-new-driver.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,8 @@
223223
// CHK-MACRO-GFX90A: clang{{.*}} "-fsycl-is-device"{{.*}} "-D__SYCL_TARGET_AMD_GPU_GFX90A__"{{.*}}
224224
// CHK-MACRO-GFX90C: clang{{.*}} "-fsycl-is-device"{{.*}} "-D__SYCL_TARGET_AMD_GPU_GFX90C__"{{.*}}
225225

226+
/// Check that -sycl-device-link is passed to clang-linker-wrapper tool
227+
// RUN: %clangxx -fsycl -### --offload-new-driver \
228+
// RUN: -fsycl-link %s 2>&1 \
229+
// RUN: | FileCheck -check-prefix CHECK_SYCL_DEVICE_LINKING %s
230+
// CHECK_SYCL_DEVICE_LINKING: clang-linker-wrapper{{.*}} "--sycl-device-link"

clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,12 +1227,26 @@ packageSYCLBIN(SYCLBIN::BundleState State,
12271227
return *OutFileOrErr;
12281228
}
12291229

1230+
Error copyFileToFinalExecutable(StringRef File, const ArgList &Args) {
1231+
if (Verbose || DryRun) {
1232+
llvm::Triple Triple(Args.getLastArgValue(OPT_host_triple_EQ,
1233+
sys::getDefaultTargetTriple()));
1234+
StringRef CopyCommand = Triple.isOSWindows() ? "copy" : "cp";
1235+
llvm::errs() << "\"" << CopyCommand << "\" " << File << " "
1236+
<< ExecutableName << "\n";
1237+
}
1238+
// TODO: check if copy can be replaced by rename.
1239+
if (std::error_code EC = sys::fs::copy_file(File, ExecutableName))
1240+
return createFileError(ExecutableName, EC);
1241+
return Error::success();
1242+
}
1243+
12301244
Error mergeSYCLBIN(ArrayRef<StringRef> Files, const ArgList &Args) {
12311245
// Fast path for the general case where there's only one file. In this case we
12321246
// do not need to parse it and can instead simply copy it.
12331247
if (Files.size() == 1) {
1234-
if (std::error_code EC = sys::fs::copy_file(Files[0], ExecutableName))
1235-
return createFileError(ExecutableName, EC);
1248+
if (Error Err = copyFileToFinalExecutable(Files[0], Args))
1249+
reportError(std::move(Err));
12361250
return Error::success();
12371251
}
12381252
// TODO: Merge SYCLBIN files here and write to ExecutableName output.
@@ -2227,7 +2241,7 @@ Expected<SmallVector<StringRef>> linkAndWrapDeviceFiles(
22272241

22282242
// Store the offloading image for each linked output file.
22292243
for (OffloadKind Kind = OFK_OpenMP; Kind != OFK_LAST;
2230-
Kind = static_cast<OffloadKind>((uint16_t)(Kind) << 1)) {
2244+
Kind = static_cast<OffloadKind>((uint16_t)(Kind) << 1)) {
22312245
if ((ActiveOffloadKindMask & Kind) == 0)
22322246
continue;
22332247
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileOrErr =
@@ -2789,6 +2803,14 @@ int main(int Argc, char **Argv) {
27892803
if (OutputSYCLBIN) {
27902804
if (Error Err = sycl::mergeSYCLBIN(*FilesOrErr, Args))
27912805
reportError(std::move(Err));
2806+
} else if (Args.hasArg(OPT_sycl_device_link)) {
2807+
// Skip host linker if --sycl-device-link option is set.
2808+
// Just copy the output of device linking and wrapping action.
2809+
if (FilesOrErr->size() != 1)
2810+
reportError(
2811+
createStringError("Expect single output from the device linker."));
2812+
if (Error Err = sycl::copyFileToFinalExecutable((*FilesOrErr)[0], Args))
2813+
reportError(std::move(Err));
27922814
} else {
27932815
// Run the host linking job with the rendered arguments.
27942816
if (Error Err = runLinker(*FilesOrErr, Args))

clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,11 @@ Flags<[WrapperOnlyOption]>, HelpText<"Link SYCL device code using thinLTO">;
228228
def sycl_embed_ir : Flag<["--", "-"], "sycl-embed-ir">,
229229
Flags<[WrapperOnlyOption]>, HelpText<"Embed LLVM IR for runtime kernel fusion">;
230230

231+
def sycl_device_link
232+
: Flag<["--", "-"], "sycl-device-link">,
233+
Flags<[WrapperOnlyOption]>,
234+
HelpText<"Link SYCL device code only. Discard host code.">;
235+
231236
def sycl_dump_device_code_EQ : Joined<["--", "-"], "sycl-dump-device-code=">,
232237
Flags<[WrapperOnlyOption]>,
233238
HelpText<"Directory to dump offloading images to.">;

0 commit comments

Comments
 (0)