Skip to content

Commit e994e74

Browse files
author
Anastasia Stulova
committed
[OpenCL] Add clang extension for non-portable kernel parameters.
Added __cl_clang_non_portable_kernel_param_types extension that allows using non-portable types as kernel parameters. This allows bypassing the portability guarantees from the restrictions specified in C++ for OpenCL v1.0 s2.4. Currently this only disables the restrictions related to the data layout. The programmer should ensure the compiler generates the same layout for host and device or otherwise the argument should only be accessed on the device side. This extension could be extended to other case (e.g. permitting size_t) if desired in the future. Patch by olestrohm (Ole Strohm)! https://reviews.llvm.org/D101168
1 parent f6ef409 commit e994e74

File tree

9 files changed

+107
-11
lines changed

9 files changed

+107
-11
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,6 +1813,54 @@ supporting the variadic arguments e.g. majority of CPU targets.
18131813
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : disable
18141814
void bar(int a, ...); // error - variadic prototype is not allowed
18151815
1816+
``__cl_clang_non_portable_kernel_param_types``
1817+
---------------------------------------------
1818+
1819+
With this extension it is possible to enable the use of some restricted types
1820+
in kernel parameters specified in `C++ for OpenCL v1.0 s2.4
1821+
<https://www.khronos.org/opencl/assets/CXX_for_OpenCL.html#kernel_function>`_.
1822+
The restrictions can be relaxed using regular OpenCL extension pragma mechanism
1823+
detailed in `the OpenCL Extension Specification, section 1.2
1824+
<https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview>`_.
1825+
1826+
This is not a conformant behavior and it can only be used when the
1827+
kernel arguments are not accessed on the host side or the data layout/size
1828+
between the host and device is known to be compatible.
1829+
1830+
**Example of Use**:
1831+
1832+
.. code-block:: c++
1833+
1834+
// Plain Old Data type.
1835+
struct Pod {
1836+
int a;
1837+
int b;
1838+
};
1839+
1840+
// Not POD type because of the constructor.
1841+
// Standard layout type because there is only one access control.
1842+
struct OnlySL {
1843+
int a;
1844+
int b;
1845+
NotPod() : a(0), b(0) {}
1846+
};
1847+
1848+
// Not standard layout type because of two different access controls.
1849+
struct NotSL {
1850+
int a;
1851+
private:
1852+
int b;
1853+
}
1854+
1855+
kernel void kernel_main(
1856+
Pod a,
1857+
#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
1858+
OnlySL b,
1859+
global NotSL *c,
1860+
#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : disable
1861+
global OnlySL *d,
1862+
);
1863+
18161864
Legacy 1.x atomics with generic address space
18171865
---------------------------------------------
18181866

clang/include/clang/Basic/OpenCLExtensions.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ OPENCL_EXTENSION(cl_khr_subgroups, true, 200)
8787
OPENCL_EXTENSION(cl_clang_storage_class_specifiers, true, 100)
8888
OPENCL_EXTENSION(__cl_clang_function_pointers, true, 100)
8989
OPENCL_EXTENSION(__cl_clang_variadic_functions, true, 100)
90+
OPENCL_EXTENSION(__cl_clang_non_portable_kernel_param_types, true, 100)
9091

9192
// AMD OpenCL extensions
9293
OPENCL_EXTENSION(cl_amd_media_ops, true, 100)

clang/lib/Basic/Targets/AMDGPU.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
287287
Opts["cl_clang_storage_class_specifiers"] = true;
288288
Opts["__cl_clang_variadic_functions"] = true;
289289
Opts["__cl_clang_function_pointers"] = true;
290+
Opts["__cl_clang_non_portable_kernel_param_types"] = true;
290291

291292
bool IsAMDGCN = isAMDGCN(getTriple());
292293

clang/lib/Basic/Targets/NVPTX.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
133133
Opts["cl_clang_storage_class_specifiers"] = true;
134134
Opts["__cl_clang_function_pointers"] = true;
135135
Opts["__cl_clang_variadic_functions"] = true;
136+
Opts["__cl_clang_non_portable_kernel_param_types"] = true;
136137

137138
Opts["cl_khr_fp64"] = true;
138139
Opts["cl_khr_byte_addressable_store"] = true;

clang/lib/Sema/SemaDecl.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8662,6 +8662,9 @@ static bool isOpenCLSizeDependentType(ASTContext &C, QualType Ty) {
86628662
}
86638663

86648664
static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
8665+
if (PT->isDependentType())
8666+
return InvalidKernelParam;
8667+
86658668
if (PT->isPointerType() || PT->isReferenceType()) {
86668669
QualType PointeeType = PT->getPointeeType();
86678670
if (PointeeType.getAddressSpace() == LangAS::opencl_generic ||
@@ -8684,8 +8687,11 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
86848687
// Moreover the types used in parameters of the kernel functions must be:
86858688
// Standard layout types for pointer parameters. The same applies to
86868689
// reference if an implementation supports them in kernel parameters.
8687-
if (S.getLangOpts().OpenCLCPlusPlus && !PointeeType->isAtomicType() &&
8688-
!PointeeType->isVoidType() && !PointeeType->isStandardLayoutType())
8690+
if (S.getLangOpts().OpenCLCPlusPlus &&
8691+
!S.getOpenCLOptions().isAvailableOption(
8692+
"__cl_clang_non_portable_kernel_param_types", S.getLangOpts()) &&
8693+
!PointeeType->isAtomicType() && !PointeeType->isVoidType() &&
8694+
!PointeeType->isStandardLayoutType())
86898695
return InvalidKernelParam;
86908696

86918697
return PtrKernelParam;
@@ -8725,8 +8731,10 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
87258731
// Moreover the types used in parameters of the kernel functions must be:
87268732
// Trivial and standard-layout types C++17 [basic.types] (plain old data
87278733
// types) for parameters passed by value;
8728-
if (S.getLangOpts().OpenCLCPlusPlus && !PT->isOpenCLSpecificType() &&
8729-
!PT.isPODType(S.Context))
8734+
if (S.getLangOpts().OpenCLCPlusPlus &&
8735+
!S.getOpenCLOptions().isAvailableOption(
8736+
"__cl_clang_non_portable_kernel_param_types", S.getLangOpts()) &&
8737+
!PT->isOpenCLSpecificType() && !PT.isPODType(S.Context))
87308738
return InvalidKernelParam;
87318739

87328740
if (PT->isRecordType())

clang/test/Misc/amdgcn.languageOptsOpenCL.cl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
#endif
2525
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
2626

27+
#ifndef __cl_clang_non_portable_kernel_param_types
28+
#error "Missing __cl_clang_non_portable_kernel_param_types define"
29+
#endif
30+
#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
31+
2732
#ifndef cl_khr_fp16
2833
#error "Missing cl_khr_fp16 define"
2934
#endif

clang/test/Misc/nvptx.languageOptsOpenCL.cl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@
2828
#endif
2929
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
3030

31+
#ifndef __cl_clang_non_portable_kernel_param_types
32+
#error "Missing __cl_clang_non_portable_kernel_param_types define"
33+
#endif
34+
#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
35+
3136
#ifdef cl_khr_fp16
3237
#error "Incorrect cl_khr_fp16 define"
3338
#endif

clang/test/Misc/r600.languageOptsOpenCL.cl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@
3434
#endif
3535
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
3636

37+
#ifndef __cl_clang_non_portable_kernel_param_types
38+
#error "Missing __cl_clang_non_portable_kernel_param_types define"
39+
#endif
40+
#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
41+
3742
#ifdef cl_khr_fp16
3843
#error "Incorrect cl_khr_fp16 define"
3944
#endif

clang/test/SemaOpenCLCXX/invalid-kernel.clcpp

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
1+
// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown
2+
// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown -DUNSAFEKERNELPARAMETER
3+
4+
#ifdef UNSAFEKERNELPARAMETER
5+
#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
6+
#endif
27

38
struct C {
49
kernel void m(); //expected-error{{kernel functions cannot be class members}}
@@ -24,8 +29,10 @@ kernel void int_p_p(__global int *__global *in);
2429
kernel void int_p_r(__global int *__global &in);
2530
kernel void int_p_p_r(__global int *__global *__global &in);
2631

27-
// expected-error@+1{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
2832
kernel void k_atomic_v(atomic_int in);
33+
#ifndef UNSAFEKERNELPARAMETER
34+
// expected-error@-2{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
35+
#endif
2936
kernel void k_atomic_p(__global atomic_int *in);
3037
kernel void k_atomic_r(__global atomic_int &in);
3138

@@ -56,7 +63,10 @@ struct StandardLayout {
5663
StandardLayout(int a, int b) : a(a), b(b) {}
5764
};
5865

59-
kernel void standard_v(StandardLayout in) {} //expected-error{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
66+
kernel void standard_v(StandardLayout in) {}
67+
#ifndef UNSAFEKERNELPARAMETER
68+
//expected-error@-2{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
69+
#endif
6070
kernel void standard_p(__global StandardLayout *in) {}
6171
kernel void standard_p_p(__global StandardLayout *__global *in) {}
6272
kernel void standard_r(__global StandardLayout &in) {}
@@ -67,7 +77,19 @@ private:
6777
int b;
6878
};
6979

70-
kernel void trivial_v(Trivial in) {} //expected-error{{'__private Trivial' cannot be used as the type of a kernel parameter}}
71-
kernel void trivial_p(__global Trivial *in) {} //expected-error{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
72-
kernel void trivial_p_p(__global Trivial *__global *in) {} //expected-error{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
73-
kernel void trivial_r(__global Trivial &in) {} //expected-error{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
80+
kernel void trivial_v(Trivial in) {}
81+
#ifndef UNSAFEKERNELPARAMETER
82+
//expected-error@-2{{'__private Trivial' cannot be used as the type of a kernel parameter}}
83+
#endif
84+
kernel void trivial_p(__global Trivial *in) {}
85+
#ifndef UNSAFEKERNELPARAMETER
86+
//expected-error@-2{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
87+
#endif
88+
kernel void trivial_p_p(__global Trivial *__global *in) {}
89+
#ifndef UNSAFEKERNELPARAMETER
90+
//expected-error@-2{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
91+
#endif
92+
kernel void trivial_r(__global Trivial &in) {}
93+
#ifndef UNSAFEKERNELPARAMETER
94+
//expected-error@-2{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
95+
#endif

0 commit comments

Comments
 (0)