https://github.com/YuriPlyakhin updated 
https://github.com/llvm/llvm-project/pull/195965

>From 65a4a7e5eb6edec26c196d62ef2a63ae13d163db Mon Sep 17 00:00:00 2001
From: "Plyakhin, Yury" <[email protected]>
Date: Wed, 6 May 2026 01:07:34 +0200
Subject: [PATCH 1/2] [clang][SYCL] Emit "sycl-module-id" function attribute

Attach the "sycl-module-id" LLVM function attribute to SYCL device
functions that are candidates for entry points in device-code splitting.
The attribute value is the module identifier (translation unit name),
which clang-sycl-linker uses to group kernels by translation unit when
splitting device code.

The attribute is emitted at two sites:

1. SYCL kernel caller functions (spir_kernel) are synthesized by
   EmitSYCLKernelCaller and do not go through EmitFunction, so the
   attribute is set directly after SetSYCLKernelAttributes.

2. sycl_external function definitions go through
   SetLLVMFunctionAttributesForDefinition; the attribute is added there
   when SYCLIsDevice and SYCLExternalAttr are present.

Both sites call the new CodeGenModule::addSYCLModuleIdAttr helper.

Co-authored-by: Claude
---
 clang/lib/CodeGen/CodeGenModule.cpp           | 13 +++++++++
 clang/lib/CodeGen/CodeGenModule.h             |  5 ++++
 clang/lib/CodeGen/CodeGenSYCL.cpp             |  1 +
 .../CodeGenSYCL/kernel-caller-entry-point.cpp |  6 ++---
 clang/test/CodeGenSYCL/sycl-module-id.cpp     | 27 +++++++++++++++++++
 5 files changed, 49 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/CodeGenSYCL/sycl-module-id.cpp

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 20a28c39af88a..e88fed1296667 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3028,6 +3028,19 @@ void 
CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
       F->addTypeMetadata(0, Id);
     }
   }
