Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SYCL] Lift restrictions on free-function kernels when compiling at runtime #15892

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ LANGOPT(SYCLExperimentalRangeRounding, 1, 0, "Use experimental parallel for rang
LANGOPT(SYCLEnableIntHeaderDiags, 1, 0, "Enable diagnostics that require the "
"SYCL integration header")
LANGOPT(SYCLIsNativeCPU , 1, 0, "Generate code for SYCL Native CPU")
LANGOPT(SYCLRTCMode, 1, 0, "Compile in RTC mode")

LANGOPT(HIPUseNewLaunchAPI, 1, 0, "Use new kernel launching API for HIP")
LANGOPT(OffloadUniformBlock, 1, 0, "Assume that kernels are launched with uniform block sizes (default true for CUDA/HIP and false otherwise)")
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -6877,6 +6877,11 @@ defm sycl_esimd_force_stateless_mem : BoolFOption<"sycl-esimd-force-stateless-me
NegFlag<SetFalse, [], [ClangOption, CLOption], "Do not enforce using "
"stateless memory accesses.">,
BothFlags<[], [ClangOption, CLOption, CC1Option], "">>;
defm sycl_rtc_mode: BoolFOption<"sycl-rtc-mode",
LangOpts<"SYCLRTCMode">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "RTC Mode On">,
NegFlag<SetFalse, [], [ClangOption], "RTC Mode Off">,
sommerlukas marked this conversation as resolved.
Show resolved Hide resolved
BothFlags<[HelpHidden], [ClangOption, CC1Option], " RTC mode in SYCL.">>;
// TODO: Remove this option once ESIMD headers are updated to
// guard vectors to be device only.
def fno_sycl_esimd_build_host_code : Flag<["-"], "fno-sycl-esimd-build-host-code">,
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5583,6 +5583,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fsycl-allow-func-ptr");
}

Args.AddLastArg(CmdArgs, options::OPT_fsycl_rtc_mode,
options::OPT_fno_sycl_rtc_mode);
mdtoguchi marked this conversation as resolved.
Show resolved Hide resolved

Args.AddLastArg(CmdArgs, options::OPT_fsycl_decompose_functor,
options::OPT_fno_sycl_decompose_functor);

Expand Down
12 changes: 12 additions & 0 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2040,6 +2040,11 @@ class SyclKernelFieldChecker : public SyclKernelFieldHandler {
}

bool handleStructType(ParmVarDecl *PD, QualType ParamTy) final {
if (this->SemaSYCLRef.getLangOpts().SYCLRTCMode) {
sommerlukas marked this conversation as resolved.
Show resolved Hide resolved
// When compiling in RTC mode, the restriction regarding forward
// declarations doesn't apply, as we don't need the integration header.
return isValid();
}
CXXRecordDecl *RD = ParamTy->getAsCXXRecordDecl();
// For free functions all struct/class kernel arguments are forward declared
// in integration header, that adds additional restrictions for kernel
Expand Down Expand Up @@ -6453,6 +6458,13 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) {
O << "} // namespace _V1\n";
O << "} // namespace sycl\n";

// The rest of this function only applies to free-function kernels. However,
// in RTC mode, we do not need integration header information for
// free-function kernels, so we can return early here.
if (this->S.getLangOpts().SYCLRTCMode) {
sommerlukas marked this conversation as resolved.
Show resolved Hide resolved
return;
}

unsigned ShimCounter = 1;
int FreeFunctionCount = 0;
for (const KernelDesc &K : KernelDescs) {
Expand Down
80 changes: 80 additions & 0 deletions clang/test/CodeGenSYCL/free_function_int_header_rtc_mode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// RUN: %clang_cc1 -fsycl-is-device -internal-isystem %S/Inputs -triple spir64-unknown-unknown -sycl-std=2020 -fsycl-rtc-mode -fsycl-int-header=%t.rtc.h %s
// RUN: FileCheck -input-file=%t.rtc.h --check-prefixes=CHECK,CHECK-RTC %s

// RUN: %clang_cc1 -fsycl-is-device -internal-isystem %S/Inputs -triple spir64-unknown-unknown -sycl-std=2020 -fno-sycl-rtc-mode -fsycl-int-header=%t.nortc.h %s
// RUN: FileCheck -input-file=%t.nortc.h --check-prefixes=CHECK,CHECK-NORTC %s

// This test checks that free-function kernel information is included or
// excluded from the integration header, depending on the '-fsycl-rtc-mode'
// flag.

#include "sycl.hpp"

[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 2)]]
void free_function_single(int* ptr, int start, int end){
for(int i = start; i < end; ++i){
ptr[i] = start + 66;
}
}

