Index: clang/lib/Sema/OpenCLBuiltins.td =================================================================== --- clang/lib/Sema/OpenCLBuiltins.td +++ clang/lib/Sema/OpenCLBuiltins.td @@ -20,12 +20,13 @@ //===----------------------------------------------------------------------===// // Versions of OpenCL class Version { - int Version = _Version; + int Name = _Version; } -def CL10: Version<100>; -def CL11: Version<110>; -def CL12: Version<120>; -def CL20: Version<200>; +def CLNull : Version<000>; +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. @@ -174,8 +175,13 @@ 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. + // CLNull abstracts a version beyond all existing version. + Version MaxVersion = CLNull; } //===----------------------------------------------------------------------===// @@ -279,6 +285,137 @@ } } +//-------------------------------------------------------------------- +// OpenCL v1.1 s6.11.1, v1.2 s6.12.1, v2.0/2.2 s6.13.1 - Work-item Functions +// --- Table 7 --- +def : Builtin<"get_work_dim", [uint_t]>; +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_t, uint_t]>; + 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/2.2 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.2 s5.1.6 and 6.1.6 - Vector Data Load and Store Functions +// --- Table 15 --- +// --- 3 arguments --- +// 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_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + } + foreach name = ["vstore"#VSize] in { + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + def : Builtin, size_t, PointerType, AS>]>; + } + foreach name = ["vloada_half"#VSize] in { + def : Builtin, size_t, PointerType, AS>]>; + } + foreach rnd = ["", "_rte", "_rtz", "_rtp", "_rtn"] in { + foreach name = ["vstorea_half"#VSize#rnd] in { + def : Builtin, size_t, PointerType]>; + def : Builtin, size_t, 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_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + } + foreach name = ["vstore"#VSize] in { + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + def : Builtin, size_t, PointerType, GenericAS>]>; + } + foreach name = ["vloada_half"#VSize] in { + def : Builtin, size_t, PointerType, GenericAS>]>; + } + foreach rnd = ["", "_rte", "_rtz", "_rtp", "_rtn"] in { + foreach name = ["vstorea_half"#VSize#rnd] in { + def : Builtin, size_t, PointerType]>; + def : Builtin, size_t, 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_t, PointerType, ConstantAS>]>; + def : Builtin, size_t, PointerType, ConstantAS>]>; + def : Builtin, size_t, PointerType, ConstantAS>]>; + def : Builtin, size_t, PointerType, ConstantAS>]>; + def : Builtin, size_t, PointerType, ConstantAS>]>; + def : Builtin, size_t, PointerType, ConstantAS>]>; + def : Builtin, size_t, PointerType, ConstantAS>]>; + def : Builtin, size_t, PointerType, ConstantAS>]>; + def : Builtin, size_t, PointerType, ConstantAS>]>; + def : Builtin, size_t, PointerType, ConstantAS>]>; + def : Builtin, size_t, PointerType, ConstantAS>]>; + } + foreach name = ["vloada_half"#VSize] in { + def : Builtin, size_t, PointerType, ConstantAS>]>; + } + foreach rnd = ["", "_rte", "_rtz", "_rtp", "_rtn"] in { + foreach name = ["vstorea_half"#VSize#rnd] in { + def : Builtin, size_t, PointerType]>; + def : Builtin, size_t, PointerType]>; + } + } +} //-------------------------------------------------------------------- @@ -301,15 +438,6 @@ } - -// OpenCL v1.2 s6.12.1: Work-Item Functions -def get_work_dim : Builtin<"get_work_dim", [uint_t]>; -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", @@ -373,14 +501,3 @@ def : Builtin, VectorType, VectorType]>; } } - - - -// OpenCL v2.0 s9.17.3: Additions to section 6.13.1: Work-Item Functions -let Version = CL20 in { - let Extension = "cl_khr_subgroups" in { - def get_sub_group_size : Builtin<"get_sub_group_size", [uint_t]>; - def get_max_sub_group_size : Builtin<"get_max_sub_group_size", [uint_t]>; - def get_num_sub_groups : Builtin<"get_num_sub_groups", [uint_t]>; - } -} Index: clang/lib/Sema/SemaLookup.cpp =================================================================== --- clang/lib/Sema/SemaLookup.cpp +++ clang/lib/Sema/SemaLookup.cpp @@ -792,6 +792,13 @@ const OpenCLBuiltinStruct &Decl = BuiltinTable[FctIndex + SignatureIndex]; ASTContext &Context = S.Context; + // Ignore this BIF if the version is incorrect. + if (Context.getLangOpts().OpenCLVersion < Decl.MinVersion) + continue; + if ((Decl.MaxVersion != 0) && + (Context.getLangOpts().OpenCLVersion >= Decl.MaxVersion)) + continue; + std::vector RetTypes; SmallVector, 5> ArgTypes; Index: clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl =================================================================== --- clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl +++ clang/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 @@ -14,7 +24,10 @@ 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 @@ -27,8 +40,6 @@ atom_cmpxchg((volatile __global unsigned int *) global_p, ui, ui); } - - kernel void basic_conversion() { double d; float f; @@ -58,13 +69,46 @@ write_imageh(image_write_only_image1d_buffer, i, h4); } + +#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 kernel void basic_readwrite_image_type(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_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 + +#if __OPENCL_C_VERSION__ < CL_VERSION_2_0 + vload8(s, (const __global long *) global_p); + vload2(s, (const __local uint *) local_p); + vload16(s, (const __private float *) private_p); +#endif +} + +kernel void basic_work_item() { + uint ui; -kernel void basic_subgroup(global uint *out) { - out[0] = get_sub_group_size(); + 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 } Index: clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp =================================================================== --- clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp +++ clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp @@ -267,6 +267,10 @@ // the SignatureTable must be considered to build the signature. // The first type at index SignTableIndex is the return type. unsigned NumTypes; + // Version in which it was introduced (e.g.: CL20). MinVersion is inclusive. + unsigned MinVersion; + // Version in which it was introduced (e.g.: CL20). MaxVersion is exclusive. + unsigned MaxVersion; }; )"; @@ -380,6 +384,8 @@ OS << " { " << Overload.second << ", " << Overload.first->getValueAsListOfDefs("Signature").size() << ", " + << Overload.first->getValueAsDef("MinVersion")->getValueAsInt("Name") << ", " + << Overload.first->getValueAsDef("MaxVersion")->getValueAsInt("Name") << " },\n"; Index++; } @@ -405,6 +411,7 @@ OS << R"( + // Return 0 if name is not a recognized OpenCL builtin, or an index // into a table of declarations if it is an OpenCL builtin. std::pair isOpenCLBuiltin(llvm::StringRef name) {