+
+  // Attach "sycl-module-id" to sycl_external function definitions to mark
+  // them as entry points for per-translation-unit device-code splitting.
+  if (getLangOpts().SYCLIsDevice) {
+    if (const auto *FD = dyn_cast<FunctionDecl>(D))
+      if (FD->hasAttr<SYCLExternalAttr>())
+        addSYCLModuleIdAttr(F);
+  }
+}
+
+void CodeGenModule::addSYCLModuleIdAttr(llvm::Function *Fn) {
+  assert(getLangOpts().SYCLIsDevice);
+  Fn->addFnAttr("sycl-module-id", getModule().getModuleIdentifier());
 }
 
 void CodeGenModule::SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV) {
diff --git a/clang/lib/CodeGen/CodeGenModule.h 
b/clang/lib/CodeGen/CodeGenModule.h
index d62707a3355c9..44af19e295bed 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -2075,6 +2075,11 @@ class CodeGenModule : public CodeGenTypeCache {
   void EmitSYCLKernelCaller(const FunctionDecl *KernelEntryPointFn,
                             ASTContext &Ctx);
 
+  /// Attach the "sycl-module-id" function attribute to \p Fn, recording the
+  /// translation unit name. Used on SYCL kernels and sycl_external functions
+  /// to enable per-translation-unit device-code splitting.
+  void addSYCLModuleIdAttr(llvm::Function *Fn);
+
   /// Determine whether the definition must be emitted; if this returns \c
   /// false, the definition can be emitted lazily if it's used.
   bool MustBeEmitted(const ValueDecl *D);
diff --git a/clang/lib/CodeGen/CodeGenSYCL.cpp 
b/clang/lib/CodeGen/CodeGenSYCL.cpp
index 5a52675de299d..7ca749a25fe6c 100644
--- a/clang/lib/CodeGen/CodeGenSYCL.cpp
+++ b/clang/lib/CodeGen/CodeGenSYCL.cpp
@@ -76,6 +76,7 @@ void CodeGenModule::EmitSYCLKernelCaller(const FunctionDecl 
*KernelEntryPointFn,
   CodeGenFunction CGF(*this);
   SetLLVMFunctionAttributes(GlobalDecl(), FnInfo, Fn, false);
   SetSYCLKernelAttributes(Fn, CGF);
+  addSYCLModuleIdAttr(Fn);
   CGF.StartFunction(GlobalDecl(), Ctx.VoidTy, Fn, FnInfo, Args,
                     SourceLocation(), SourceLocation());
   CGF.EmitFunctionBody(OutlinedFnDecl->getBody());
diff --git a/clang/test/CodeGenSYCL/kernel-caller-entry-point.cpp 
b/clang/test/CodeGenSYCL/kernel-caller-entry-point.cpp
index 7af4c83d1ba32..410988e16acdc 100644
--- a/clang/test/CodeGenSYCL/kernel-caller-entry-point.cpp
+++ b/clang/test/CodeGenSYCL/kernel-caller-entry-point.cpp
@@ -703,11 +703,11 @@ int main() {
 // CHECK-SPIR-NEXT:     ret void
 // CHECK-SPIR-NEXT:   }
 
-// CHECK-AMDGCN: #[[AMDGCN_ATTR0]] = { convergent mustprogress noinline 
norecurse nounwind optnone "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" }
+// CHECK-AMDGCN: #[[AMDGCN_ATTR0]] = { convergent mustprogress noinline 
norecurse nounwind optnone "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" "sycl-module-id"=
 // CHECK-AMDGCN: #[[AMDGCN_ATTR1]] = { convergent nounwind }
 //
-// CHECK-NVPTX: #[[NVPTX_ATTR0]] = { convergent mustprogress noinline 
norecurse nounwind optnone "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" }
+// CHECK-NVPTX: #[[NVPTX_ATTR0]] = { convergent mustprogress noinline 
norecurse nounwind optnone "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" "sycl-module-id"=
 // CHECK-NVPTX: #[[NVPTX_ATTR1]] = { convergent nounwind }
 //
-// CHECK-SPIR: #[[SPIR_ATTR0]] = { convergent mustprogress noinline norecurse 
nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+// CHECK-SPIR: #[[SPIR_ATTR0]] = { convergent mustprogress noinline norecurse 
nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" 
"sycl-module-id"=
 // CHECK-SPIR: #[[SPIR_ATTR1]] = { convergent nounwind }
diff --git a/clang/test/CodeGenSYCL/sycl-module-id.cpp 
b/clang/test/CodeGenSYCL/sycl-module-id.cpp
new file mode 100644
index 0000000000000..d9beded116a65
--- /dev/null
+++ b/clang/test/CodeGenSYCL/sycl-module-id.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fsycl-is-device -triple spir64-unknown-unknown \
+// RUN:   -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
+
+// Verify that the "sycl-module-id" function attribute is emitted for:
+// 1. SYCL kernels
+// 2. sycl_external functions
+
+// Required by sycl_kernel_entry_point semantics.
+template <typename KernelName, typename... Ts>
+void sycl_kernel_launch(const char *, Ts...) {}
+
+template <typename KernelName, typename KernelType>
+[[clang::sycl_kernel_entry_point(KernelName)]]
+void kernel_single_task(KernelType kf) { kf(); }
+
+struct KN;
+struct K { void operator()() const {} };
+void use() { kernel_single_task<KN>(K{}); }
+
+[[clang::sycl_external]] int ext(int x) { return x + 1; }
+
+// Both the kernel and the sycl_external function must carry sycl-module-id
+// with a value equal to the module identifier (the source file path).
+// CHECK: source_filename = "[[MODID:.*]]"
+// CHECK-DAG: define {{.*}}spir_kernel {{.*}}@{{.*}}2KN{{.*}} #[[SATTR:[0-9]+]]
+// CHECK-DAG: define {{.*}}spir_func {{.*}}@_Z3exti{{.*}} #[[SATTR]]
+// CHECK: attributes #[[SATTR]] = { {{.*}}"sycl-module-id"="[[MODID]]"

>From f366b0dd36d1cd37a805ee87afac6bf202f6ef3c Mon Sep 17 00:00:00 2001
From: "Plyakhin, Yury" <[email protected]>
Date: Wed, 6 May 2026 23:53:22 +0200
Subject: [PATCH 2/2] updated comment pre feedback

---
 clang/lib/CodeGen/CodeGenModule.h | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenModule.h 
b/clang/lib/CodeGen/CodeGenModule.h
index 44af19e295bed..c7e168433e42c 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -2075,9 +2075,11 @@ class CodeGenModule : public CodeGenTypeCache {
   void EmitSYCLKernelCaller(const FunctionDecl *KernelEntryPointFn,
                             ASTContext &Ctx);
 
-  /// Attach the "sycl-module-id" function attribute to \p Fn, recording the
-  /// translation unit name. Used on SYCL kernels and sycl_external functions
-  /// to enable per-translation-unit device-code splitting.
+  /// Attach the "sycl-module-id" function attribute to \p Fn, to record the
+  /// module ID for the translation unit. This attribute is applied to SYCL
+  /// kernel entry point functions and functions declared with the
+  /// sycl_external attribute to enable them to be identified as entry points
+  /// by clang-sycl-linker during device-code splitting.
   void addSYCLModuleIdAttr(llvm::Function *Fn);
 
   /// Determine whether the definition must be emitted; if this returns \c

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to