[OpenCL] Add support of __opencl_c_read_write_images feature macro

This feature requires support of __opencl_c_images, so diagnostics for that is provided as well

Reviewed By: Anastasia

Differential Revision: https://reviews.llvm.org/D104915
This commit is contained in:
Anton Zabaznov 2021-07-13 15:09:14 +03:00
parent 4709d9d5be
commit ab76101f40
9 changed files with 97 additions and 40 deletions

View File

@ -367,4 +367,6 @@ def warn_opencl_unsupported_core_feature : Warning<
def err_opencl_extension_and_feature_differs : Error<
"options %0 and %1 are set to different values">;
def err_opencl_feature_requires : Error<
"feature %0 requires support of %1 feature">;
}

View File

@ -10111,7 +10111,8 @@ def err_opencl_builtin_pipe_invalid_access_modifier : Error<
def err_opencl_invalid_access_qualifier : Error<
"access qualifier can only be used for pipe and image type">;
def err_opencl_invalid_read_write : Error<
"access qualifier %0 can not be used for %1 %select{|prior to OpenCL version 2.0}2">;
"access qualifier %0 can not be used for %1 %select{|prior to OpenCL C version 2.0 or in version 3.0 "
"and without __opencl_c_read_write_images feature}2">;
def err_opencl_multiple_access_qualifiers : Error<
"multiple access qualifiers">;
def note_opencl_typedef_access_qualifier : Note<

View File

@ -19,6 +19,9 @@
namespace clang {
class DiagnosticsEngine;
class TargetInfo;
namespace {
// This enum maps OpenCL version(s) into value. These values are used as
// a mask to indicate in which OpenCL version(s) extension is a core or
@ -179,6 +182,16 @@ public:
return OpenCLOptionInfo(std::forward<Args>(args)...).isAvailableIn(LO);
}
// Diagnose feature dependencies for OpenCL C 3.0. Return false if target
// doesn't follow these requirements.
static bool diagnoseUnsupportedFeatureDependencies(const TargetInfo &TI,
DiagnosticsEngine &Diags);
// Diagnose that features and equivalent extension are set to same values.
// Return false if target doesn't follow these requirements.
static bool diagnoseFeatureExtensionDifferences(const TargetInfo &TI,
DiagnosticsEngine &Diags);
private:
// Option is enabled via pragma
bool isEnabled(llvm::StringRef Ext) const;

View File

@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/OpenCLOptions.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetInfo.h"
namespace clang {
@ -104,4 +106,43 @@ void OpenCLOptions::disableAll() {
Opt.getValue().Enabled = false;
}
bool OpenCLOptions::diagnoseUnsupportedFeatureDependencies(
const TargetInfo &TI, DiagnosticsEngine &Diags) {
// Feature pairs. First feature in a pair requires the second one to be
// supported.
static const llvm::StringMap<llvm::StringRef> DependentFeaturesMap = {
{"__opencl_c_read_write_images", "__opencl_c_images"}};
auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
bool IsValid = true;
for (auto &FeaturePair : DependentFeaturesMap)
if (TI.hasFeatureEnabled(OpenCLFeaturesMap, FeaturePair.getKey()) &&
!TI.hasFeatureEnabled(OpenCLFeaturesMap, FeaturePair.getValue())) {
IsValid = false;
Diags.Report(diag::err_opencl_feature_requires)
<< FeaturePair.getKey() << FeaturePair.getValue();
}
return IsValid;
}
bool OpenCLOptions::diagnoseFeatureExtensionDifferences(
const TargetInfo &TI, DiagnosticsEngine &Diags) {
// Extensions and equivalent feature pairs.
static const llvm::StringMap<llvm::StringRef> FeatureExtensionMap = {
{"cl_khr_fp64", "__opencl_c_fp64"}};
auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
bool IsValid = true;
for (auto &ExtAndFeat : FeatureExtensionMap)
if (TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.getKey()) !=
TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.getValue())) {
IsValid = false;
Diags.Report(diag::err_opencl_extension_and_feature_differs)
<< ExtAndFeat.getKey() << ExtAndFeat.getValue();
}
return IsValid;
}
} // end namespace clang

View File

