azabaznov created this revision. azabaznov added reviewers: Anastasia, svenvh. Herald added subscribers: dexonsmith, jfb. azabaznov requested review of this revision.
This change relates to OpenCL C 3.0 support. RFC thread: https://lists.llvm.org/pipermail/cfe-dev/2020-September/066883.html The same interface ('-cl-ext' option) is being used to indicate that feature or extension is supported. OpenCL C 3.0 by default doesn't provide any features which are core in OpenCL C 2.0. The idea is to define feature test macros for all OpenCL versions and provide simultaneous macro presence if there exist equivalent extension. https://reviews.llvm.org/D89869 Files: clang/include/clang/Basic/OpenCLExtensions.def clang/include/clang/Basic/OpenCLOptions.h clang/lib/Basic/Targets/SPIR.h clang/lib/Basic/Targets/X86.h clang/lib/Frontend/CompilerInstance.cpp clang/lib/Parse/ParsePragma.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp clang/test/Preprocessor/opencl-feature-extension-simult.cl clang/test/Preprocessor/opencl-features.cl
Index: clang/test/Preprocessor/opencl-features.cl =================================================================== --- /dev/null +++ clang/test/Preprocessor/opencl-features.cl @@ -0,0 +1,129 @@ +// RUN: %clang_cc1 %s -E -cl-std=CL2.0 +// RUN: %clang_cc1 %s -E -cl-std=CL2.0 -cl-ext=-__opencl_c_device_enqueue,-__opencl_c_pipes,-__opencl_c_read_write_images +// RUN: %clang_cc1 %s -E -cl-std=CLC++ +// RUN: %clang_cc1 %s -E -cl-std=CL3.0 + +// expected-no-diagnostics + +#ifndef __opencl_c_int64 + #error Feature __opencl_c_int64 should be defined +#endif + +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ == CL_VERSION_2_0) + #ifndef __opencl_c_3d_image_writes + #error Feature __opencl_c_3d_image_writes should be defined + #endif + + #ifndef __opencl_c_atomic_order_acq_rel + #error Feature __opencl_c_atomic_order_acq_rel should be defined + #endif + + #ifndef __opencl_c_atomic_order_seq_cst + #error Feature __opencl_c_atomic_order_seq_cst should be defined + #endif + + #ifndef __opencl_c_atomic_scope_device + #error Feature __opencl_c_atomic_scope_device should be defined + #endif + + #ifndef __opencl_c_atomic_scope_all_devices + #error Feature __opencl_c_atomic_scope_all_devices should be defined + #endif + + #ifndef __opencl_c_device_enqueue + #error Feature __opencl_c_device_enqueue should be defined + #endif + + #ifndef __opencl_c_generic_address_space + #error Feature __opencl_c_generic_address_space should be defined + #endif + + #ifndef __opencl_c_pipes + #error Feature __opencl_c_pipes should be defined + #endif + + #ifndef __opencl_c_program_scope_global_variables + #error Feature __opencl_c_program_scope_global_variables should be defined + #endif + + #ifndef __opencl_c_read_write_images + #error Feature __opencl_c_read_write_images should be defined + #endif + + #ifndef __opencl_c_subgroups + #error Feature __opencl_c_subgroups should be defined + #endif + + #ifndef __opencl_c_work_group_collective_functions + #error Feature __opencl_c_work_group_collective_functions should be defined + #endif + + #ifndef __opencl_c_fp64 + #error Feature __opencl_c_fp64 should be defined + #endif + + #ifndef __opencl_c_images + #error Feature __opencl_c_images should be defined + #endif +#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) + + +#if __OPENCL_C_VERSION__ == CL_VERSION_3_0 + #ifdef __opencl_c_3d_image_writes + #error Feature __opencl_c_3d_image_writes shouldn't be defined + #endif + + #ifdef __opencl_c_atomic_order_acq_rel + #error Feature __opencl_c_atomic_order_acq_rel shouldn't be defined + #endif + + #ifdef __opencl_c_atomic_order_seq_cst + #error Feature __opencl_c_atomic_order_seq_cst shouldn't be defined + #endif + + #ifdef __opencl_c_atomic_scope_device + #error Feature __opencl_c_atomic_scope_device shouldn't be defined + #endif + + #ifdef __opencl_c_atomic_scope_all_devices + #error Feature __opencl_c_atomic_scope_all_devices shouldn't be defined + #endif + + #ifdef __opencl_c_device_enqueue + #error Feature __opencl_c_device_enqueue shouldn't be defined + #endif + + #ifdef __opencl_c_generic_address_space + #error Feature __opencl_c_generic_address_space shouldn't be defined + #endif + + #ifdef __opencl_c_pipes + #error Feature __opencl_c_pipes shouldn't be defined + #endif + + #ifdef __opencl_c_program_scope_global_variables + #error Feature __opencl_c_program_scope_global_variables shouldn't be defined + #endif + + #ifdef __opencl_c_read_write_images + #error Feature __opencl_c_read_write_images shouldn't be defined + #endif + + #ifdef __opencl_c_subgroups + #error Feature __opencl_c_subgroups shouldn't be defined + #endif + + #ifdef __opencl_c_work_group_collective_functions + #error Feature __opencl_c_work_group_collective_functions shouldn't be defined + #endif + + #ifdef __opencl_c_fp64 + #error Feature __opencl_c_fp64 shouldn't be defined + #endif + + #ifdef __opencl_c_images + #error Feature __opencl_c_images shouldn't be defined + #endif +#endif // __OPENCL_C_VERSION__ == CL_VERSION_3_0 + + Index: clang/test/Preprocessor/opencl-feature-extension-simult.cl =================================================================== --- /dev/null +++ clang/test/Preprocessor/opencl-feature-extension-simult.cl @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 %s -E -cl-std=CL1.2 -cl-ext=-cl_khr_fp64 +// RUN: %clang_cc1 %s -E -cl-std=CL1.2 -cl-ext=+cl_khr_fp64 +// RUN: %clang_cc1 %s -E -cl-std=CL1.2 -cl-ext=-cl_khr_3d_image_writes +// RUN: %clang_cc1 %s -E -cl-std=CL1.2 -cl-ext=+cl_khr_3d_image_writes +// RUN: %clang_cc1 %s -E -cl-std=CL1.2 -cl-ext=-cl_khr_subgroups +// RUN: %clang_cc1 %s -E -cl-std=CL1.2 -cl-ext=+cl_khr_subgroups + +// RUN: %clang_cc1 %s -E -cl-std=CL2.0 -cl-ext=-cl_khr_fp64 +// RUN: %clang_cc1 %s -E -cl-std=CL2.0 -cl-ext=+cl_khr_fp64 +// RUN: %clang_cc1 %s -E -cl-std=CL2.0 -cl-ext=-cl_khr_3d_image_writes +// RUN: %clang_cc1 %s -E -cl-std=CL2.0 -cl-ext=+cl_khr_3d_image_writes +// RUN: %clang_cc1 %s -E -cl-std=CL2.0 -cl-ext=-cl_khr_subgroups +// RUN: %clang_cc1 %s -E -cl-std=CL2.0 -cl-ext=+cl_khr_subgroups + +// RUN: %clang_cc1 %s -E -cl-std=CL3.0 -cl-ext=-all__opencl_c_fp64 +// RUN: %clang_cc1 %s -E -cl-std=CL3.0 -cl-ext=+__opencl_c_fp64 +// RUN: %clang_cc1 %s -E -cl-std=CL3.0 -cl-ext=+__opencl_c_3d_image_writes +// RUN: %clang_cc1 %s -E -cl-std=CL3.0 -cl-ext=+__opencl_c_subgroups +// RUN: %clang_cc1 %s -E -cl-std=CL3.0 -cl-ext=+__opencl_c_pipes +// RUN: %clang_cc1 %s -E -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue +// RUN: %clang_cc1 %s -E -cl-std=CL3.0 -cl-ext=+__opencl_c_read_write_images +// RUN: %clang_cc1 %s -E -cl-std=CL3.0 -cl-ext=+__opencl_c_fp64,-cl_khr_fp64 +// RUN: %clang_cc1 %s -E -cl-std=CL3.0 -cl-ext=+__opencl_c_3d_image_writes,-cl_khr_3d_image_writes +// RUN: %clang_cc1 %s -E -cl-std=CL3.0 -cl-ext=+__opencl_c_subgroups,-cl_khr_subgroups + +// expected-no-diagnostics + +#ifdef cl_khr_fp64 + #ifndef __opencl_c_fp64 + #error macros were not properly set up + #endif +#endif +#ifdef __opencl_c_fp64 + #ifndef cl_khr_fp64 + #error macros were not properly set up + #endif +#endif + +#ifdef cl_khr_3d_image_writes + #ifndef __opencl_c_3d_image_writes + #error macros were not properly set up + #endif +#endif +#ifdef __opencl_c_3d_image_writes + #ifndef cl_khr_3d_image_writes + #error macros were not properly set up + #endif +#endif + +#ifdef cl_khr_subgroups + #ifndef __opencl_c_subgroups + #error macros were not properly set up + #endif +#endif +#ifdef __opencl_c_subgroups + #ifndef cl_khr_subgroups + #error macros were not properly set up + #endif +#endif Index: clang/lib/Serialization/ASTWriter.cpp =================================================================== --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -3974,6 +3974,7 @@ auto V = I.getValue(); Record.push_back(V.Supported ? 1 : 0); Record.push_back(V.Enabled ? 1 : 0); + Record.push_back(V.IsFeature ? 1 : 0); Record.push_back(V.Avail); Record.push_back(V.Core); } Index: clang/lib/Serialization/ASTReader.cpp =================================================================== --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -3602,6 +3602,7 @@ auto &Opt = OpenCLExtensions.OptMap[Name]; Opt.Supported = Record[I++] != 0; Opt.Enabled = Record[I++] != 0; + Opt.IsFeature = Record[I++] != 0; Opt.Avail = Record[I++]; Opt.Core = Record[I++]; } Index: clang/lib/Parse/ParsePragma.cpp =================================================================== --- clang/lib/Parse/ParsePragma.cpp +++ clang/lib/Parse/ParsePragma.cpp @@ -770,7 +770,7 @@ // behavior is set to disable." if (Name == "all") { if (State == Disable) { - Opt.disableAll(); + Opt.disableAllExtensions(); Opt.enableSupportedCore(getLangOpts()); } else { PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1; Index: clang/lib/Frontend/CompilerInstance.cpp =================================================================== --- clang/lib/Frontend/CompilerInstance.cpp +++ clang/lib/Frontend/CompilerInstance.cpp @@ -946,6 +946,9 @@ // FIXME: can we disable FEnvAccess? } + if (getLangOpts().OpenCL) + getTarget().getSupportedOpenCLOpts().adjustFeatures(getLangOpts()); + // Inform the target of the language options. // // FIXME: We shouldn't need to do this, the target should be immutable once Index: clang/lib/Basic/Targets/X86.h =================================================================== --- clang/lib/Basic/Targets/X86.h +++ clang/lib/Basic/Targets/X86.h @@ -358,7 +358,7 @@ bool hasSjLjLowering() const override { return true; } void setSupportedOpenCLOpts() override { - getSupportedOpenCLOpts().supportAll(); + getSupportedOpenCLOpts().supportAllExtensions(); } uint64_t getPointerWidthV(unsigned AddrSpace) const override { Index: clang/lib/Basic/Targets/SPIR.h =================================================================== --- clang/lib/Basic/Targets/SPIR.h +++ clang/lib/Basic/Targets/SPIR.h @@ -100,7 +100,7 @@ void setSupportedOpenCLOpts() override { // Assume all OpenCL extensions and optional core features are supported // for SPIR since it is a generic target. - getSupportedOpenCLOpts().supportAll(); + getSupportedOpenCLOpts().supportAllExtensions(); } bool hasExtIntType() const override { return true; } Index: clang/include/clang/Basic/OpenCLOptions.h =================================================================== --- clang/include/clang/Basic/OpenCLOptions.h +++ clang/include/clang/Basic/OpenCLOptions.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_BASIC_OPENCLOPTIONS_H #include "clang/Basic/LangOptions.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" namespace clang { @@ -24,13 +25,21 @@ struct Info { bool Supported; // Is this option supported bool Enabled; // Is this option enabled + bool IsFeature; // Is this OpenCL feature unsigned Avail; // Option starts to be available in this OpenCL version unsigned Core; // Option becomes (optional) core feature in this OpenCL // version - Info(bool S = false, bool E = false, unsigned A = 100, unsigned C = ~0U) - :Supported(S), Enabled(E), Avail(A), Core(C){} + Info(bool S = false, bool E = false, bool F = false, unsigned A = 100, + unsigned C = ~0U) + : Supported(S), Enabled(E), IsFeature(F), Avail(A), Core(C) {} }; llvm::StringMap<Info> OptMap; + + const llvm::DenseMap<StringRef, StringRef> EquivalentFeaturesExtensions{ + {"__opencl_c_subgroups", "cl_khr_subgroups"}, + {"__opencl_c_3d_image_writes", "cl_khr_3d_image_writes"}, + {"__opencl_c_fp64", "cl_khr_fp64"}}; + public: bool isKnown(llvm::StringRef Ext) const { return OptMap.find(Ext) != OptMap.end(); @@ -90,7 +99,7 @@ } if (Ext.equals("all")) { - supportAll(V); + supportAllExtensions(V); return; } OptMap[Ext].Supported = V; @@ -100,9 +109,46 @@ #define OPENCLEXT_INTERNAL(Ext, AvailVer, CoreVer) \ OptMap[#Ext].Avail = AvailVer; \ OptMap[#Ext].Core = CoreVer; +#define OPENCLFEAT_INTERNAL(Feat, AvailVer, CoreVer) \ + OptMap[#Feat].Avail = AvailVer; \ + OptMap[#Feat].Core = CoreVer; \ + OptMap[#Feat].IsFeature = true; #include "clang/Basic/OpenCLExtensions.def" } + // Support features whose support is directly related to the + // specific OpenCL version. For example, OpenCL 2.0 supports + // all features that are optional in 3.0 + void adjustFeatures(const LangOptions &LO) { + // Assume compiling for FULL profile + OptMap["__opencl_c_int64"].Supported = true; + + auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; + if (CLVer >= 300) { + // Simultaneously support feature and equivalent extension. + for (auto FeatExt : EquivalentFeaturesExtensions) + OptMap[FeatExt.getSecond()].Supported = + OptMap[FeatExt.getFirst()].Supported; + + // For OpenCL C 3.0 all features are supported + // explicitly via option or target settings. + return; + } + + for (auto &Opt : OptMap) { + auto &Info = Opt.getValue(); + if (!Info.IsFeature) + continue; + // For pre-OpenCL C 3.0 features are supported simultaneously + // with corresponding extensions (if there is such extension). + auto ExtIt = EquivalentFeaturesExtensions.find(Opt.getKey()); + if (ExtIt != EquivalentFeaturesExtensions.end()) + Info.Supported = OptMap[ExtIt->getSecond()].Supported; + else if (Info.Avail <= CLVer) + Info.Supported = true; + } + } + void addSupport(const OpenCLOptions &Opts) { for (auto &I:Opts.OptMap) if (I.second.Supported) @@ -114,16 +160,18 @@ } // Turn on or off support of all options. - void supportAll(bool On = true) { + void supportAllExtensions(bool On = true) { for (llvm::StringMap<Info>::iterator I = OptMap.begin(), E = OptMap.end(); I != E; ++I) - I->second.Supported = On; + if (!I->second.IsFeature) + I->second.Supported = On; } - void disableAll() { + void disableAllExtensions() { for (llvm::StringMap<Info>::iterator I = OptMap.begin(), E = OptMap.end(); I != E; ++I) - I->second.Enabled = false; + if (!I->second.IsFeature) + I->second.Enabled = false; } void enableSupportedCore(LangOptions LO) { Index: clang/include/clang/Basic/OpenCLExtensions.def =================================================================== --- clang/include/clang/Basic/OpenCLExtensions.def +++ clang/include/clang/Basic/OpenCLExtensions.def @@ -32,6 +32,10 @@ #endif // OPENCLEXT #endif // OPENCLEXT_INTERNAL +#ifndef OPENCLFEAT_INTERNAL +#define OPENCLFEAT_INTERNAL OPENCLEXT_INTERNAL +#endif // OPENCLFEAT_INTERNAL + // OpenCL 1.0. OPENCLEXT_INTERNAL(cl_khr_3d_image_writes, 100, 200) // fprounding mode is special since it is not mentioned beyond 1.0 @@ -100,7 +104,25 @@ OPENCLEXT_INTERNAL(cl_intel_subgroups_short, 120, ~0U) OPENCLEXT_INTERNAL(cl_intel_device_side_avc_motion_estimation, 120, ~0U) +// OpenCL features +OPENCLFEAT_INTERNAL(__opencl_c_pipes, 200, ~0U) +OPENCLFEAT_INTERNAL(__opencl_c_generic_address_space, 200, ~0U) +OPENCLFEAT_INTERNAL(__opencl_c_work_group_collective_functions, 200, ~0U) +OPENCLFEAT_INTERNAL(__opencl_c_atomic_order_acq_rel, 200, ~0U) +OPENCLFEAT_INTERNAL(__opencl_c_atomic_order_seq_cst, 200, ~0U) +OPENCLFEAT_INTERNAL(__opencl_c_atomic_scope_device, 200, ~0U) +OPENCLFEAT_INTERNAL(__opencl_c_atomic_scope_all_devices, 200, ~0U) +OPENCLFEAT_INTERNAL(__opencl_c_subgroups, 200, ~0U) +OPENCLFEAT_INTERNAL(__opencl_c_3d_image_writes, 100, ~0U) +OPENCLFEAT_INTERNAL(__opencl_c_device_enqueue, 200, ~0U) +OPENCLFEAT_INTERNAL(__opencl_c_read_write_images, 200, ~0U) +OPENCLFEAT_INTERNAL(__opencl_c_program_scope_global_variables, 200, ~0U) +OPENCLFEAT_INTERNAL(__opencl_c_fp64, 120, ~0U) +OPENCLFEAT_INTERNAL(__opencl_c_int64, 100, ~0U) +OPENCLFEAT_INTERNAL(__opencl_c_images, 100, ~0U) + #undef OPENCLEXT_INTERNAL +#undef OPENCLFEAT_INTERNAL #ifdef OPENCLEXT #undef OPENCLEXT
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits