[OpenCL] Prevent adding extension pragma by default.

This commit refactors extension support to allow
specifying whether pragma is needed or not explicitly.

For backward compatibility pragmas are set to required
for all extensions that were added prior to this but
not for OpenCL 3.0 features.

Differential Revision: https://reviews.llvm.org/D97052
This commit is contained in:
Anastasia Stulova 2021-03-03 12:05:38 +00:00
parent 0a5dd06718
commit 25ad188bfc
8 changed files with 141 additions and 62 deletions

View File

@ -16,8 +16,12 @@
// If extensions are to be enumerated with information about whether
// an extension is core or optional core and minimum OpenCL version
// when an extension becomes available,
// define OPENCL_GENERIC_EXTENSION(ext, avail, core, opt) where
// define OPENCL_GENERIC_EXTENSION(ext, pragma, avail, core, opt) where
// ext - name of the extension or optional core feature.
// pragma - true if extension needs pragmas or false otherwise.
// NOTE: extension pragma without any documentation detailing
// its behavior explicitly is deprecated. Therefore the default
// value is false.
// avail - minimum OpenCL version supporting it.
// core - OpenCL versions mask when the extension becomes core feature.
// 0U indicates not a core feature.
@ -50,67 +54,67 @@
#endif // OPENCL_GENERIC_EXTENSION
// Declaration helpers
#define OPENCL_EXTENSION(ext, avail) OPENCL_GENERIC_EXTENSION(ext, avail, 0U, 0U)
#define OPENCL_COREFEATURE(ext, avail, core) OPENCL_GENERIC_EXTENSION(ext, avail, core, 0U)
#define OPENCL_OPTIONALCOREFEATURE(ext, avail, opt) OPENCL_GENERIC_EXTENSION(ext, avail, 0U, opt)
#define OPENCL_EXTENSION(ext, pragma, avail) OPENCL_GENERIC_EXTENSION(ext, pragma, avail, 0U, 0U)
#define OPENCL_COREFEATURE(ext, pragma, avail, core) OPENCL_GENERIC_EXTENSION(ext, pragma, avail, core, 0U)
#define OPENCL_OPTIONALCOREFEATURE(ext, pragma, avail, opt) OPENCL_GENERIC_EXTENSION(ext, pragma, avail, 0U, opt)
// OpenCL 1.0.
OPENCL_COREFEATURE(cl_khr_byte_addressable_store, 100, OCL_C_11P)
OPENCL_COREFEATURE(cl_khr_global_int32_base_atomics, 100, OCL_C_11P)
OPENCL_COREFEATURE(cl_khr_global_int32_extended_atomics, 100, OCL_C_11P)
OPENCL_COREFEATURE(cl_khr_local_int32_base_atomics, 100, OCL_C_11P)
OPENCL_COREFEATURE(cl_khr_local_int32_extended_atomics, 100, OCL_C_11P)
OPENCL_OPTIONALCOREFEATURE(cl_khr_fp64, 100, OCL_C_12P)
OPENCL_EXTENSION(cl_khr_fp16, 100)
OPENCL_EXTENSION(cl_khr_int64_base_atomics, 100)
OPENCL_EXTENSION(cl_khr_int64_extended_atomics, 100)
OPENCL_COREFEATURE(cl_khr_3d_image_writes, 100, OCL_C_20)
OPENCL_COREFEATURE(cl_khr_byte_addressable_store, true, 100, OCL_C_11P)
OPENCL_COREFEATURE(cl_khr_global_int32_base_atomics, true, 100, OCL_C_11P)
OPENCL_COREFEATURE(cl_khr_global_int32_extended_atomics, true, 100, OCL_C_11P)
OPENCL_COREFEATURE(cl_khr_local_int32_base_atomics, true, 100, OCL_C_11P)
OPENCL_COREFEATURE(cl_khr_local_int32_extended_atomics, true, 100, OCL_C_11P)
OPENCL_OPTIONALCOREFEATURE(cl_khr_fp64, true, 100, OCL_C_12P)
OPENCL_EXTENSION(cl_khr_fp16, true, 100)
OPENCL_EXTENSION(cl_khr_int64_base_atomics, true, 100)
OPENCL_EXTENSION(cl_khr_int64_extended_atomics, true, 100)
OPENCL_COREFEATURE(cl_khr_3d_image_writes, true, 100, OCL_C_20)
// EMBEDDED_PROFILE
OPENCL_EXTENSION(cles_khr_int64, 110)
OPENCL_EXTENSION(cles_khr_int64, true, 110)
// OpenCL 1.2.
OPENCL_EXTENSION(cl_khr_depth_images, 120)
OPENCL_EXTENSION(cl_khr_gl_msaa_sharing, 120)
OPENCL_EXTENSION(cl_khr_depth_images, true, 120)
OPENCL_EXTENSION(cl_khr_gl_msaa_sharing,true, 120)
// OpenCL 2.0.
OPENCL_EXTENSION(cl_khr_mipmap_image, 200)
OPENCL_EXTENSION(cl_khr_mipmap_image_writes, 200)
OPENCL_EXTENSION(cl_khr_srgb_image_writes, 200)
OPENCL_EXTENSION(cl_khr_subgroups, 200)
OPENCL_EXTENSION(cl_khr_mipmap_image, true, 200)
OPENCL_EXTENSION(cl_khr_mipmap_image_writes, true, 200)
OPENCL_EXTENSION(cl_khr_srgb_image_writes, true, 200)
OPENCL_EXTENSION(cl_khr_subgroups, true, 200)
// Clang Extensions.
OPENCL_EXTENSION(cl_clang_storage_class_specifiers, 100)
OPENCL_EXTENSION(__cl_clang_function_pointers, 100)
OPENCL_EXTENSION(__cl_clang_variadic_functions, 100)
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)
// AMD OpenCL extensions
OPENCL_EXTENSION(cl_amd_media_ops, 100)
OPENCL_EXTENSION(cl_amd_media_ops2, 100)
OPENCL_EXTENSION(cl_amd_media_ops, true, 100)
OPENCL_EXTENSION(cl_amd_media_ops2, true, 100)
// ARM OpenCL extensions
OPENCL_EXTENSION(cl_arm_integer_dot_product_int8, 120)
OPENCL_EXTENSION(cl_arm_integer_dot_product_accumulate_int8, 120)
OPENCL_EXTENSION(cl_arm_integer_dot_product_accumulate_int16, 120)
OPENCL_EXTENSION(cl_arm_integer_dot_product_accumulate_saturate_int8, 120)
OPENCL_EXTENSION(cl_arm_integer_dot_product_int8, true, 120)
OPENCL_EXTENSION(cl_arm_integer_dot_product_accumulate_int8, true, 120)
OPENCL_EXTENSION(cl_arm_integer_dot_product_accumulate_int16, true, 120)
OPENCL_EXTENSION(cl_arm_integer_dot_product_accumulate_saturate_int8, true, 120)
// Intel OpenCL extensions
OPENCL_EXTENSION(cl_intel_subgroups, 120)
OPENCL_EXTENSION(cl_intel_subgroups_short, 120)
OPENCL_EXTENSION(cl_intel_device_side_avc_motion_estimation, 120)
OPENCL_EXTENSION(cl_intel_subgroups, true, 120)
OPENCL_EXTENSION(cl_intel_subgroups_short, true, 120)
OPENCL_EXTENSION(cl_intel_device_side_avc_motion_estimation, true, 120)
// OpenCL C 3.0 features (6.2.1. Features)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_pipes, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_generic_address_space, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_atomic_order_acq_rel, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_atomic_order_seq_cst, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_subgroups, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_3d_image_writes, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_device_enqueue, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_read_write_images, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_program_scope_global_variables, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_fp64, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_images, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_pipes, false, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_generic_address_space, false, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_atomic_order_acq_rel, false, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_atomic_order_seq_cst, false, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_subgroups, false, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_3d_image_writes, false, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_device_enqueue, false, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_read_write_images, false, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_program_scope_global_variables, false, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_fp64, false, 300, OCL_C_30)
OPENCL_OPTIONALCOREFEATURE(__opencl_c_images, false, 300, OCL_C_30)
#undef OPENCL_OPTIONALCOREFEATURE
#undef OPENCL_COREFEATURE

