From f15b9461daa267969fde37ec43ba55971d371cc0 Mon Sep 17 00:00:00 2001 From: Sven van Haastregt Date: Thu, 19 Sep 2019 13:41:51 +0000 Subject: [OpenCL] Add version handling and add vector ld/st builtins Allow setting a MinVersion, stating from which OpenCL version a builtin function is available, and a MaxVersion, stating from which OpenCL version a builtin function should not be available anymore. Guard some definitions of the "work-item" builtin functions according to the OpenCL versions from which they are available. Add the "vector data load and store" builtin functions (e.g. vload/vstore), whose signatures differ before and after OpenCL 2.0 in the pointer argument address spaces. Patch by Pierre Gondois and Sven van Haastregt. Differential Revision: https://reviews.llvm.org/D63504 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@372321 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/OpenCLBuiltins.td | 161 ++++++++++++++++++++++++--- lib/Sema/SemaLookup.cpp | 7 ++ test/SemaOpenCL/fdeclare-opencl-builtins.cl | 50 +++++++++ utils/TableGen/ClangOpenCLBuiltinEmitter.cpp | 22 ++-- 4 files changed, 217 insertions(+), 23 deletions(-) diff --git a/lib/Sema/OpenCLBuiltins.td b/lib/Sema/OpenCLBuiltins.td index 8305102f96..20b574e0a5 100644 --- a/lib/Sema/OpenCLBuiltins.td +++ b/lib/Sema/OpenCLBuiltins.td @@ -20,12 +20,13 @@ //===----------------------------------------------------------------------===// // Versions of OpenCL class Version { - int Version = _Version; + int ID = _Version; } -def CL10: Version<100>; -def CL11: Version<110>; -def CL12: Version<120>; -def CL20: Version<200>; +def CLAll : Version< 0>; +def CL10 : Version<100>; +def CL11 : Version<110>; +def CL12 : Version<120>; +def CL20 : Version<200>; // Address spaces // Pointer types need to be assigned an address space. @@ -191,8 +192,13 @@ class Builtin _Signature> { list Signature = _Signature; // OpenCL Extension to which the function belongs (cl_khr_subgroups, ...) string Extension = ""; - // OpenCL Version to which the function belongs (CL10, ...) - Version Version = CL10; + // Version of OpenCL from which the function is available (e.g.: CL10). + // MinVersion is inclusive. + Version MinVersion = CL10; + // Version of OpenCL from which the function is not supported anymore. + // MaxVersion is exclusive. + // CLAll makes the function available for all versions. + Version MaxVersion = CLAll; } //===----------------------------------------------------------------------===// @@ -312,6 +318,137 @@ foreach RType = [Float, Double, Half, Char, UChar, Short, } } +//-------------------------------------------------------------------- +// OpenCL v1.1 s6.11.1, v1.2 s6.12.1, v2.0 s6.13.1 - Work-item Functions +// --- Table 7 --- +def : Builtin<"get_work_dim", [UInt]>; +foreach name = ["get_global_size", "get_global_id", "get_local_size", + "get_local_id", "get_num_groups", "get_group_id", + "get_global_offset"] in { + def : Builtin; +} + +let MinVersion = CL20 in { + def : Builtin<"get_enqueued_local_size", [Size, UInt]>; + foreach name = ["get_global_linear_id", "get_local_linear_id"] in { + def : Builtin; + } +} + +//-------------------------------------------------------------------- +// OpenCL v1.1 s6.11.7, v1.2 s6.12.7, v2.0 s6.13.7 - Vector Data Load and Store Functions +// OpenCL Extension v1.1 s9.3.6 and s9.6.6, v1.2 s9.5.6, v2.0 s9.4.6, v2.0 s5.1.6 and 6.1.6 - Vector Data Load and Store Functions +// --- Table 15 --- +// Variants for OpenCL versions below 2.0, using pointers to the global, local +// and private address spaces. +let MaxVersion = CL20 in { + foreach AS = [GlobalAS, LocalAS, PrivateAS] in { + foreach VSize = [2, 3, 4, 8, 16] in { + foreach name = ["vload" # VSize] in { + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + } + foreach name = ["vstore" # VSize] in { + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + } + foreach name = ["vloada_half" # VSize] in { + def : Builtin, Size, PointerType, AS>]>; + } + foreach rnd = ["", "_rte", "_rtz", "_rtp", "_rtn"] in { + foreach name = ["vstorea_half" # VSize # rnd] in { + def : Builtin, Size, PointerType]>; + def : Builtin, Size, PointerType]>; + } + } + } + } +} +// Variants for OpenCL versions above 2.0, using pointers to the generic +// address space. +let MinVersion = CL20 in { + foreach VSize = [2, 3, 4, 8, 16] in { + foreach name = ["vload" # VSize] in { + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + } + foreach name = ["vstore" # VSize] in { + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + } + foreach name = ["vloada_half" # VSize] in { + def : Builtin, Size, PointerType, GenericAS>]>; + } + foreach rnd = ["", "_rte", "_rtz", "_rtp", "_rtn"] in { + foreach name = ["vstorea_half" # VSize # rnd] in { + def : Builtin, Size, PointerType]>; + def : Builtin, Size, PointerType]>; + } + } + } +} +// Variants using pointers to the constant address space. +foreach VSize = [2, 3, 4, 8, 16] in { + foreach name = ["vload" # VSize] in { + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + } + foreach name = ["vloada_half" # VSize] in { + def : Builtin, Size, PointerType, ConstantAS>]>; + } + foreach rnd = ["", "_rte", "_rtz", "_rtp", "_rtn"] in { + foreach name = ["vstorea_half" # VSize # rnd] in { + def : Builtin, Size, PointerType]>; + def : Builtin, Size, PointerType]>; + } + } +} + //-------------------------------------------------------------------- // OpenCL v1.1 s6.11.10, v1.2 s6.12.10, v2.0 s6.13.10: Async Copies from Global to Local Memory, Local to Global Memory, and Prefetch // OpenCL Extension v2.0 s5.1.7 and s6.1.7: Async Copies from Global to Local Memory, Local to Global Memory, and Prefetch @@ -350,14 +487,6 @@ foreach Type = [Int, UInt] in { } } -// OpenCL v1.2 s6.12.1: Work-Item Functions -def get_work_dim : Builtin<"get_work_dim", [UInt]>; -foreach name = ["get_global_size", "get_global_id", "get_local_size", - "get_local_id", "get_num_groups", "get_group_id", - "get_global_offset"] in { - def : Builtin; -} - // OpenCL v1.2 s6.12.2: Math Functions foreach name = ["acos", "acosh", "acospi", "asin", "asinh", "asinpi", @@ -511,7 +640,7 @@ foreach aQual = ["WO", "RW"] in { // OpenCL v2.0 s9.17.3: Additions to section 6.13.1: Work-Item Functions -let Version = CL20 in { +let MinVersion = CL20 in { let Extension = "cl_khr_subgroups" in { def get_sub_group_size : Builtin<"get_sub_group_size", [UInt]>; def get_max_sub_group_size : Builtin<"get_max_sub_group_size", [UInt]>; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index dfc1cce89d..f0c11bb233 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -764,6 +764,13 @@ static void InsertOCLBuiltinDeclarationsFromTable(Sema &S, LookupResult &LR, BuiltinTable[FctIndex + SignatureIndex]; ASTContext &Context = S.Context; + // Ignore this BIF if its version does not match the language options. + if (Context.getLangOpts().OpenCLVersion < OpenCLBuiltin.MinVersion) + continue; + if ((OpenCLBuiltin.MaxVersion != 0) && + (Context.getLangOpts().OpenCLVersion >= OpenCLBuiltin.MaxVersion)) + continue; + SmallVector RetTypes; SmallVector, 5> ArgTypes; diff --git a/test/SemaOpenCL/fdeclare-opencl-builtins.cl b/test/SemaOpenCL/fdeclare-opencl-builtins.cl index 590f27353d..6c32e12571 100644 --- a/test/SemaOpenCL/fdeclare-opencl-builtins.cl +++ b/test/SemaOpenCL/fdeclare-opencl-builtins.cl @@ -1,10 +1,20 @@ +// RUN: %clang_cc1 %s -triple spir -verify -pedantic -fsyntax-only -cl-std=CL -fdeclare-opencl-builtins -DNO_HEADER +// RUN: %clang_cc1 %s -triple spir -verify -pedantic -fsyntax-only -cl-std=CL -fdeclare-opencl-builtins -finclude-default-header +// RUN: %clang_cc1 %s -triple spir -verify -pedantic -fsyntax-only -cl-std=CL1.2 -fdeclare-opencl-builtins -DNO_HEADER +// RUN: %clang_cc1 %s -triple spir -verify -pedantic -fsyntax-only -cl-std=CL1.2 -fdeclare-opencl-builtins -finclude-default-header // RUN: %clang_cc1 %s -triple spir -verify -pedantic -fsyntax-only -cl-std=CL2.0 -fdeclare-opencl-builtins -DNO_HEADER // RUN: %clang_cc1 %s -triple spir -verify -pedantic -fsyntax-only -cl-std=CL2.0 -fdeclare-opencl-builtins -finclude-default-header + +#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 // expected-no-diagnostics +#endif // Test the -fdeclare-opencl-builtins option. #pragma OPENCL EXTENSION cl_khr_fp16 : enable +#if __OPENCL_C_VERSION__ < CL_VERSION_1_2 +#pragma OPENCL EXTENSION cl_khr_fp64 : enable +#endif // Provide typedefs when invoking clang without -finclude-default-header. #ifdef NO_HEADER @@ -15,7 +25,10 @@ typedef half half4 __attribute__((ext_vector_type(4))); typedef int int2 __attribute__((ext_vector_type(2))); typedef int int4 __attribute__((ext_vector_type(4))); typedef long long2 __attribute__((ext_vector_type(2))); +typedef unsigned char uchar; typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned short ushort; typedef __SIZE_TYPE__ size_t; #endif @@ -60,12 +73,14 @@ kernel void basic_image_readonly(read_only image2d_t image_read_only_image2d) { res = read_imageh(image_read_only_image2d, sampler, i2); } +#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 kernel void basic_image_readwrite(read_write image3d_t image_read_write_image3d) { half4 h4; int4 i4; write_imageh(image_read_write_image3d, i4, h4); } +#endif // __OPENCL_C_VERSION__ >= CL_VERSION_2_0 kernel void basic_image_writeonly(write_only image1d_buffer_t image_write_only_image1d_buffer) { half4 h4; @@ -78,4 +93,39 @@ kernel void basic_image_writeonly(write_only image1d_buffer_t image_write_only_i kernel void basic_subgroup(global uint *out) { out[0] = get_sub_group_size(); +#if __OPENCL_C_VERSION__ < CL_VERSION_2_0 +// expected-error@-2{{implicit declaration of function 'get_sub_group_size' is invalid in OpenCL}} +#endif +} + +kernel void basic_vector_data() { +#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 + generic void *generic_p; +#endif + constant void *constant_p; + local void *local_p; + global void *global_p; + private void *private_p; + size_t s; + + vload4(s, (const __constant ulong *) constant_p); + vload16(s, (const __constant short *) constant_p); + +#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 + vload3(s, (const __generic ushort *) generic_p); + vload16(s, (const __generic uchar *) generic_p); +#endif + + vload8(s, (const __global long *) global_p); + vload2(s, (const __local uint *) local_p); + vload16(s, (const __private float *) private_p); +} + +kernel void basic_work_item() { + uint ui; + + get_enqueued_local_size(ui); +#if __OPENCL_C_VERSION__ < CL_VERSION_2_0 +// expected-error@-2{{implicit declaration of function 'get_enqueued_local_size' is invalid in OpenCL}} +#endif } diff --git a/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp b/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp index b93a68fb30..7ae1a0672f 100644 --- a/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp +++ b/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp @@ -121,11 +121,13 @@ private: // Emit the BuiltinTable table. This table contains all the overloads of // each function, and is a struct OpenCLBuiltinDecl. // E.g.: - // // convert_float2_rtn - // { 58, 2 }, + // // 891 convert_float2_rtn + // { 58, 2, 100, 0 }, // This means that the signature of this convert_float2_rtn overload has // 1 argument (+1 for the return type), stored at index 58 in - // the SignatureTable. + // the SignatureTable. The last two values represent the minimum (1.0) and + // maximum (0, meaning no max version) OpenCL version in which this overload + // is supported. void EmitBuiltinTable(); // Emit a StringMatcher function to check whether a function name is an @@ -268,6 +270,10 @@ struct OpenCLBuiltinStruct { // the SignatureTable represent the complete signature. The first type at // index SigTableIndex is the return type. const unsigned NumTypes; + // First OpenCL version in which this overload was introduced (e.g. CL20). + const unsigned short MinVersion; + // First OpenCL version in which this overload was removed (e.g. CL20). + const unsigned short MaxVersion; }; )"; @@ -400,11 +406,13 @@ void BuiltinNameEmitter::EmitBuiltinTable() { OS << " // " << (Index + 1) << ": " << FOM.first << "\n"; for (const auto &Overload : FOM.second) { - OS << " { " - << Overload.second << ", " - << Overload.first->getValueAsListOfDefs("Signature").size() + OS << " { " << Overload.second << ", " + << Overload.first->getValueAsListOfDefs("Signature").size() << ", " + << Overload.first->getValueAsDef("MinVersion")->getValueAsInt("ID") + << ", " + << Overload.first->getValueAsDef("MaxVersion")->getValueAsInt("ID") << " },\n"; - Index++; + Index++; } } OS << "};\n\n"; -- cgit v1.2.1