[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 2)]]
void free_function_nd_range(int* ptr, int start, int end){
for(int i = start; i < end; ++i){
ptr[i] = start + 66;
}
}

template<typename KernelName, typename KernelFunc>
__attribute__((sycl_kernel)) void kernel(const KernelFunc &kernelFunc){
kernelFunc();
}

int main(){
sycl::accessor<int, 1, sycl::access::mode::read_write> accessorA;
kernel<class Kernel_Function>(
[=]() {
accessorA.use();
});
return 0;
}


// CHECK: const char* const kernel_names[] = {
// CHECK-NEXT: "{{.*}}__sycl_kernel_free_function_singlePiii",
// CHECK-NEXT: "{{.*}}__sycl_kernel_free_function_nd_rangePiii",
// CHECK-NEXT: "{{.*}}Kernel_Function",


// CHECK: static constexpr const char* getName() { return "{{.*}}__sycl_kernel_free_function_singlePiii"; }
// CHECK: static constexpr const char* getName() { return "{{.*}}__sycl_kernel_free_function_nd_rangePiii"; }
// CHECK: static constexpr const char* getName() { return "{{.*}}Kernel_Function"; }

// CHECK-RTC-NOT: free_function_single_kernel
// CHECK-RTC-NOT: free_function_nd_range

// CHECK-NORTC: void free_function_single(int *ptr, int start, int end);
// CHECK-NORTC: static constexpr auto __sycl_shim[[#FIRST:]]()
// CHECK-NORTC-NEXT: return (void (*)(int *, int, int))free_function_single;

// CHECK-NORTC: struct ext::oneapi::experimental::is_kernel<__sycl_shim[[#FIRST]]()> {
// CHECK-NORTC-NEXT: static constexpr bool value = true;

// CHECK-NORTC: struct ext::oneapi::experimental::is_single_task_kernel<__sycl_shim[[#FIRST]]()> {
// CHECK-NORTC-NEXT: static constexpr bool value = true;


// CHECK-NORTC: void free_function_nd_range(int *ptr, int start, int end);
// CHECK-NORTC: static constexpr auto __sycl_shim[[#SECOND:]]() {
// CHECK-NORTC-NEXT: return (void (*)(int *, int, int))free_function_nd_range;

// CHECK-NORTC: struct ext::oneapi::experimental::is_kernel<__sycl_shim[[#SECOND]]()> {
// CHECK-NORTC-NEXT: static constexpr bool value = true;

// CHECK-NORTC: struct ext::oneapi::experimental::is_nd_range_kernel<__sycl_shim2(), 2> {
// CHECK-NORTC-NEXT: static constexpr bool value = true;

// CHECK-NORTC: kernel_id ext::oneapi::experimental::get_kernel_id<__sycl_shim[[#FIRST]]()>() {
// CHECK-NORTC-NEXT: return sycl::detail::get_kernel_id_impl(std::string_view{"{{.*}}__sycl_kernel_free_function_singlePiii"});

// CHECK-NORTC: kernel_id ext::oneapi::experimental::get_kernel_id<__sycl_shim[[#SECOND]]()>() {
// CHECK-NORTC-NEXT: return sycl::detail::get_kernel_id_impl(std::string_view{"{{.*}}__sycl_kernel_free_function_nd_rangePiii"});
Loading