https://github.com/YuriPlyakhin updated https://github.com/llvm/llvm-project/pull/206870
>From 9d6a2b8e6bc7fdaada513ebb8e278f6c5746afad Mon Sep 17 00:00:00 2001 From: "Plyakhin, Yury" <[email protected]> Date: Wed, 1 Jul 2026 02:37:42 +0200 Subject: [PATCH 1/2] [clang][SYCL] Add -fsycl-device-code-split option Add the -fsycl-device-code-split= driver option to control how SYCL device code is split into separate device images. Supported values: - per_kernel: one device image per SYCL kernel - per_source: one device image per translation unit - off: no device code split The bare -fsycl-device-code-split flag is an alias for -fsycl-device-code-split=per_source, which is also the default. Co-Authored-By: Claude --- clang/docs/ReleaseNotes.md | 5 +++++ clang/include/clang/Options/Options.td | 9 +++++++++ clang/lib/Driver/ToolChains/Clang.cpp | 20 ++++++++++++++++++++ clang/test/Driver/sycl-offload-jit.cpp | 26 ++++++++++++++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index cde904ebaac1e..dae7c6c7c8bc2 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -1136,6 +1136,11 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the - Fixed `-nolibsycl` being silently ignored on Linux: the SYCL runtime library was unconditionally added to the link line even when the flag was passed. +- Added the `-fsycl-device-code-split=` option to control SYCL device code + splitting. Supported values are `per_kernel` (one device image per kernel), + `per_source` (one device image per translation unit), and `off` (no split). + The bare `-fsycl-device-code-split` flag is an alias for + `-fsycl-device-code-split=per_source`, which is also the default. #### Improvements diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 9f1f4a5a682ee..6cca1857ea073 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -7572,6 +7572,15 @@ def fsycl_host_only : Flag<["-"], "fsycl-host-only">, def sycl_link : Flag<["--"], "sycl-link">, Flags<[HelpHidden]>, HelpText<"Perform link through clang-sycl-linker via the target " "offloading toolchain.">; +def fsycl_device_code_split_EQ : Joined<["-"], "fsycl-device-code-split=">, + HelpText<"Perform SYCL device code split: per_kernel (device code module is " + "created for each SYCL kernel) | per_source (device code module is " + "created for each source (translation unit)) | off (no device code " + "split). Default is 'per_source'.">, + Values<"per_kernel,per_source,off">; +def fsycl_device_code_split : Flag<["-"], "fsycl-device-code-split">, + Alias<fsycl_device_code_split_EQ>, AliasArgs<["per_source"]>, + HelpText<"Perform SYCL device code split in the 'per_source' mode.">; } // let Group = sycl_Group // OS-specific options diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index e4b62590ef811..4eaabdc9dc3b6 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -9876,6 +9876,26 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, LinkerArgs.emplace_back("--create-library"); } + // Translate the SYCL device code split mode into the corresponding + // clang-sycl-linker `--module-split-mode` value. + if (Kind == Action::OFK_SYCL) { + if (Arg *A = ToolChainArgs.getLastArg(OPT_fsycl_device_code_split_EQ)) { + StringRef Mode = A->getValue(); + StringRef SplitMode = + llvm::StringSwitch<StringRef>(Mode) + .Case("per_kernel", "kernel") + .Case("per_source", "source") + .Case("off", "none") + .Default(""); + if (SplitMode.empty()) + C.getDriver().Diag(clang::diag::err_drv_invalid_value) + << A->getSpelling() << Mode; + else + LinkerArgs.emplace_back( + Args.MakeArgString("--module-split-mode=" + SplitMode)); + } + } + // Forward all of these to the appropriate toolchain. for (StringRef Arg : CompilerArgs) CmdArgs.push_back(Args.MakeArgString( diff --git a/clang/test/Driver/sycl-offload-jit.cpp b/clang/test/Driver/sycl-offload-jit.cpp index fe329f79e03f4..bccdb4652addd 100644 --- a/clang/test/Driver/sycl-offload-jit.cpp +++ b/clang/test/Driver/sycl-offload-jit.cpp @@ -54,6 +54,32 @@ // CHECK-NO-SPIRVLINK-FLAGS-NOT: --device-linker=spirv64-unknown-unknown=--allow-partial-linkage // CHECK-NO-SPIRVLINK-FLAGS-NOT: --device-linker=spirv64-unknown-unknown=--create-library +/// Check -fsycl-device-code-split= is translated to the corresponding +/// clang-sycl-linker --module-split-mode= value. +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl -fsycl-device-code-split=per_kernel %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-SPLIT-KERNEL %s +// CHK-SPLIT-KERNEL: clang-linker-wrapper{{.*}}"--device-linker=spirv64-unknown-unknown=--module-split-mode=kernel" +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl -fsycl-device-code-split=per_source %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-SPLIT-SOURCE %s +// CHK-SPLIT-SOURCE: clang-linker-wrapper{{.*}}"--device-linker=spirv64-unknown-unknown=--module-split-mode=source" +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl -fsycl-device-code-split=off %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-SPLIT-OFF %s +// CHK-SPLIT-OFF: clang-linker-wrapper{{.*}}"--device-linker=spirv64-unknown-unknown=--module-split-mode=none" + +/// Check the bare -fsycl-device-code-split flag aliases to 'per_source'. +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl -fsycl-device-code-split %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-SPLIT-SOURCE %s + +/// Check that without -fsycl-device-code-split, no --module-split-mode= is passed. +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-NO-SPLIT %s +// CHK-NO-SPLIT-NOT: --module-split-mode= + +/// Check an invalid -fsycl-device-code-split= value is diagnosed. +// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -fsycl -fsycl-device-code-split=bogus %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-SPLIT-INVALID %s +// CHK-SPLIT-INVALID: error: invalid value 'bogus' in '-fsycl-device-code-split=' + /// Check for option incompatibility with -fsycl // RUN: not %clang -### -fsycl -ffreestanding %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-INCOMPATIBILITY %s -DINCOMPATOPT=-ffreestanding >From 46f5fe65fda97e524716d3ac2965da00bc9c9d57 Mon Sep 17 00:00:00 2001 From: "Plyakhin, Yury" <[email protected]> Date: Wed, 1 Jul 2026 04:23:10 +0200 Subject: [PATCH 2/2] format --- clang/lib/Driver/ToolChains/Clang.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 4eaabdc9dc3b6..0aedcef6f9930 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -9881,12 +9881,11 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, if (Kind == Action::OFK_SYCL) { if (Arg *A = ToolChainArgs.getLastArg(OPT_fsycl_device_code_split_EQ)) { StringRef Mode = A->getValue(); - StringRef SplitMode = - llvm::StringSwitch<StringRef>(Mode) - .Case("per_kernel", "kernel") - .Case("per_source", "source") - .Case("off", "none") - .Default(""); + StringRef SplitMode = llvm::StringSwitch<StringRef>(Mode) + .Case("per_kernel", "kernel") + .Case("per_source", "source") + .Case("off", "none") + .Default(""); if (SplitMode.empty()) C.getDriver().Diag(clang::diag::err_drv_invalid_value) << A->getSpelling() << Mode; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