@ -748,15 +748,6 @@ bool TargetInfo::validateOpenCLTarget(const LangOptions &Opts,
if (Opts.OpenCLCPlusPlus || Opts.OpenCLVersion < 300)
return true;
// Feature and corresponding equivalent extension must be set
// simultaneously to the same value.
for (auto &ExtAndFeat : {std::make_pair("cl_khr_fp64", "__opencl_c_fp64")})
if (hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.first) !=
hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.second)) {
Diags.Report(diag::err_opencl_extension_and_feature_differs)
<< ExtAndFeat.first << ExtAndFeat.second;
return false;
}
return true;
return OpenCLOptions::diagnoseUnsupportedFeatureDependencies(*this, Diags) &&
OpenCLOptions::diagnoseFeatureExtensionDifferences(*this, Diags);
}

View File

@ -7395,16 +7395,21 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
}
// OpenCL v2.0 s6.6 - read_write can be used for image types to specify that an
// image object can be read and written.
// OpenCL v2.0 s6.13.6 - A kernel cannot read from and write to the same pipe
// object. Using the read_write (or __read_write) qualifier with the pipe
// qualifier is a compilation error.
// OpenCL v2.0 s6.6 - read_write can be used for image types to specify that
// an image object can be read and written. OpenCL v2.0 s6.13.6 - A kernel
// cannot read from and write to the same pipe object. Using the read_write
// (or __read_write) qualifier with the pipe qualifier is a compilation error.
// OpenCL v3.0 s6.8 - For OpenCL C 2.0, or with the
// __opencl_c_read_write_images feature, image objects specified as arguments
// to a kernel can additionally be declared to be read-write.
if (const auto *PDecl = dyn_cast<ParmVarDecl>(D)) {
const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr();
if (AL.getAttrName()->getName().find("read_write") != StringRef::npos) {
if ((!S.getLangOpts().OpenCLCPlusPlus &&
S.getLangOpts().OpenCLVersion < 200) ||
(S.getLangOpts().OpenCLVersion < 200) ||
(S.getLangOpts().OpenCLVersion == 300 &&
!S.getOpenCLOptions().isSupported("__opencl_c_read_write_images",
S.getLangOpts()))) ||
DeclTy->isPipeType()) {
S.Diag(AL.getLoc(), diag::err_opencl_invalid_read_write)
<< AL << PDecl->getType() << DeclTy->isImageType();

View File

@ -1,4 +1,6 @@
// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=-__opencl_c_fp64,+cl_khr_fp64 %s 2>&1 | FileCheck %s
// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_fp64,-cl_khr_fp64 %s 2>&1 | FileCheck %s
// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=-__opencl_c_fp64,+cl_khr_fp64 %s 2>&1 | FileCheck -check-prefix=CHECK-FP64 %s
// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_fp64,-cl_khr_fp64 %s 2>&1 | FileCheck -check-prefix=CHECK-FP64 %s
// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_read_write_images,-__opencl_c_images %s 2>&1 | FileCheck -check-prefix=CHECK-READ-WRITE-IMAGES %s
// CHECK: error: options cl_khr_fp64 and __opencl_c_fp64 are set to different values
// CHECK-FP64: error: options cl_khr_fp64 and __opencl_c_fp64 are set to different values
// CHECK-READ-WRITE-IMAGES: error: feature __opencl_c_read_write_images requires support of __opencl_c_images feature

View File

@ -1,12 +1,14 @@
// RUN: %clang_cc1 -verify -pedantic -fsyntax-only -cl-std=CL1.2 %s -cl-ext=-cl_khr_3d_image_writes
// RUN: %clang_cc1 -verify -pedantic -fsyntax-only -cl-std=CL2.0 %s
// RUN: %clang_cc1 -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL1.2 %s -cl-ext=-cl_khr_3d_image_writes
// RUN: %clang_cc1 -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL2.0 %s
// RUN: %clang_cc1 -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL3.0 %s
// RUN: %clang_cc1 -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL3.0 %s -cl-ext=-__opencl_c_read_write_images
typedef image1d_t img1d_ro_default; // expected-note {{previously declared 'read_only' here}}
typedef write_only image1d_t img1d_wo; // expected-note {{previously declared 'write_only' here}}
typedef read_only image1d_t img1d_ro;
#if __OPENCL_C_VERSION__ >= 200
#if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ == 300 && defined(__opencl_c_read_write_images))
typedef read_write image1d_t img1d_rw;
#endif
@ -17,10 +19,10 @@ typedef read_only int IntRO; // expected-error {{access qualifier can only be us
void myWrite(write_only image1d_t); // expected-note {{passing argument to parameter here}} expected-note {{passing argument to parameter here}}
void myRead(read_only image1d_t); // expected-note {{passing argument to parameter here}}
#if __OPENCL_C_VERSION__ >= 200
#if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ == 300 && defined(__opencl_c_read_write_images))
void myReadWrite(read_write image1d_t);
#else
void myReadWrite(read_write image1d_t); // expected-error {{access qualifier 'read_write' can not be used for '__read_write image1d_t' prior to OpenCL version 2.0}}
void myReadWrite(read_write image1d_t); // expected-error {{access qualifier 'read_write' can not be used for '__read_write image1d_t' prior to OpenCL C version 2.0 or in version 3.0 and without __opencl_c_read_write_images feature}}
#endif
@ -36,7 +38,7 @@ kernel void k3(img1d_wo img) {
myWrite(img);
}
#if __OPENCL_C_VERSION__ >= 200
#if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ == 300 && defined(__opencl_c_read_write_images))
kernel void k4(img1d_rw img) {
myReadWrite(img);
}
@ -62,26 +64,26 @@ kernel void k11(read_only write_only image1d_t i){} // expected-error{{multiple
kernel void k12(read_only read_only image1d_t i){} // expected-warning {{duplicate 'read_only' declaration specifier}}
#if __OPENCL_C_VERSION__ >= 200
#if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ == 300 && defined(__opencl_c_read_write_images))
kernel void k13(read_write pipe int i){} // expected-error{{access qualifier 'read_write' can not be used for 'read_only pipe int'}}
#else
kernel void k13(__read_write image1d_t i){} // expected-error{{access qualifier '__read_write' can not be used for '__read_write image1d_t' prior to OpenCL version 2.0}}
#endif
#if __OPENCL_C_VERSION__ >= 200
void myPipeWrite(write_only pipe int); // expected-note {{passing argument to parameter here}}
kernel void k14(read_only pipe int p) {
myPipeWrite(p); // expected-error {{passing '__private read_only pipe int' to parameter of incompatible type 'write_only pipe int'}}
}
kernel void k13(__read_write image1d_t i){} // expected-error{{access qualifier '__read_write' can not be used for '__read_write image1d_t' prior to OpenCL C version 2.0 or in version 3.0 and without __opencl_c_read_write_images feature}}
#endif
#if __OPENCL_C_VERSION__ < 200
kernel void test_image3d_wo(write_only image3d_t img) {} // expected-error {{use of type '__write_only image3d_t' requires cl_khr_3d_image_writes support}}
#endif
#if __OPENCL_C_VERSION__ >= 200
#if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ == 300 && defined(__opencl_c_read_write_images))
kernel void read_write_twice_typedef(read_write img1d_rw i){} // expected-warning {{duplicate 'read_write' declaration specifier}}
// expected-note@-74 {{previously declared 'read_write' here}}
// expected-note@-67 {{previously declared 'read_write' here}}
#endif
#if OPENCL_C_VERSION__ >= 200
void myPipeWrite(write_only pipe int); // expected-note {{passing argument to parameter here}}
kernel void k14(read_only pipe int p) {
myPipeWrite(p); // expected-error {{passing '__private read_only pipe int' to parameter of incompatible type 'write_only pipe int'}}
}
kernel void pipe_ro_twice(read_only read_only pipe int i){} // expected-warning{{duplicate 'read_only' declaration specifier}}
// Conflicting access qualifiers
@ -94,7 +96,7 @@ kernel void pipe_ro_twice_typedef(read_only ROPipeInt i){} // expected-warning{{
kernel void pass_ro_typedef_to_wo(ROPipeInt p) {
myPipeWrite(p); // expected-error {{passing '__private ROPipeInt' (aka '__private read_only pipe int') to parameter of incompatible type 'write_only pipe int'}}
// expected-note@-25 {{passing argument to parameter here}}
// expected-note@-16 {{passing argument to parameter here}}
}
#endif

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -triple spir-unknown-unknown -verify -cl-std=CL3.0 -cl-ext=-__opencl_c_images %s
// RUN: %clang_cc1 -triple spir-unknown-unknown -verify -cl-std=CL3.0 -cl-ext=-__opencl_c_images,-__opencl_c_read_write_images %s
// RUN: %clang_cc1 -triple spir-unknown-unknown -verify -cl-std=CL3.0 -cl-ext=+__opencl_c_images %s
#ifdef __opencl_c_images