Skip to content

Commit 41676bc

Browse files
[SYCL] Treat only SYCL kernels as entry points for FPGA target (#4693)
Introduced new `sycl-post-link` option `-emit-only-kernels-as-entry-points`, which allows to stop treating `SYCL_EXTERNAL` functions as entry points. Updated clang driver to pass the new option for `spir64_fpga` target, because on FPGA, there are no use cases for preserving `SYCL_EXTERNAL` functions as separate entries in device images if they are not referenced and it only causes compilation slowdowns due to increased amount of device code.
1 parent e9b8f43 commit 41676bc

File tree

9 files changed

+147
-65
lines changed

9 files changed

+147
-65
lines changed

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8916,6 +8916,13 @@ void SYCLPostLink::ConstructJob(Compilation &C, const JobAction &JA,
89168916
// auto is the default split mode
89178917
addArgs(CmdArgs, TCArgs, {"-split=auto"});
89188918
}
8919+
8920+
// On FPGA target we don't need non-kernel functions as entry points, because
8921+
// it only increases amount of code for device compiler to handle, without any
8922+
// actual benefits.
8923+
if (getToolChain().getTriple().getArchName() == "spir64_fpga")
8924+
addArgs(CmdArgs, TCArgs, {"-emit-only-kernels-as-entry-points"});
8925+
89198926
// OPT_fsycl_device_code_split is not checked as it is an alias to
89208927
// -fsycl-device-code-split=auto
89218928

clang/test/Driver/sycl-offload-intelfpga.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,24 @@
2929
// CHK-RANGE-ROUNDING: clang{{.*}} "-fsycl-is-device"{{.*}} "-fsycl-disable-range-rounding"
3030
// CHK-RANGE-ROUNDING: clang{{.*}} "-fsycl-disable-range-rounding"{{.*}} "-fsycl-is-host"
3131

32+
/// FPGA target implies -emit-only-kernels-as-entry-points in sycl-post-link
33+
// RUN: %clangxx -### -target x86_64-unknown-linux-gnu -fsycl -fintelfpga %s 2>&1 \
34+
// RUN: | FileCheck -check-prefix=CHK-NON-KERNEL-ENTRY-POINTS %s
35+
// RUN: %clangxx -### -target x86_64-unknown-linux-gnu -fsycl -fsycl-targets=spir64_fpga-unknown-unknown %s 2>&1 \
36+
// RUN: | FileCheck -check-prefix=CHK-NON-KERNEL-ENTRY-POINTS %s
37+
// CHK-NON-KERNEL-ENTRY-POINTS: sycl-post-link{{.*}} "-emit-only-kernels-as-entry-points"
38+
39+
/// Non-FPGA targets should not imply -emit-only-kernels-as-entry-points in sycl-post-link
40+
// RUN: %clang -### -fsycl -fsycl-targets=spir64_fpga,spir64_gen %s 2>&1 \
41+
// RUN: | FileCheck %s --check-prefix=CHK-NON-KERNEL-ENTRY-POINTS-NEG-1
42+
// CHK-NON-KERNEL-ENTRY-POINTS-NEG-1: clang{{.*}} "-triple" "spir64_fpga-unknown-unknown"
43+
// CHK-NON-KERNEL-ENTRY-POINTS-NEG-1: sycl-post-link{{.*}} "-emit-only-kernels-as-entry-points"
44+
// CHK-NON-KERNEL-ENTRY-POINTS-NEG-1: clang{{.*}} "-triple" "spir64_gen-unknown-unknown"
45+
// CHK-NON-KERNEL-ENTRY-POINTS-NEG-1: sycl-post-link
46+
// CHK-NON-KERNEL-ENTRY-POINTS-NEG-1-NOT: "-emit-only-kernels-as-entry-points"
47+
// RUN: %clang -### -fsycl %s 2>&1 | FileCheck %s --check-prefix=CHK-NON-KERNEL-ENTRY-POINTS-NEG-2
48+
// CHK-NON-KERNEL-ENTRY-POINTS-NEG-2-NOT: "-emit-only-kernels-as-entry-points"
49+
3250
/// -fsycl-disable-range-rounding is applied to all compilations if fpga is used
3351
// RUN: %clangxx -### -target x86_64-unknown-linux-gnu -fsycl -fsycl-targets=spir64_fpga-unknown-unknown,spir64_gen-unknown-unknown %s 2>&1 \
3452
// RUN: | FileCheck -check-prefix=CHK-RANGE-ROUNDING-MULTI %s

llvm/test/tools/sycl-post-link/spec-constants/spec_const_and_split.ll

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,25 @@
1919

2020
declare dso_local spir_func zeroext i1 @_Z33__sycl_getScalarSpecConstantValueIbET_PKc(i8 addrspace(4)*)
2121

22-
define dso_local spir_kernel void @KERNEL_AAA() #0 {
22+
define dso_local spir_kernel void @KERNEL_AAA() {
2323
%1 = call spir_func zeroext i1 @_Z33__sycl_getScalarSpecConstantValueIbET_PKc(i8 addrspace(4)* addrspacecast (i8* getelementptr inbounds ([10 x i8], [10 x i8]* @SCSymID, i64 0, i64 0) to i8 addrspace(4)*))
2424
; CHECK-IR0: %{{[0-9]+}} = call i1 @_Z20__spirv_SpecConstantib(i32 1, i1 false)
2525
%2 = call spir_func zeroext i1 @_Z33__sycl_getScalarSpecConstantValueIbET_PKc(i8 addrspace(4)* addrspacecast (i8* getelementptr inbounds ([11 x i8], [11 x i8]* @SCSymID2, i64 0, i64 0) to i8 addrspace(4)*))
2626
; CHECK-IR0: %{{[0-9]+}} = call i1 @_Z20__spirv_SpecConstantib(i32 0, i1 false)
2727
ret void
2828
}
2929

30-
define dso_local spir_kernel void @KERNEL_BBB() #0 {
30+
define dso_local spir_kernel void @KERNEL_BBB() {
3131
%1 = call spir_func zeroext i1 @_Z33__sycl_getScalarSpecConstantValueIbET_PKc(i8 addrspace(4)* addrspacecast (i8* getelementptr inbounds ([10 x i8], [10 x i8]* @SCSymID, i64 0, i64 0) to i8 addrspace(4)*))
3232
; CHECK-IR1: %{{[0-9]+}} = call i1 @_Z20__spirv_SpecConstantib(i32 0, i1 false)
3333
ret void
3434
}
3535

36-
define dso_local spir_kernel void @KERNEL_CCC() #0 {
36+
define dso_local spir_kernel void @KERNEL_CCC() {
3737
; CHECK-IR2: define{{.*}}spir_kernel void @KERNEL_CCC
3838
ret void
3939
}
4040

41-
attributes #0 = { "sycl-module-id"="a.cpp" }
42-
4341
; CHECK-IR0: !sycl.specialization-constants = !{![[#MD0:]], ![[#MD1:]]}
4442
; CHECK-IR0: ![[#MD0:]] = !{!"SpecConst2", i32 0, i32 0, i32 1}
4543
; CHECK-IR0: ![[#MD1:]] = !{!"SpecConst", i32 1, i32 0, i32 1}

llvm/test/tools/sycl-post-link/sycl-external-funcs/split-global.ll

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
; This test checks handling of unreferenced functions with sycl-module-id
2+
; attribute with splitting in global mode.
3+
14
; RUN: sycl-post-link -ir-output-only -split=auto -S %s -o %t.ll
2-
; RUN: FileCheck %s -input-file=%t.ll
5+
; RUN: FileCheck %s -input-file=%t.ll --check-prefix=CHECK-ALL
6+
7+
; RUN: sycl-post-link -ir-output-only -emit-only-kernels-as-entry-points -split=auto -S %s -o %t.ll
8+
; RUN: FileCheck %s -input-file=%t.ll --check-prefix=CHECK-KERNEL-ONLY --implicit-check-not @externalDeviceFunc
39

4-
; This test checks that unreferenced functions with sycl-module-id
5-
; attribute are not dropped from the module after splitting
6-
; in global mode.
710

811
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
912
target triple = "spir64-unknown-linux"
@@ -18,5 +21,7 @@ define dso_local spir_kernel void @kernel1() #0 {
1821

1922
attributes #0 = { "sycl-module-id"="a.cpp" }
2023

21-
; CHECK-DAG: define dso_local spir_func void @externalDeviceFunc()
22-
; CHECK-DAG: define dso_local spir_kernel void @kernel1()
24+
; CHECK-ALL-DAG: define dso_local spir_func void @externalDeviceFunc()
25+
; CHECK-ALL-DAG: define dso_local spir_kernel void @kernel1()
26+
;
27+
; CHECK-KERNEL-ONLY: define dso_local spir_kernel void @kernel1()
Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
1+
; This test checks handling of unreferenced functions with sycl-module-id
2+
; attribute with splitting in per-kernel mode.
3+
14
; RUN: sycl-post-link -split=kernel -symbols -S %s -o %t.table
5+
; RUN: FileCheck %s -input-file=%t_0.ll --check-prefixes CHECK-IR0
6+
; RUN: FileCheck %s -input-file=%t_1.ll --check-prefixes CHECK-IR1
7+
; RUN: FileCheck %s -input-file=%t_2.ll --check-prefixes CHECK-IR2
8+
; RUN: FileCheck %s -input-file=%t_0.sym --check-prefixes CHECK-SYM0
9+
; RUN: FileCheck %s -input-file=%t_1.sym --check-prefixes CHECK-SYM1
10+
; RUN: FileCheck %s -input-file=%t_2.sym --check-prefixes CHECK-SYM2
11+
12+
; RUN: sycl-post-link -split=kernel -emit-only-kernels-as-entry-points -symbols -S %s -o %t.table
213
; RUN: FileCheck %s -input-file=%t_0.ll --check-prefixes CHECK-IR1
314
; RUN: FileCheck %s -input-file=%t_1.ll --check-prefixes CHECK-IR2
415
; RUN: FileCheck %s -input-file=%t_0.sym --check-prefixes CHECK-SYM1
516
; RUN: FileCheck %s -input-file=%t_1.sym --check-prefixes CHECK-SYM2
17+
; RUN: FileCheck %s -input-file=%t.table --check-prefixes CHECK-TABLE
618

7-
; This test checks that unreferenced functions with sycl-module-id
8-
; attribute are not dropped from the module after splitting
9-
; in per-kernel mode.
19+
; CHECK-TABLE: [Code|Properties|Symbols]
20+
; CHECK-TABLE-NEXT: {{.*}}_0.ll|{{.*}}_0.prop|{{.*}}_0.sym
21+
; CHECK-TABLE-NEXT: {{.*}}_1.ll|{{.*}}_1.prop|{{.*}}_1.sym
22+
; CHECK-TABLE-EMPTY:
1023

1124
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
1225
target triple = "spir64-unknown-linux"
@@ -19,10 +32,19 @@ define dso_local spir_kernel void @kernel1() #0 {
1932
ret void
2033
}
2134

35+
define dso_local spir_kernel void @kernel2() #0 {
36+
ret void
37+
}
38+
2239
attributes #0 = { "sycl-module-id"="a.cpp" }
2340

24-
; CHECK-IR1: define dso_local spir_func void @externalDeviceFunc()
25-
; CHECK-IR2: define dso_local spir_kernel void @kernel1()
41+
; CHECK-IR0: define dso_local spir_func void @externalDeviceFunc()
42+
; CHECK-IR1: define dso_local spir_kernel void @kernel1()
43+
; CHECK-IR2: define dso_local spir_kernel void @kernel2()
2644

27-
; CHECK-SYM1: externalDeviceFunc
28-
; CHECK-SYM2: kernel1
45+
; CHECK-SYM0: externalDeviceFunc
46+
; CHECK-SYM0-EMPTY:
47+
; CHECK-SYM1: kernel1
48+
; CHECK-SYM1-EMPTY:
49+
; CHECK-SYM2: kernel2
50+
; CHECK-SYM2-EMPTY:

llvm/test/tools/sycl-post-link/sycl-external-funcs/split-per-source1.ll

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
1+
; This test checks handling of unreferenced functions with sycl-module-id
2+
; attribute with splitting in per-source mode.
3+
14
; RUN: sycl-post-link -split=source -symbols -S %s -o %t.table
25
; RUN: FileCheck %s -input-file=%t_0.ll --check-prefixes CHECK-IR1
36
; RUN: FileCheck %s -input-file=%t_1.ll --check-prefixes CHECK-IR2
47
; RUN: FileCheck %s -input-file=%t_0.sym --check-prefixes CHECK-SYM1
58
; RUN: FileCheck %s -input-file=%t_1.sym --check-prefixes CHECK-SYM2
69

7-
; This test checks that unreferenced functions with sycl-module-id
8-
; attribute are not dropped from the module after splitting
9-
; in per-source mode.
10+
; RUN: sycl-post-link -split=source -emit-only-kernels-as-entry-points -symbols -S %s -o %t.table
11+
; RUN: FileCheck %s -input-file=%t_0.sym --check-prefixes CHECK-SYM2
12+
; RUN: FileCheck %s -input-file=%t.table --check-prefixes CHECK-TABLE
13+
; CHECK-TABLE: [Code|Properties|Symbols]
14+
; CHECK-TABLE-NEXT: {{.*}}.ll|{{.*}}_0.prop|{{.*}}_0.sym
15+
; CHECK-TABLE-EMPTY:
16+
1017

1118
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
1219
target triple = "spir64-unknown-linux"
@@ -26,4 +33,6 @@ attributes #1 = { "sycl-module-id"="b.cpp" }
2633
; CHECK-IR2: define dso_local spir_kernel void @kernel1()
2734

2835
; CHECK-SYM1: externalDeviceFunc
36+
; CHECK-SYM1-EMPTY:
2937
; CHECK-SYM2: kernel1
38+
; CHECK-SYM2-EMPTY:

llvm/test/tools/sycl-post-link/sycl-external-funcs/split-per-source2.ll

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1+
; This test checks handling of referenced SYCL_EXTERNAL functions with
2+
; sycl-module-id attribute with splitting in per-source mode.
3+
14
; RUN: sycl-post-link -split=source -symbols -S %s -o %t.table
25
; RUN: FileCheck %s -input-file=%t_0.ll --check-prefixes CHECK-IR1
36
; RUN: FileCheck %s -input-file=%t_1.ll --check-prefixes CHECK-IR2
47
; RUN: FileCheck %s -input-file=%t_0.sym --check-prefixes CHECK-SYM1
58
; RUN: FileCheck %s -input-file=%t_1.sym --check-prefixes CHECK-SYM2
69

7-
; This test checks that the definition of function externalDeviceFunc is
8-
; present in both resulting modules when per-source split is requested.
10+
; RUN: sycl-post-link -split=source -emit-only-kernels-as-entry-points -symbols -S %s -o %t.table
11+
; RUN: FileCheck %s -input-file=%t_0.sym --check-prefixes CHECK-SYM2
12+
; RUN: FileCheck %s -input-file=%t.table --check-prefixes CHECK-TABLE
13+
; CHECK-TABLE: [Code|Properties|Symbols]
14+
; CHECK-TABLE-NEXT: {{.*}}.ll|{{.*}}_0.prop|{{.*}}_0.sym
15+
; CHECK-TABLE-EMPTY:
16+
917

1018
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
1119
target triple = "spir64-unknown-linux"
@@ -27,4 +35,6 @@ attributes #1 = { "sycl-module-id"="b.cpp" }
2735
; CHECK-IR2: define dso_local spir_kernel void @kernel1()
2836

2937
; CHECK-SYM1: externalDeviceFunc
38+
; CHECK-SYM1-EMPTY:
3039
; CHECK-SYM2: kernel1
40+
; CHECK-SYM2-EMPTY:

llvm/test/tools/sycl-post-link/sym_but_no_split.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,20 @@
66
; RUN: FileCheck %s -input-file=%t.files.table --check-prefixes CHECK-TABLE
77
; RUN: FileCheck %s -input-file=%t.files_0.sym --match-full-lines --check-prefixes CHECK-SYM
88

9-
define dso_local spir_kernel void @KERNEL_AAA() #0 {
9+
define dso_local spir_kernel void @KERNEL_AAA() {
1010
; CHECK-SYM-NOT: {{[a-zA-Z0-9._@]+}}
1111
; CHECK-SYM: KERNEL_AAA
1212
entry:
1313
ret void
1414
}
1515

16-
define dso_local spir_kernel void @KERNEL_BBB() #0 {
16+
define dso_local spir_kernel void @KERNEL_BBB() {
1717
; CHECK-SYM-NEXT: KERNEL_BBB
1818
; CHECK-SYM-EMPTY:
1919
entry:
2020
ret void
2121
}
2222

23-
attributes #0 = { "sycl-module-id"="a.cpp" }
24-
2523
; CHECK-TABLE: [Code|Properties|Symbols]
2624
; CHECK-TABLE-NEXT: {{.*}}files_0.sym
2725
; CHECK-TABLE-EMPTY:

llvm/tools/sycl-post-link/sycl-post-link.cpp

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,12 @@ static cl::opt<bool> EmitExportedSymbols{"emit-exported-symbols",
175175
cl::desc("emit exported symbols"),
176176
cl::cat(PostLinkCat)};
177177

178+
static cl::opt<bool> EmitOnlyKernelsAsEntryPoints{
179+
"emit-only-kernels-as-entry-points",
180+
cl::desc("Consider only sycl_kernel functions as entry points for "
181+
"device code split"),
182+
cl::cat(PostLinkCat), cl::init(false)};
183+
178184
struct ImagePropSaveInfo {
179185
bool NeedDeviceLibReqMask;
180186
bool DoSpecConst;
@@ -261,6 +267,22 @@ static bool funcIsSpirvSyclBuiltin(StringRef FName) {
261267
return FName.startswith("__spirv_") || FName.startswith("__sycl_");
262268
}
263269

270+
static bool isEntryPoint(const Function &F) {
271+
// Kernels are always considered to be entry points
272+
if (CallingConv::SPIR_KERNEL == F.getCallingConv())
273+
return true;
274+
275+
if (!EmitOnlyKernelsAsEntryPoints) {
276+
// If not disabled, SYCL_EXTERNAL functions with sycl-module-id attribute
277+
// are also considered as entry points (except __spirv_* and __sycl_*
278+
// functions)
279+
return F.hasFnAttribute(ATTR_SYCL_MODULE_ID) &&
280+
!funcIsSpirvSyclBuiltin(F.getName());
281+
}
282+
283+
return false;
284+
}
285+
264286
// This function decides how kernels of the input module M will be distributed
265287
// ("split") into multiple modules based on the command options and IR
266288
// attributes. The decision is recorded in the output map parameter
@@ -271,37 +293,34 @@ static void collectKernelModuleMap(
271293
Module &M, std::map<StringRef, std::vector<Function *>> &ResKernelModuleMap,
272294
KernelMapEntryScope EntryScope) {
273295

274-
// Process module entry points: kernels and SYCL_EXTERNAL functions.
275-
// Only they have sycl-module-id attribute, so any other unrefenced
276-
// functions are dropped. SPIRV and SYCL builtin functions are not
277-
// considered as module entry points.
296+
// Only process module entry points:
278297
for (auto &F : M.functions()) {
279-
if (F.hasFnAttribute(ATTR_SYCL_MODULE_ID) &&
280-
!funcIsSpirvSyclBuiltin(F.getName())) {
281-
switch (EntryScope) {
282-
case Scope_PerKernel:
283-
ResKernelModuleMap[F.getName()].push_back(&F);
284-
break;
285-
case Scope_PerModule: {
286-
Attribute Id = F.getFnAttribute(ATTR_SYCL_MODULE_ID);
287-
StringRef Val = Id.getValueAsString();
288-
ResKernelModuleMap[Val].push_back(&F);
289-
break;
290-
}
291-
case Scope_Global:
292-
// the map key is not significant here
293-
ResKernelModuleMap[GLOBAL_SCOPE_NAME].push_back(&F);
294-
break;
295-
}
296-
} else if (EntryScope == Scope_PerModule &&
297-
F.getCallingConv() == CallingConv::SPIR_KERNEL) {
298-
// TODO It may make sense to group all kernels w/o the attribute into
299-
// a separate module rather than issuing an error. Should probably be
300-
// controlled by an option.
301-
// Functions with spir_func calling convention are allowed to not have
302-
// a sycl-module-id attribute.
303-
error("no '" + Twine(ATTR_SYCL_MODULE_ID) + "' attribute in kernel '" +
304-
F.getName() + "', per-module split not possible");
298+
if (!isEntryPoint(F))
299+
continue;
300+
301+
switch (EntryScope) {
302+
case Scope_PerKernel:
303+
ResKernelModuleMap[F.getName()].push_back(&F);
304+
break;
305+
case Scope_PerModule: {
306+
if (!F.hasFnAttribute(ATTR_SYCL_MODULE_ID))
307+
// TODO It may make sense to group all kernels w/o the attribute into
308+
// a separate module rather than issuing an error. Should probably be
309+
// controlled by an option.
310+
// Functions with spir_func calling convention are allowed to not have
311+
// a sycl-module-id attribute.
312+
error("no '" + Twine(ATTR_SYCL_MODULE_ID) + "' attribute in kernel '" +
313+
F.getName() + "', per-module split not possible");
314+
315+
Attribute Id = F.getFnAttribute(ATTR_SYCL_MODULE_ID);
316+
StringRef Val = Id.getValueAsString();
317+
ResKernelModuleMap[Val].push_back(&F);
318+
break;
319+
}
320+
case Scope_Global:
321+
// the map key is not significant here
322+
ResKernelModuleMap["<GLOBAL>"].push_back(&F);
323+
break;
305324
}
306325
}
307326
}
@@ -872,13 +891,9 @@ static ModulePair splitSyclEsimd(std::unique_ptr<Module> M) {
872891
std::vector<Function *> SyclFunctions;
873892
std::vector<Function *> EsimdFunctions;
874893
// Collect information about the SYCL and ESIMD functions in the module.
875-
// Process module entry points: kernels and SYCL_EXTERNAL functions.
876-
// Only they have sycl-module-id attribute, so any other unrefenced
877-
// functions are dropped. SPIRV and SYCL builtin functions are not
878-
// considered as module entry points.
894+
// Only process module entry points.
879895
for (auto &F : M->functions()) {
880-
if (F.hasFnAttribute(ATTR_SYCL_MODULE_ID) &&
881-
!funcIsSpirvSyclBuiltin(F.getName())) {
896+
if (isEntryPoint(F)) {
882897
if (F.getMetadata("sycl_explicit_simd"))
883898
EsimdFunctions.push_back(&F);
884899
else
@@ -950,8 +965,8 @@ int main(int argc, char **argv) {
950965
"- SYCL and ESIMD kernels can be split into separate modules with\n"
951966
" '-split-esimd' option. The option has no effect when there is only\n"
952967
" one type of kernels in the input module. Functions unreachable from\n"
953-
" any kernel or SYCL_EXTERNAL function are dropped from the resulting\n"
954-
" module(s)."
968+
" any entry point (kernels and SYCL_EXTERNAL functions) are\n"
969+
" dropped from the resulting module(s).\n"
955970
"- Module splitter to split a big input module into smaller ones.\n"
956971
" Groups kernels using function attribute 'sycl-module-id', i.e.\n"
957972
" kernels with the same values of the 'sycl-module-id' attribute will\n"

0 commit comments

Comments
 (0)