View File

@ -65,14 +65,17 @@ static inline bool isOpenCLVersionIsContainedInMask(const LangOptions &LO,
class OpenCLOptions {
public:
struct OpenCLOptionInfo {
// Does this option have pragma.
bool WithPragma = false;
// Option starts to be available in this OpenCL version
unsigned Avail;
unsigned Avail = 100U;
// Option becomes core feature in this OpenCL versions
unsigned Core;
unsigned Core = 0U;
// Option becomes optional core feature in this OpenCL versions
unsigned Opt;
unsigned Opt = 0U;
// Is this option supported
bool Supported = false;
@ -80,8 +83,10 @@ public:
// Is this option enabled
bool Enabled = false;
OpenCLOptionInfo(unsigned A = 100, unsigned C = 0U, unsigned O = 0U)
: Avail(A), Core(C), Opt(O) {}
OpenCLOptionInfo() = default;
OpenCLOptionInfo(bool Pragma, unsigned AvailV, unsigned CoreV,
unsigned OptV)
: WithPragma(Pragma), Avail(AvailV), Core(CoreV), Opt(OptV) {}
bool isCore() const { return Core != 0U; }
@ -109,6 +114,8 @@ public:
bool isEnabled(llvm::StringRef Ext) const;
bool isWithPragma(llvm::StringRef Ext) const;
// Is supported as either an extension or an (optional) core feature for
// OpenCL version \p LO.
bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const;
@ -131,6 +138,11 @@ public:
// For supported core or optional core feature, return false.
bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const;
// FIXME: Whether extension should accept pragma should not
// be reset dynamically. But it currently required when
// registering new extensions via pragmas.
void acceptsPragma(llvm::StringRef Ext, bool V = true);
void enable(llvm::StringRef Ext, bool V = true);
/// Enable or disable support for OpenCL extensions

View File

@ -19,6 +19,11 @@ bool OpenCLOptions::isEnabled(llvm::StringRef Ext) const {
return E != OptMap.end() && E->second.Enabled;
}
bool OpenCLOptions::isWithPragma(llvm::StringRef Ext) const {
auto E = OptMap.find(Ext);
return E != OptMap.end() && E->second.WithPragma;
}
bool OpenCLOptions::isSupported(llvm::StringRef Ext,
const LangOptions &LO) const {
auto E = OptMap.find(Ext);
@ -69,6 +74,10 @@ void OpenCLOptions::enable(llvm::StringRef Ext, bool V) {
OptMap[Ext].Enabled = V;
}
void OpenCLOptions::acceptsPragma(llvm::StringRef Ext, bool V) {
OptMap[Ext].WithPragma = V;
}
void OpenCLOptions::support(llvm::StringRef Ext, bool V) {
assert(!Ext.empty() && "Extension is empty.");
assert(Ext[0] != '+' && Ext[0] != '-');
@ -76,10 +85,9 @@ void OpenCLOptions::support(llvm::StringRef Ext, bool V) {
}
OpenCLOptions::OpenCLOptions() {
#define OPENCL_GENERIC_EXTENSION(Ext, AvailVer, CoreVer, OptVer) \
OptMap[#Ext].Avail = AvailVer; \
OptMap[#Ext].Core = CoreVer; \
OptMap[#Ext].Opt = OptVer;
#define OPENCL_GENERIC_EXTENSION(Ext, WithPragma, AvailVer, CoreVer, OptVer) \
OptMap.insert_or_assign( \
#Ext, OpenCLOptionInfo{WithPragma, AvailVer, CoreVer, OptVer});
#include "clang/Basic/OpenCLExtensions.def"
}

View File

@ -722,7 +722,7 @@ void TargetInfo::getOpenCLFeatureDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
// FIXME: OpenCL options which affect language semantics/syntax
// should be moved into LangOptions, thus macro definitions of
// such options is better to be done in clang::InitializePreprocessor
// such options is better to be done in clang::InitializePreprocessor.
auto defineOpenCLExtMacro = [&](llvm::StringRef Name, unsigned AvailVer,
unsigned CoreVersions,
unsigned OptionalVersions) {
@ -730,12 +730,12 @@ void TargetInfo::getOpenCLFeatureDefines(const LangOptions &Opts,
// OpenCL version
auto It = getTargetOpts().OpenCLFeaturesMap.find(Name);
if ((It != getTargetOpts().OpenCLFeaturesMap.end()) && It->getValue() &&
OpenCLOptions::OpenCLOptionInfo(AvailVer, CoreVersions,
OpenCLOptions::OpenCLOptionInfo(false, AvailVer, CoreVersions,
OptionalVersions)
.isAvailableIn(Opts))
Builder.defineMacro(Name);
};
#define OPENCL_GENERIC_EXTENSION(Ext, Avail, Core, Opt) \
#define OPENCL_GENERIC_EXTENSION(Ext, WithPragma, Avail, Core, Opt) \
defineOpenCLExtMacro(#Ext, Avail, Core, Opt);
#include "clang/Basic/OpenCLExtensions.def"

View File

@ -780,13 +780,16 @@ void Parser::HandlePragmaOpenCLExtension() {
} else if (State == Begin) {
if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {
Opt.support(Name);
// FIXME: Default behavior of the extension pragma is not defined.
// Therefore, it should never be added by default.
Opt.acceptsPragma(Name);
}
Actions.setCurrentOpenCLExtension(Name);
} else if (State == End) {
if (Name != Actions.getCurrentOpenCLExtension())
PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
Actions.setCurrentOpenCLExtension("");
} else if (!Opt.isKnown(Name))
} else if (!Opt.isKnown(Name) || !Opt.isWithPragma(Name))
PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
else if (Opt.isSupportedExtension(Name, getLangOpts()))
Opt.enable(Name, State == Enable);

View File

@ -3628,6 +3628,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
auto &OptInfo = OpenCLExtensions.OptMap[Name];
OptInfo.Supported = Record[I++] != 0;
OptInfo.Enabled = Record[I++] != 0;
OptInfo.WithPragma = Record[I++] != 0;
OptInfo.Avail = Record[I++];
OptInfo.Core = Record[I++];
OptInfo.Opt = Record[I++];

View File

@ -3958,6 +3958,7 @@ void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) {
auto V = I.getValue();
Record.push_back(V.Supported ? 1 : 0);
Record.push_back(V.Enabled ? 1 : 0);
Record.push_back(V.WithPragma ? 1 : 0);
Record.push_back(V.Avail);
Record.push_back(V.Core);
Record.push_back(V.Opt);

View File

@ -3,15 +3,13 @@
// RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple spir-unknown-unknown
// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple spir-unknown-unknown
// RUN: %clang_cc1 -x cl -cl-std=clc++ %s -verify -triple spir-unknown-unknown
// RUN: %clang_cc1 -x cl -cl-std=CL3.0 %s -verify -triple spir-unknown-unknown
// RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES
// RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES
// RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES
// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES
// RUN: %clang_cc1 -x cl -cl-std=clc++ %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES
#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) && !defined(TEST_CORE_FEATURES)
// expected-no-diagnostics
#endif
// RUN: %clang_cc1 -x cl -cl-std=CL3.0 %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES
// Extensions in all versions
#ifndef cl_clang_storage_class_specifiers
@ -100,7 +98,7 @@
#error "Missing cl_khr_3d_image_writes define"
#endif
#pragma OPENCL EXTENSION cl_khr_3d_image_writes : enable
#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) && defined TEST_CORE_FEATURES
#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ == 200) && defined TEST_CORE_FEATURES
// expected-warning@-2{{OpenCL extension 'cl_khr_3d_image_writes' is core feature or supported optional core feature - ignoring}}
#endif
@ -215,3 +213,55 @@
// expected-warning@+2{{unsupported OpenCL extension 'cl_intel_device_side_avc_motion_estimation' - ignoring}}
#endif
#pragma OPENCL EXTENSION cl_intel_device_side_avc_motion_estimation : enable
// Check that pragmas for the OpenCL 3.0 features are rejected.
#pragma OPENCL EXTENSION __opencl_c_int64 : disable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_int64' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_3d_image_writes : disable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_3d_image_writes' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_atomic_order_acq_rel : disable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_atomic_order_acq_rel' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_atomic_order_seq_cst : disable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_atomic_order_seq_cst' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_device_enqueue : disable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_device_enqueue' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_fp64 : disable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_fp64' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_generic_address_space : disable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_generic_address_space' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_images : disable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_images' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_pipes : disable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_pipes' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_program_scope_global_variables : disable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_program_scope_global_variables' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_read_write_images : disable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_read_write_images' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_subgroups : disable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_subgroups' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_int64 : enable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_int64' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_3d_image_writes : enable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_3d_image_writes' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_atomic_order_acq_rel : enable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_atomic_order_acq_rel' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_atomic_order_seq_cst : enable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_atomic_order_seq_cst' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_device_enqueue : enable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_device_enqueue' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_fp64 : enable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_fp64' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_generic_address_space : enable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_generic_address_space' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_images : enable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_images' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_pipes : enable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_pipes' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_program_scope_global_variables : enable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_program_scope_global_variables' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_read_write_images : enable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_read_write_images' - ignoring}}
#pragma OPENCL EXTENSION __opencl_c_subgroups : enable
//expected-warning@-1{{unknown OpenCL extension '__opencl_c_subgroups' - ignoring}}