https://github.com/koparasy updated https://github.com/llvm/llvm-project/pull/213728
>From a81e0c8a8531d8a8e97cf80f0fe11ff4fce8d486 Mon Sep 17 00:00:00 2001 From: Konstantinos Parasyris <[email protected]> Date: Mon, 3 Aug 2026 10:37:17 -0700 Subject: [PATCH 1/3] [CIR] Support SYCL kernel call statement in host codegen --- clang/lib/CIR/CodeGen/CIRGenFunction.h | 6 +++ clang/lib/CIR/CodeGen/CIRGenModule.cpp | 20 +++++++++ clang/lib/CIR/CodeGen/CIRGenSYCL.cpp | 35 +++++++++++++++ clang/lib/CIR/CodeGen/CIRGenStmt.cpp | 4 +- clang/lib/CIR/CodeGen/CMakeLists.txt | 1 + .../kernel-call-stmt-device-nyi.cpp | 23 ++++++++++ .../test/CIR/CodeGenSYCL/kernel-call-stmt.cpp | 45 +++++++++++++++++++ 7 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 clang/lib/CIR/CodeGen/CIRGenSYCL.cpp create mode 100644 clang/test/CIR/CodeGenSYCL/kernel-call-stmt-device-nyi.cpp create mode 100644 clang/test/CIR/CodeGenSYCL/kernel-call-stmt.cpp diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 4ba3ee59f49b0..5c0fac6f0330c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -48,6 +48,10 @@ class LoopOp; } // namespace acc } // namespace mlir +namespace clang { +class SYCLKernelCallStmt; +} // namespace clang + namespace clang::CIRGen { struct CGCoroData; @@ -2267,6 +2271,8 @@ class CIRGenFunction : public CIRGenTypeCache { bool buildingTopLevelCase); mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s); + mlir::LogicalResult emitSYCLKernelCallStmt(const SYCLKernelCallStmt &s); + std::optional<mlir::Value> emitTargetBuiltinExpr(unsigned builtinID, const clang::CallExpr *e, ReturnValueSlot &returnValue); diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index a7143408c9bee..b475b17cd4816 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -432,6 +432,26 @@ void CIRGenModule::emitDeferred() { curDeclsToEmit.swap(deferredDeclsToEmit); for (const GlobalDecl &d : curDeclsToEmit) { + // Functions declared with the sycl_kernel_entry_point attribute are + // emitted normally during host compilation. During device compilation, a + // SYCL kernel caller offload entry point function is generated and emitted + // in place of each of these functions. + if (const auto *fd = d.getDecl()->getAsFunction()) { + if (langOpts.SYCLIsDevice && fd->hasAttr<SYCLKernelEntryPointAttr>() && + fd->isDefined()) { + // Functions with an invalid sycl_kernel_entry_point attribute are + // ignored during device compilation. + if (!fd->getAttr<SYCLKernelEntryPointAttr>()->isInvalidAttr()) { + // Generating the SYCL kernel caller offload entry point is not yet + // implemented in CIR. + errorNYI(fd->getSourceRange(), + "SYCL kernel caller offload entry point"); + } + // Do not emit the sycl_kernel_entry_point attributed function. + continue; + } + } + emitGlobalDecl(d); // If we found out that we need to emit more decls, do that recursively. diff --git a/clang/lib/CIR/CodeGen/CIRGenSYCL.cpp b/clang/lib/CIR/CodeGen/CIRGenSYCL.cpp new file mode 100644 index 0000000000000..9308b1fe4189f --- /dev/null +++ b/clang/lib/CIR/CodeGen/CIRGenSYCL.cpp @@ -0,0 +1,35 @@ +//===--------- CIRGenSYCL.cpp - Emit CIR for SYCL kernels -----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This contains code required for the generation of SYCL kernel code. +// +//===----------------------------------------------------------------------===// + +#include "CIRGenFunction.h" + +#include "clang/AST/StmtSYCL.h" + +using namespace clang; +using namespace clang::CIRGen; + +mlir::LogicalResult +CIRGenFunction::emitSYCLKernelCallStmt(const SYCLKernelCallStmt &s) { + // SYCLKernelCallStmt nodes are only present in the bodies of functions + // declared with the sycl_kernel_entry_point attribute. ODR-use of such a + // function in code emitted during device compilation should be diagnosed. + // During device compilation, the offload kernel entry point is emitted in + // place of such a function (see CIRGenModule::emitDeferred), so this + // function is only reached during host compilation. + assert(!getLangOpts().SYCLIsDevice && + "Attempt to emit a SYCL kernel call statement during device " + "compilation"); + + // During host compilation, the kernel launch statement is emitted in place + // of the original function body. + return emitStmt(s.getKernelLaunchStmt(), /*useCurrentScope=*/true); +} diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index d34769200dbfd..8e4c5f008c5a0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -20,6 +20,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" +#include "clang/AST/StmtSYCL.h" #include "clang/CIR/MissingFeatures.h" #include "llvm/Support/SaveAndRestore.h" @@ -210,6 +211,8 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s, return emitIndirectGotoStmt(cast<IndirectGotoStmt>(*s)); case Stmt::CoreturnStmtClass: return emitCoreturnStmt(cast<CoreturnStmt>(*s)); + case Stmt::SYCLKernelCallStmtClass: + return emitSYCLKernelCallStmt(cast<SYCLKernelCallStmt>(*s)); case Stmt::OpenACCComputeConstructClass: return emitOpenACCComputeConstruct(cast<OpenACCComputeConstruct>(*s)); case Stmt::OpenACCLoopConstructClass: @@ -431,7 +434,6 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s, case Stmt::DefaultStmtClass: case Stmt::CaseStmtClass: case Stmt::SEHLeaveStmtClass: - case Stmt::SYCLKernelCallStmtClass: case Stmt::ObjCAtTryStmtClass: case Stmt::ObjCAtThrowStmtClass: case Stmt::ObjCAtSynchronizedStmtClass: diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt index 78569b11651e0..1fe9b25dd786c 100644 --- a/clang/lib/CIR/CodeGen/CMakeLists.txt +++ b/clang/lib/CIR/CodeGen/CMakeLists.txt @@ -52,6 +52,7 @@ add_clang_library(clangCIR CIRGenStmtOpenACC.cpp CIRGenStmtOpenACCLoop.cpp CIRGenStmtOpenMP.cpp + CIRGenSYCL.cpp CIRGenTypes.cpp CIRGenVTables.cpp TargetInfo.cpp diff --git a/clang/test/CIR/CodeGenSYCL/kernel-call-stmt-device-nyi.cpp b/clang/test/CIR/CodeGenSYCL/kernel-call-stmt-device-nyi.cpp new file mode 100644 index 0000000000000..c6522064f2fdc --- /dev/null +++ b/clang/test/CIR/CodeGenSYCL/kernel-call-stmt-device-nyi.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++20 -fsycl-is-device -triple spir64-unknown-unknown \ +// RUN: -fclangir -emit-cir -verify %s + +// During device compilation, a SYCL kernel caller offload entry point is +// emitted in place of each sycl_kernel_entry_point attributed function. That +// lowering is not yet implemented in CIR, so it must be reported as a clean +// "Not Yet Implemented" diagnostic rather than crashing. + +// 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)]] +// expected-error@+1 {{ClangIR code gen Not Yet Implemented: SYCL kernel caller offload entry point}} +void kernel_single_task(KernelType kf) { kf(); } + +struct KN; +struct K { + void operator()() const {} +}; + +void test() { kernel_single_task<KN>(K{}); } diff --git a/clang/test/CIR/CodeGenSYCL/kernel-call-stmt.cpp b/clang/test/CIR/CodeGenSYCL/kernel-call-stmt.cpp new file mode 100644 index 0000000000000..3f42bad95dc14 --- /dev/null +++ b/clang/test/CIR/CodeGenSYCL/kernel-call-stmt.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -std=c++20 -fsycl-is-host -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -std=c++20 -fsycl-is-host -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -std=c++20 -fsycl-is-host -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG + +// Verify that, during host compilation, the body of a function declared with +// the sycl_kernel_entry_point attribute is lowered to its kernel launch +// statement rather than reporting a not-yet-implemented error. The kernel +// entry point body must be replaced by the launch call; the original kernel +// functor invocation must not be emitted on the host. + +// 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 test() { kernel_single_task<KN>(K{}); } + +// The kernel entry point body is replaced by a call to the sycl_kernel_launch +// specialization, and does not invoke the kernel functor's operator() on the +// host. +// CIR-LABEL: cir.func {{.*}}@_Z18kernel_single_taskI2KN1KEvT0_ +// CIR-NOT: cir.call @_ZNK1KclEv +// CIR: cir.call @_Z18sycl_kernel_launchI2KNJ1KEEvPKcDpT0_ +// CIR: cir.return + +// LLVM-LABEL: define {{.*}}void @_Z18kernel_single_taskI2KN1KEvT0_ +// LLVM-NOT: call {{.*}}@_ZNK1KclEv +// LLVM: call void @_Z18sycl_kernel_launchI2KNJ1KEEvPKcDpT0_ +// LLVM: ret void + +// OGCG-LABEL: define {{.*}}void @_Z18kernel_single_taskI2KN1KEvT0_ +// OGCG-NOT: call {{.*}}@_ZNK1KclEv +// OGCG: call void @_Z18sycl_kernel_launchI2KNJ1KEEvPKcDpT0_ +// OGCG: ret void >From 891b22888d7cec2cb1b4e63c015986b5ab73f08d Mon Sep 17 00:00:00 2001 From: Konstantinos Parasyris <[email protected]> Date: Mon, 3 Aug 2026 10:48:08 -0700 Subject: [PATCH 2/3] Rename file to align with OG SYCL --- ...call-stmt-device-nyi.cpp => kernel-caller-entry-point-nyi.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename clang/test/CIR/CodeGenSYCL/{kernel-call-stmt-device-nyi.cpp => kernel-caller-entry-point-nyi.cpp} (100%) diff --git a/clang/test/CIR/CodeGenSYCL/kernel-call-stmt-device-nyi.cpp b/clang/test/CIR/CodeGenSYCL/kernel-caller-entry-point-nyi.cpp similarity index 100% rename from clang/test/CIR/CodeGenSYCL/kernel-call-stmt-device-nyi.cpp rename to clang/test/CIR/CodeGenSYCL/kernel-caller-entry-point-nyi.cpp >From 8d53d076f0ff0312308082460ff77227d33f7e12 Mon Sep 17 00:00:00 2001 From: Konstantinos Parasyris <[email protected]> Date: Wed, 5 Aug 2026 16:45:48 -0700 Subject: [PATCH 3/3] Address comments --- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 5 +---- ...ler-entry-point-nyi.cpp => kernel-caller-entry-point.cpp} | 0 2 files changed, 1 insertion(+), 4 deletions(-) rename clang/test/CIR/CodeGenSYCL/{kernel-caller-entry-point-nyi.cpp => kernel-caller-entry-point.cpp} (100%) diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index b475b17cd4816..fa1bdd267fc8f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -441,12 +441,9 @@ void CIRGenModule::emitDeferred() { fd->isDefined()) { // Functions with an invalid sycl_kernel_entry_point attribute are // ignored during device compilation. - if (!fd->getAttr<SYCLKernelEntryPointAttr>()->isInvalidAttr()) { - // Generating the SYCL kernel caller offload entry point is not yet - // implemented in CIR. + if (!fd->getAttr<SYCLKernelEntryPointAttr>()->isInvalidAttr()) errorNYI(fd->getSourceRange(), "SYCL kernel caller offload entry point"); - } // Do not emit the sycl_kernel_entry_point attributed function. continue; } diff --git a/clang/test/CIR/CodeGenSYCL/kernel-caller-entry-point-nyi.cpp b/clang/test/CIR/CodeGenSYCL/kernel-caller-entry-point.cpp similarity index 100% rename from clang/test/CIR/CodeGenSYCL/kernel-caller-entry-point-nyi.cpp rename to clang/test/CIR/CodeGenSYCL/kernel-caller-entry-point.cpp _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
