[clang] e994e74 - [OpenCL] Add clang extension for non-portable kernel parameters.

Anastasia Stulova via cfe-commits cfe-commits at lists.llvm.org
Wed May 5 06:58:51 PDT 2021


Author: Anastasia Stulova
Date: 2021-05-05T14:58:23+01:00
New Revision: e994e74bca49831eb649e7c67955e9de7a1784b6

URL: https://github.com/llvm/llvm-project/commit/e994e74bca49831eb649e7c67955e9de7a1784b6
DIFF: https://github.com/llvm/llvm-project/commit/e994e74bca49831eb649e7c67955e9de7a1784b6.diff

LOG: [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

Added: 
    

Modified: 
    clang/docs/LanguageExtensions.rst
    clang/include/clang/Basic/OpenCLExtensions.def
    clang/lib/Basic/Targets/AMDGPU.h
    clang/lib/Basic/Targets/NVPTX.h
    clang/lib/Sema/SemaDecl.cpp
    clang/test/Misc/amdgcn.languageOptsOpenCL.cl
    clang/test/Misc/nvptx.languageOptsOpenCL.cl
    clang/test/Misc/r600.languageOptsOpenCL.cl
    clang/test/SemaOpenCLCXX/invalid-kernel.clcpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 5e5382879e0c8..bdb5b3adf39fb 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1813,6 +1813,54 @@ supporting the variadic arguments e.g. majority of CPU targets.
   #pragma OPENCL EXTENSION __cl_clang_variadic_functions : disable
   void bar(int a, ...); // error - variadic prototype is not allowed
 
+``__cl_clang_non_portable_kernel_param_types``
+---------------------------------------------
+
+With this extension it is possible to enable the use of some restricted types
+in kernel parameters specified in `C++ for OpenCL v1.0 s2.4
+<https://www.khronos.org/opencl/assets/CXX_for_OpenCL.html#kernel_function>`_.
+The restrictions can be relaxed using regular OpenCL extension pragma mechanism
+detailed in `the OpenCL Extension Specification, section 1.2
+<https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview>`_.
+
+This is not a conformant behavior and it can only be used when the
+kernel arguments are not accessed on the host side or the data layout/size
+between the host and device is known to be compatible.
+
+**Example of Use**:
+
+.. code-block:: c++
+
+  // Plain Old Data type.
+  struct Pod {
+    int a;
+    int b;
+  };
+
+  // Not POD type because of the constructor.
+  // Standard layout type because there is only one access control.
+  struct OnlySL {
+    int a;
+    int b;
+    NotPod() : a(0), b(0) {}
+  };
+
+  // Not standard layout type because of two 
diff erent access controls.
+  struct NotSL {
+    int a;
+  private:
+    int b;
+  }
+
+  kernel void kernel_main(
+    Pod a,
+  #pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
+    OnlySL b,
+    global NotSL *c,
+  #pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : disable
+    global OnlySL *d,
+  );
+
 Legacy 1.x atomics with generic address space
 ---------------------------------------------
 

diff  --git a/clang/include/clang/Basic/OpenCLExtensions.def b/clang/include/clang/Basic/OpenCLExtensions.def
index 5e2977f478f3a..a0f01a2af9c37 100644
--- a/clang/include/clang/Basic/OpenCLExtensions.def
+++ b/clang/include/clang/Basic/OpenCLExtensions.def
@@ -87,6 +87,7 @@ OPENCL_EXTENSION(cl_khr_subgroups, true, 200)
 OPENCL_EXTENSION(cl_clang_storage_class_specifiers, true, 100)
 OPENCL_EXTENSION(__cl_clang_function_pointers, true, 100)
 OPENCL_EXTENSION(__cl_clang_variadic_functions, true, 100)
+OPENCL_EXTENSION(__cl_clang_non_portable_kernel_param_types, true, 100)
 
 // AMD OpenCL extensions
 OPENCL_EXTENSION(cl_amd_media_ops, true, 100)

diff  --git a/clang/lib/Basic/Targets/AMDGPU.h b/clang/lib/Basic/Targets/AMDGPU.h
index 8ee0ca30d305d..b2d422ce0bbe9 100644
--- a/clang/lib/Basic/Targets/AMDGPU.h
+++ b/clang/lib/Basic/Targets/AMDGPU.h
@@ -287,6 +287,7 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
     Opts["cl_clang_storage_class_specifiers"] = true;
     Opts["__cl_clang_variadic_functions"] = true;
     Opts["__cl_clang_function_pointers"] = true;
+    Opts["__cl_clang_non_portable_kernel_param_types"] = true;
 
     bool IsAMDGCN = isAMDGCN(getTriple());
 

diff  --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h
index 9e80473df9e00..b7b0aae65819d 100644
--- a/clang/lib/Basic/Targets/NVPTX.h
+++ b/clang/lib/Basic/Targets/NVPTX.h
@@ -133,6 +133,7 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
     Opts["cl_clang_storage_class_specifiers"] = true;
     Opts["__cl_clang_function_pointers"] = true;
     Opts["__cl_clang_variadic_functions"] = true;
+    Opts["__cl_clang_non_portable_kernel_param_types"] = true;
 
     Opts["cl_khr_fp64"] = true;
     Opts["cl_khr_byte_addressable_store"] = true;

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 1abb692413b9d..c1aa638369383 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8662,6 +8662,9 @@ static bool isOpenCLSizeDependentType(ASTContext &C, QualType Ty) {
 }
 
 static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
+  if (PT->isDependentType())
+    return InvalidKernelParam;
+
   if (PT->isPointerType() || PT->isReferenceType()) {
     QualType PointeeType = PT->getPointeeType();
     if (PointeeType.getAddressSpace() == LangAS::opencl_generic ||
@@ -8684,8 +8687,11 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
     // Moreover the types used in parameters of the kernel functions must be:
     // Standard layout types for pointer parameters. The same applies to
     // reference if an implementation supports them in kernel parameters.
-    if (S.getLangOpts().OpenCLCPlusPlus && !PointeeType->isAtomicType() &&
-        !PointeeType->isVoidType() && !PointeeType->isStandardLayoutType())
+    if (S.getLangOpts().OpenCLCPlusPlus &&
+        !S.getOpenCLOptions().isAvailableOption(
+            "__cl_clang_non_portable_kernel_param_types", S.getLangOpts()) &&
+        !PointeeType->isAtomicType() && !PointeeType->isVoidType() &&
+        !PointeeType->isStandardLayoutType())
       return InvalidKernelParam;
 
     return PtrKernelParam;
@@ -8725,8 +8731,10 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
   // Moreover the types used in parameters of the kernel functions must be:
   // Trivial and standard-layout types C++17 [basic.types] (plain old data
   // types) for parameters passed by value;
-  if (S.getLangOpts().OpenCLCPlusPlus && !PT->isOpenCLSpecificType() &&
-      !PT.isPODType(S.Context))
+  if (S.getLangOpts().OpenCLCPlusPlus &&
+      !S.getOpenCLOptions().isAvailableOption(
+          "__cl_clang_non_portable_kernel_param_types", S.getLangOpts()) &&
+      !PT->isOpenCLSpecificType() && !PT.isPODType(S.Context))
     return InvalidKernelParam;
 
   if (PT->isRecordType())

diff  --git a/clang/test/Misc/amdgcn.languageOptsOpenCL.cl b/clang/test/Misc/amdgcn.languageOptsOpenCL.cl
index 1dd31029d7349..7fc4e7ea005e7 100644
--- a/clang/test/Misc/amdgcn.languageOptsOpenCL.cl
+++ b/clang/test/Misc/amdgcn.languageOptsOpenCL.cl
@@ -24,6 +24,11 @@
 #endif
 #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
 
+#ifndef __cl_clang_non_portable_kernel_param_types
+#error "Missing __cl_clang_non_portable_kernel_param_types define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
+
 #ifndef cl_khr_fp16
 #error "Missing cl_khr_fp16 define"
 #endif

diff  --git a/clang/test/Misc/nvptx.languageOptsOpenCL.cl b/clang/test/Misc/nvptx.languageOptsOpenCL.cl
index d547f4d2acfd3..6657c18f1eebe 100644
--- a/clang/test/Misc/nvptx.languageOptsOpenCL.cl
+++ b/clang/test/Misc/nvptx.languageOptsOpenCL.cl
@@ -28,6 +28,11 @@
 #endif
 #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
 
+#ifndef __cl_clang_non_portable_kernel_param_types
+#error "Missing __cl_clang_non_portable_kernel_param_types define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
+
 #ifdef cl_khr_fp16
 #error "Incorrect cl_khr_fp16 define"
 #endif

diff  --git a/clang/test/Misc/r600.languageOptsOpenCL.cl b/clang/test/Misc/r600.languageOptsOpenCL.cl
index 2c87370f9d5fe..80c628af03608 100644
--- a/clang/test/Misc/r600.languageOptsOpenCL.cl
+++ b/clang/test/Misc/r600.languageOptsOpenCL.cl
@@ -34,6 +34,11 @@
 #endif
 #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
 
+#ifndef __cl_clang_non_portable_kernel_param_types
+#error "Missing __cl_clang_non_portable_kernel_param_types define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
+
 #ifdef cl_khr_fp16
 #error "Incorrect cl_khr_fp16 define"
 #endif

diff  --git a/clang/test/SemaOpenCLCXX/invalid-kernel.clcpp b/clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
index 977d487928b65..9bd147364483c 100644
--- a/clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
+++ b/clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
@@ -1,4 +1,9 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown -DUNSAFEKERNELPARAMETER
+
+#ifdef UNSAFEKERNELPARAMETER
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
+#endif
 
 struct C {
   kernel void m(); //expected-error{{kernel functions cannot be class members}}
@@ -24,8 +29,10 @@ kernel void int_p_p(__global int *__global *in);
 kernel void int_p_r(__global int *__global &in);
 kernel void int_p_p_r(__global int *__global *__global &in);
 
-// expected-error at +1{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
 kernel void k_atomic_v(atomic_int in);
+#ifndef UNSAFEKERNELPARAMETER
+// expected-error at -2{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
+#endif
 kernel void k_atomic_p(__global atomic_int *in);
 kernel void k_atomic_r(__global atomic_int &in);
 
@@ -56,7 +63,10 @@ struct StandardLayout {
   StandardLayout(int a, int b) : a(a), b(b) {}
 };
 
-kernel void standard_v(StandardLayout in) {} //expected-error{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+kernel void standard_v(StandardLayout in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error at -2{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+#endif
 kernel void standard_p(__global StandardLayout *in) {}
 kernel void standard_p_p(__global StandardLayout *__global *in) {}
 kernel void standard_r(__global StandardLayout &in) {}
@@ -67,7 +77,19 @@ private:
   int b;
 };
 
-kernel void trivial_v(Trivial in) {} //expected-error{{'__private Trivial' cannot be used as the type of a kernel parameter}}
-kernel void trivial_p(__global Trivial *in) {} //expected-error{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
-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}}
-kernel void trivial_r(__global Trivial &in) {} //expected-error{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
+kernel void trivial_v(Trivial in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error at -2{{'__private Trivial' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_p(__global Trivial *in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error at -2{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_p_p(__global Trivial *__global *in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error at -2{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_r(__global Trivial &in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error at -2{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
+#endif


        


More information about the cfe-commits mailing list