Index: clang/include/clang/Basic/OpenCLExtensions.def =================================================================== --- clang/include/clang/Basic/OpenCLExtensions.def +++ clang/include/clang/Basic/OpenCLExtensions.def @@ -10,20 +10,19 @@ // //===----------------------------------------------------------------------===// -// Macro OPENCLEXT or OPENCLEXT_INTERNAL can be defined to enumerate the +// Macro OPENCLEXT or OPENCLCOREEXT_INTERNAL can be defined to enumerate the // OpenCL extensions listed in this file. // // If the extensions are to be enumerated without the supported OpenCL version, // define OPENCLEXT(ext) where ext is the name of the extension. // // If the extensions are to be enumerated with supported OpenCL version, -// define OPENCLEXT_INTERNAL(ext, avail, core) where +// define OPENCLCOREEXT_INTERNAL(ext, avail, core) where // ext - name of the extension or optional core feature. // avail - minimum OpenCL version supporting it. // core - minimum OpenCL version when the extension becomes optional core // feature or core feature. ~0U indicates not a core feature or an // optional core feature. -// // As per The OpenCL Extension Specification, Section 1.2, in this file, an // extension is defined if and only it either: // * affects the OpenCL language semantics or its syntax, @@ -34,65 +33,75 @@ // compilation flow is impacted, e.g. due to a difference of syntax or // semantics in the language compared to the core standard. -#ifndef OPENCLEXT_INTERNAL -#ifndef OPENCLEXT -#pragma error "macro OPENCLEXT or OPENCLEXT_INTERNAL is required" +#ifndef OPENCLCOREEXT_INTERNAL + #ifndef OPENCLEXT + #error "macro OPENCLEXT or OPENCLCOREEXT_INTERNAL is required" + #endif + #define OPENCLEXT_INTERNAL(ext, ...) OPENCLEXT(ext) + #define OPENCLOPTIONALCOREEXT_INTERNAL(ext, ...) OPENCLEXT(ext) + #define OPENCLCOREEXT_INTERNAL(ext, ...) OPENCLEXT(ext) #else -#define OPENCLEXT_INTERNAL(ext, ...) OPENCLEXT(ext) -#endif // OPENCLEXT -#endif // OPENCLEXT_INTERNAL + #ifndef OPENCLOPTIONALCOREEXT_INTERNAL + #define OPENCLOPTIONALCOREEXT_INTERNAL(ext, avail, core) OPENCLCOREEXT_INTERNAL(ext, avail, core) + #endif + #ifndef OPENCLEXT_INTERNAL + #define OPENCLEXT_INTERNAL(ext, avail) OPENCLOPTIONALCOREEXT_INTERNAL(ext, avail, ~0U) + #endif +#endif // OpenCL 1.0. -OPENCLEXT_INTERNAL(cl_khr_3d_image_writes, 100, 200) -OPENCLEXT_INTERNAL(cl_khr_byte_addressable_store, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_fp16, 100, ~0U) -OPENCLEXT_INTERNAL(cl_khr_fp64, 100, 120) -OPENCLEXT_INTERNAL(cl_khr_global_int32_base_atomics, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_global_int32_extended_atomics, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_local_int32_base_atomics, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_local_int32_extended_atomics, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_int64_base_atomics, 100, ~0U) -OPENCLEXT_INTERNAL(cl_khr_int64_extended_atomics, 100, ~0U) +OPENCLEXT_INTERNAL(cl_khr_fp16, 100) +OPENCLEXT_INTERNAL(cl_khr_int64_base_atomics, 100) +OPENCLEXT_INTERNAL(cl_khr_int64_extended_atomics, 100) +OPENCLCOREEXT_INTERNAL(cl_khr_3d_image_writes, 100, 200) +OPENCLCOREEXT_INTERNAL(cl_khr_byte_addressable_store, 100, 110) +OPENCLOPTIONALCOREEXT_INTERNAL(cl_khr_fp64, 100, 120) +OPENCLCOREEXT_INTERNAL(cl_khr_global_int32_base_atomics, 100, 110) +OPENCLCOREEXT_INTERNAL(cl_khr_global_int32_extended_atomics, 100, 110) +OPENCLCOREEXT_INTERNAL(cl_khr_local_int32_base_atomics, 100, 110) +OPENCLCOREEXT_INTERNAL(cl_khr_local_int32_extended_atomics, 100, 110) // EMBEDDED_PROFILE -OPENCLEXT_INTERNAL(cles_khr_int64, 110, ~0U) +OPENCLEXT_INTERNAL(cles_khr_int64, 110) // OpenCL 1.2. -OPENCLEXT_INTERNAL(cl_khr_depth_images, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_gl_msaa_sharing, 120, ~0U) +OPENCLEXT_INTERNAL(cl_khr_depth_images, 120) +OPENCLEXT_INTERNAL(cl_khr_gl_msaa_sharing, 120) // OpenCL 2.0. -OPENCLEXT_INTERNAL(cl_khr_mipmap_image, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_mipmap_image_writes, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_srgb_image_writes, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroups, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_extended_types, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_non_uniform_vote, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_ballot, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_non_uniform_arithmetic, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_shuffle, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_shuffle_relative, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_clustered_reduce, 200, ~0U) +OPENCLEXT_INTERNAL(cl_khr_mipmap_image, 200) +OPENCLEXT_INTERNAL(cl_khr_mipmap_image_writes, 200) +OPENCLEXT_INTERNAL(cl_khr_srgb_image_writes, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroups, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroup_extended_types, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroup_non_uniform_vote, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroup_ballot, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroup_non_uniform_arithmetic, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroup_shuffle, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroup_shuffle_relative, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroup_clustered_reduce, 200) // Clang Extensions. -OPENCLEXT_INTERNAL(cl_clang_storage_class_specifiers, 100, ~0U) +OPENCLEXT_INTERNAL(cl_clang_storage_class_specifiers, 100) // AMD OpenCL extensions -OPENCLEXT_INTERNAL(cl_amd_media_ops, 100, ~0U) -OPENCLEXT_INTERNAL(cl_amd_media_ops2, 100, ~0U) +OPENCLEXT_INTERNAL(cl_amd_media_ops, 100) +OPENCLEXT_INTERNAL(cl_amd_media_ops2, 100) // ARM OpenCL extensions -OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_int8, 120, ~0U) -OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_int8, 120, ~0U) -OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_int16, 120, ~0U) -OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_saturate_int8, 120, ~0U) +OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_int8, 120) +OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_int8, 120) +OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_int16, 120) +OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_saturate_int8, 120) // Intel OpenCL extensions -OPENCLEXT_INTERNAL(cl_intel_subgroups, 120, ~0U) -OPENCLEXT_INTERNAL(cl_intel_subgroups_short, 120, ~0U) -OPENCLEXT_INTERNAL(cl_intel_device_side_avc_motion_estimation, 120, ~0U) +OPENCLEXT_INTERNAL(cl_intel_subgroups, 120) +OPENCLEXT_INTERNAL(cl_intel_subgroups_short, 120) +OPENCLEXT_INTERNAL(cl_intel_device_side_avc_motion_estimation, 120) #undef OPENCLEXT_INTERNAL +#undef OPENCLCOREEXT_INTERNAL +#undef OPENCLOPTIONALCOREEXT_INTERNAL #ifdef OPENCLEXT #undef OPENCLEXT Index: clang/include/clang/Basic/OpenCLOptions.h =================================================================== --- clang/include/clang/Basic/OpenCLOptions.h +++ clang/include/clang/Basic/OpenCLOptions.h @@ -97,20 +97,20 @@ } OpenCLOptions(){ -#define OPENCLEXT_INTERNAL(Ext, AvailVer, CoreVer) \ - OptMap[#Ext].Avail = AvailVer; \ - OptMap[#Ext].Core = CoreVer; +#define OPENCLCOREEXT_INTERNAL(Ext, AvailVer, CoreVer) \ + OptMap[#Ext].Avail = AvailVer; \ + OptMap[#Ext].Core = CoreVer; #include "clang/Basic/OpenCLExtensions.def" } - void addSupport(const OpenCLOptions &Opts) { - for (auto &I:Opts.OptMap) - if (I.second.Supported) - OptMap[I.getKey()].Supported = true; - } + OpenCLOptions(const OpenCLOptions &) = default; - void copy(const OpenCLOptions &Opts) { - OptMap = Opts.OptMap; + void addSupport(const llvm::StringMap &FeaturesMap) { + for (const auto &F : FeaturesMap) { + const auto &Name = F.getKey(); + if (isKnown(Name) && F.getValue()) + support(Name); + } } // Turn on or off support of all options. Index: clang/include/clang/Basic/TargetInfo.h =================================================================== --- clang/include/clang/Basic/TargetInfo.h +++ clang/include/clang/Basic/TargetInfo.h @@ -1429,23 +1429,18 @@ virtual bool defaultsToAIXPowerAlignment() const { return false; } /// Set supported OpenCL extensions and optional core features. - virtual void setSupportedOpenCLOpts() {} + virtual void setSupportedOpenCLOpts(const LangOptions &Opts) {} - /// Set supported OpenCL extensions as written on command line - virtual void setOpenCLExtensionOpts() { - for (const auto &Ext : getTargetOpts().OpenCLExtensionsAsWritten) { - getTargetOpts().SupportedOpenCLOptions.support(Ext); - } - } + void getOpenCLFeatureDefines(MacroBuilder &Builder) const; /// Get supported OpenCL extensions and optional core features. - OpenCLOptions &getSupportedOpenCLOpts() { - return getTargetOpts().SupportedOpenCLOptions; + llvm::StringMap &getSupportedOpenCLOpts() { + return getTargetOpts().OpenCLFeaturesMap; } - /// Get const supported OpenCL extensions and optional core features. - const OpenCLOptions &getSupportedOpenCLOpts() const { - return getTargetOpts().SupportedOpenCLOptions; + /// Get supported OpenCL extensions and optional core features. + const llvm::StringMap &getSupportedOpenCLOpts() const { + return getTargetOpts().OpenCLFeaturesMap; } /// Get address space for OpenCL type. @@ -1483,6 +1478,11 @@ virtual bool allowDebugInfoForExternalVar() const { return false; } protected: + /// Set core OpenCL features which depend on OpenCL version and + /// provided in command line + void adjustSupportedOpenCLOpts(const LangOptions &Opts, + bool SupportAll = false); + /// Copy type and layout related info. void copyAuxTarget(const TargetInfo *Aux); virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { Index: clang/include/clang/Basic/TargetOptions.h =================================================================== --- clang/include/clang/Basic/TargetOptions.h +++ clang/include/clang/Basic/TargetOptions.h @@ -62,7 +62,7 @@ llvm::StringMap FeatureMap; /// Supported OpenCL extensions and optional core features. - OpenCLOptions SupportedOpenCLOptions; + llvm::StringMap OpenCLFeaturesMap; /// The list of OpenCL extensions to enable or disable, as written on /// the command line. Index: clang/lib/Basic/Targets.cpp =================================================================== --- clang/lib/Basic/Targets.cpp +++ clang/lib/Basic/Targets.cpp @@ -694,8 +694,6 @@ if (!Target->handleTargetFeatures(Opts->Features, Diags)) return nullptr; - Target->setSupportedOpenCLOpts(); - Target->setOpenCLExtensionOpts(); Target->setMaxAtomicWidth(); if (!Target->validateTarget(Diags)) @@ -705,3 +703,49 @@ return Target.release(); } +void TargetInfo::adjustSupportedOpenCLOpts(const LangOptions &LO, + bool SupportAll) { + auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; + + // Unify OpenCL features. Choose last provided by the target and on command + // line + + // Support all avialable features for specific OpenCL version + auto SupportAllFeatures = [&](bool V = true) { +#define OPENCLCOREEXT_INTERNAL(Ext, AvailVer, CoreVer) \ + if (CLVer >= AvailVer) \ + getTargetOpts().OpenCLFeaturesMap[#Ext] = V; +#include "clang/Basic/OpenCLExtensions.def" + }; + + if (SupportAll) + SupportAllFeatures(); + + // Ignore optional and optional core as them to be set by the target or command line +#define OPENCLOPTIONALCOREEXT_INTERNAL(Ext, ...) + // Check if core is supported +#define OPENCLCOREEXT_INTERNAL(Ext, AvailVer, CoreVer) \ + if (CLVer >= AvailVer && CoreVer != ~0U && CLVer >= CoreVer) \ + getTargetOpts().OpenCLFeaturesMap[#Ext] = true; +#include "clang/Basic/OpenCLExtensions.def" + + // Set supported OpenCL extensions as written on command line + for (const auto &Ext : getTargetOpts().OpenCLExtensionsAsWritten) { + bool IsPrefixed = (Ext[0] == '+' || Ext[0] == '-'); + std::string Name = IsPrefixed ? Ext.substr(1) : Ext; + bool V = IsPrefixed ? Ext[0] == '+' : true; + + if (Name == "all") { + SupportAllFeatures(V); + continue; + } + + getTargetOpts().OpenCLFeaturesMap[Name] = V; + } +} + +void TargetInfo::getOpenCLFeatureDefines(MacroBuilder &Builder) const { + for (const auto &F : getTargetOpts().OpenCLFeaturesMap) + if (F.getValue()) + Builder.defineMacro(F.getKey()); +} Index: clang/lib/Basic/Targets/AMDGPU.h =================================================================== --- clang/lib/Basic/Targets/AMDGPU.h +++ clang/lib/Basic/Targets/AMDGPU.h @@ -282,34 +282,40 @@ return GPUKind != llvm::AMDGPU::GK_NONE; } - void setSupportedOpenCLOpts() override { + void setSupportedOpenCLOpts(const LangOptions &LO) override { auto &Opts = getSupportedOpenCLOpts(); - Opts.support("cl_clang_storage_class_specifiers"); + Opts["cl_clang_storage_class_specifiers"] = true; bool IsAMDGCN = isAMDGCN(getTriple()); - if (hasFP64()) - Opts.support("cl_khr_fp64"); + Opts["cl_khr_fp64"] = hasFP64(); if (IsAMDGCN || GPUKind >= llvm::AMDGPU::GK_CEDAR) { - Opts.support("cl_khr_byte_addressable_store"); - Opts.support("cl_khr_global_int32_base_atomics"); - Opts.support("cl_khr_global_int32_extended_atomics"); - Opts.support("cl_khr_local_int32_base_atomics"); - Opts.support("cl_khr_local_int32_extended_atomics"); + Opts["cl_khr_byte_addressable_store"] = true; + Opts["cl_khr_global_int32_base_atomics"] = true; + Opts["cl_khr_global_int32_extended_atomics"] = true; + Opts["cl_khr_local_int32_base_atomics"] = true; + Opts["cl_khr_local_int32_extended_atomics"] = true; } if (IsAMDGCN) { - Opts.support("cl_khr_fp16"); - Opts.support("cl_khr_int64_base_atomics"); - Opts.support("cl_khr_int64_extended_atomics"); - Opts.support("cl_khr_mipmap_image"); - Opts.support("cl_khr_mipmap_image_writes"); - Opts.support("cl_khr_subgroups"); - Opts.support("cl_khr_3d_image_writes"); - Opts.support("cl_amd_media_ops"); - Opts.support("cl_amd_media_ops2"); + Opts["cl_khr_fp16"] = true; + Opts["cl_khr_int64_base_atomics"] = true; + Opts["cl_khr_int64_extended_atomics"] = true; + + auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; + if (CLVer == 200) { + Opts["cl_khr_mipmap_image"] = true; + Opts["cl_khr_mipmap_image_writes"] = true; + Opts["cl_khr_subgroups"] = true; + } + + Opts["cl_khr_3d_image_writes"] = true; + Opts["cl_amd_media_ops"] = true; + Opts["cl_amd_media_ops2"] = true; } + + TargetInfo::adjustSupportedOpenCLOpts(LO); } LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const override { Index: clang/lib/Basic/Targets/NVPTX.h =================================================================== --- clang/lib/Basic/Targets/NVPTX.h +++ clang/lib/Basic/Targets/NVPTX.h @@ -125,16 +125,17 @@ return GPU != CudaArch::UNKNOWN; } - void setSupportedOpenCLOpts() override { + void setSupportedOpenCLOpts(const LangOptions &LOpts) override { auto &Opts = getSupportedOpenCLOpts(); - Opts.support("cl_clang_storage_class_specifiers"); - - Opts.support("cl_khr_fp64"); - Opts.support("cl_khr_byte_addressable_store"); - Opts.support("cl_khr_global_int32_base_atomics"); - Opts.support("cl_khr_global_int32_extended_atomics"); - Opts.support("cl_khr_local_int32_base_atomics"); - Opts.support("cl_khr_local_int32_extended_atomics"); + Opts["cl_clang_storage_class_specifiers"] = true; + + Opts["cl_khr_fp64"] = true; + Opts["cl_khr_byte_addressable_store"] = true; + Opts["cl_khr_global_int32_base_atomics"] = true; + Opts["cl_khr_global_int32_extended_atomics"] = true; + Opts["cl_khr_local_int32_base_atomics"] = true; + Opts["cl_khr_local_int32_extended_atomics"] = true; + TargetInfo::adjustSupportedOpenCLOpts(LOpts); } /// \returns If a target requires an address within a target specific address Index: clang/lib/Basic/Targets/SPIR.h =================================================================== --- clang/lib/Basic/Targets/SPIR.h +++ clang/lib/Basic/Targets/SPIR.h @@ -97,10 +97,10 @@ return CC_SpirFunction; } - void setSupportedOpenCLOpts() override { + void setSupportedOpenCLOpts(const LangOptions &Opts) override { // Assume all OpenCL extensions and optional core features are supported // for SPIR since it is a generic target. - getSupportedOpenCLOpts().supportAll(); + TargetInfo::adjustSupportedOpenCLOpts(Opts, true /*support all*/); } bool hasExtIntType() const override { return true; } Index: clang/lib/Basic/Targets/X86.h =================================================================== --- clang/lib/Basic/Targets/X86.h +++ clang/lib/Basic/Targets/X86.h @@ -359,8 +359,8 @@ bool hasSjLjLowering() const override { return true; } - void setSupportedOpenCLOpts() override { - getSupportedOpenCLOpts().supportAll(); + void setSupportedOpenCLOpts(const LangOptions &Opts) override { + TargetInfo::adjustSupportedOpenCLOpts(Opts, true /* support all */); } uint64_t getPointerWidthV(unsigned AddrSpace) const override { Index: clang/lib/Frontend/CompilerInstance.cpp =================================================================== --- clang/lib/Frontend/CompilerInstance.cpp +++ clang/lib/Frontend/CompilerInstance.cpp @@ -953,6 +953,9 @@ // FIXME: can we disable FEnvAccess? } + if (getLangOpts().OpenCL) + getTarget().setSupportedOpenCLOpts(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/Frontend/InitPreprocessor.cpp =================================================================== --- clang/lib/Frontend/InitPreprocessor.cpp +++ clang/lib/Frontend/InitPreprocessor.cpp @@ -1111,10 +1111,7 @@ // OpenCL definitions. if (LangOpts.OpenCL) { -#define OPENCLEXT(Ext) \ - if (TI.getSupportedOpenCLOpts().isSupported(#Ext, LangOpts)) \ - Builder.defineMacro(#Ext); -#include "clang/Basic/OpenCLExtensions.def" + TI.getOpenCLFeatureDefines(Builder); if (TI.getTriple().isSPIR()) Builder.defineMacro("__IMAGE_SUPPORT__"); Index: clang/lib/Serialization/ASTReader.cpp =================================================================== --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -7836,7 +7836,7 @@ NewOverrides.applyOverrides(SemaObj->getLangOpts()); } - SemaObj->OpenCLFeatures.copy(OpenCLExtensions); + SemaObj->OpenCLFeatures = OpenCLExtensions; SemaObj->OpenCLTypeExtMap = OpenCLTypeExtMap; SemaObj->OpenCLDeclExtMap = OpenCLDeclExtMap;