https://github.com/YuriPlyakhin created
https://github.com/llvm/llvm-project/pull/206870
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
>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] [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
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits