[OpenCL] Add support of OpenCL C 3.0 __opencl_c_fp64
authorAnton Zabaznov <anton.zabaznov@intel.com>
Fri, 21 May 2021 11:07:23 +0000 (14:07 +0300)
committerAnton Zabaznov <anton.zabaznov@intel.com>
Fri, 21 May 2021 12:01:19 +0000 (15:01 +0300)
There already exists cl_khr_fp64 extension. So OpenCL C 3.0
and higher should use the feature, earlier versions still
use the extension. OpenCL C 3.0 API spec states that extension
will be not described in the option string if corresponding
optional functionality is not supported (see 4.2. Querying Devices).
Due to that fact the usage of features for OpenCL C 3.0 must
be as follows:

```
$ clang -Xclang -cl-ext=+cl_khr_fp64,+__opencl_c_fp64 ...

$ clang -Xclang -cl-ext=-cl_khr_fp64,-__opencl_c_fp64 ...
```

e.g. the feature and the equivalent extension (if exists)
must be set to the same values

Reviewed By: Anastasia

Differential Revision: https://reviews.llvm.org/D96524

12 files changed:
clang/docs/OpenCLSupport.rst
clang/include/clang/Basic/DiagnosticCommonKinds.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Basic/Targets.cpp
clang/lib/Basic/Targets/AMDGPU.h
clang/lib/Basic/Targets/NVPTX.h
clang/lib/Frontend/CompilerInstance.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaType.cpp
clang/test/CodeGenOpenCL/printf.cl
clang/test/Misc/opencl-c-3.0.incorrect_options.cl [new file with mode: 0644]
clang/test/SemaOpenCL/fp64-fp16-options.cl [moved from clang/test/SemaOpenCL/extensions.cl with 71% similarity]

index fa719c8..dbfb67f 100644 (file)
@@ -339,7 +339,24 @@ Missing features or with limited support
 
 .. _opencl_300:
 
-OpenCL 3.0 Implementation Status
+OpenCL C 3.0 Usage
+================================
+
+OpenCL C 3.0 language standard makes most OpenCL C 2.0 features optional. Optional
+functionality in OpenCL C 3.0 is indicated with the presence of feature-test macros
+(list of feature-test macros is `here <https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_C.html#features>`_).
+Command-line flag :ref:`-cl-ext <opencl_cl_ext>` can be used to override features supported by a target.
+
+For cases when there is an associated extension for a specific feature (fp64 and 3d image writes)
+user should specify both (extension and feature) in command-line flag:
+
+   .. code-block:: console
+
+     $ clang -cc1 -cl-std=CL3.0 -cl-ext=+cl_khr_fp64,+__opencl_c_fp64 ...
+     $ clang -cc1 -cl-std=CL3.0 -cl-ext=-cl_khr_fp64,-__opencl_c_fp64 ...
+
+
+OpenCL C 3.0 Implementation Status
 ================================
 
 The following table provides an overview of features in OpenCL C 3.0 and their
index 06c2647..4dab3a3 100644 (file)
@@ -364,4 +364,7 @@ def warn_poison_system_directories : Warning <
 def warn_opencl_unsupported_core_feature : Warning<
   "%0 is a core feature in %select{OpenCL C|C++ for OpenCL}1 version %2 but not supported on this target">,
   InGroup<OpenCLCoreFeaturesDiagGroup>, DefaultIgnore;
+
+def err_opencl_extension_and_feature_differs : Error<
+  "options %0 and %1 are set to different values">;
 }
index fff6b62..5d0f5dc 100644 (file)
@@ -118,7 +118,8 @@ def warn_float_underflow : Warning<
   "magnitude of floating-point constant too small for type %0; minimum is %1">,
   InGroup<LiteralRange>;
 def warn_double_const_requires_fp64 : Warning<
-  "double precision constant requires cl_khr_fp64, casting to single precision">;
+  "double precision constant requires %select{cl_khr_fp64|cl_khr_fp64 and __opencl_c_fp64}0, "
+  "casting to single precision">;
 def err_half_const_requires_fp16 : Error<
   "half precision constant requires cl_khr_fp16">;
 
@@ -10027,6 +10028,8 @@ def err_opencl_requires_extension : Error<
 def ext_opencl_double_without_pragma : Extension<
   "Clang permits use of type 'double' regardless pragma if 'cl_khr_fp64' is"
   " supported">;
+def err_opencl_double_requires_extension :  Error<
+    "use of type 'double' requires %select{cl_khr_fp64|cl_khr_fp64 and __opencl_c_fp64}0 support">;
 def warn_opencl_generic_address_space_arg : Warning<
   "passing non-generic address space pointer to %0"
   " may cause dynamic conversion affecting performance">,
index 894db33..0755a94 100644 (file)
@@ -743,7 +743,20 @@ bool TargetInfo::validateOpenCLTarget(const LangOptions &Opts,
   diagnoseNotSupportedCore(#Ext, __VA_ARGS__);
 #include "clang/Basic/OpenCLExtensions.def"
 
-  // For now assume that OpenCL target is always
-  // valid and just provide necessary diagnostics
+  // Validate that feature macros are set properly for OpenCL C 3.0.
+  // In other cases assume that target is always valid.
+  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;
 }
index b2d422c..2729c51 100644 (file)
@@ -292,6 +292,7 @@ public:
     bool IsAMDGCN = isAMDGCN(getTriple());
 
     Opts["cl_khr_fp64"] = hasFP64();
+    Opts["__opencl_c_fp64"] = hasFP64();
 
     if (IsAMDGCN || GPUKind >= llvm::AMDGPU::GK_CEDAR) {
       Opts["cl_khr_byte_addressable_store"] = true;
index d193c4d..c429d55 100644 (file)
@@ -138,6 +138,7 @@ public:
     Opts["__cl_clang_non_portable_kernel_param_types"] = true;
 
     Opts["cl_khr_fp64"] = true;
+    Opts["__opencl_c_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;
index a623580..5df40c7 100644 (file)
@@ -135,8 +135,9 @@ bool CompilerInstance::createTarget() {
 
   // We should do it here because target knows nothing about
   // language options when it's being created.
-  if (getLangOpts().OpenCL)
-    getTarget().validateOpenCLTarget(getLangOpts(), getDiagnostics());
+  if (getLangOpts().OpenCL &&
+      !getTarget().validateOpenCLTarget(getLangOpts(), getDiagnostics()))
+    return false;
 
   // Inform the target of the language options.
   // FIXME: We shouldn't need to do this, the target should be immutable once
index 8181c12..2cabd7d 100644 (file)
@@ -3843,7 +3843,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
       } else if (getLangOpts().OpenCL && !getOpenCLOptions().isAvailableOption(
                                              "cl_khr_fp64", getLangOpts())) {
         // Impose single-precision float type when cl_khr_fp64 is not enabled.
-        Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64);
+        Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64)
+            << (getLangOpts().OpenCLVersion >= 300);
         Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
       }
     }
index bb8e3f4..3e1a18c 100644 (file)
@@ -1526,8 +1526,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
   case DeclSpec::TST_double:
     if (S.getLangOpts().OpenCL) {
       if (!S.getOpenCLOptions().isSupported("cl_khr_fp64", S.getLangOpts()))
-        S.Diag(DS.getTypeSpecTypeLoc(), diag::err_opencl_requires_extension)
-          << 0 << Context.DoubleTy << "cl_khr_fp64";
+        S.Diag(DS.getTypeSpecTypeLoc(),
+               diag::err_opencl_double_requires_extension)
+            << (S.getLangOpts().OpenCLVersion >= 300);
       else if (!S.getOpenCLOptions().isAvailableOption("cl_khr_fp64", S.getLangOpts()))
         S.Diag(DS.getTypeSpecTypeLoc(), diag::ext_opencl_double_without_pragma);
     }
index fc139d7..c68c43b 100644 (file)
@@ -1,10 +1,12 @@
 // RUN: %clang_cc1 -cl-std=CL1.2 -cl-ext=-+cl_khr_fp64 -triple spir-unknown-unknown -disable-llvm-passes -emit-llvm -o - %s | FileCheck -check-prefixes=FP64,ALL %s
 // RUN: %clang_cc1 -cl-std=CL1.2 -cl-ext=-cl_khr_fp64 -triple spir-unknown-unknown -disable-llvm-passes -emit-llvm -o - %s | FileCheck -check-prefixes=NOFP64,ALL %s
+// RUN: %clang_cc1 -cl-std=CL3.0 -cl-ext=+__opencl_c_fp64,+cl_khr_fp64 -triple spir-unknown-unknown -disable-llvm-passes -emit-llvm -o - %s | FileCheck -check-prefixes=FP64,ALL %s
+// RUN: %clang_cc1 -cl-std=CL3.0 -cl-ext=-__opencl_c_fp64,-cl_khr_fp64 -triple spir-unknown-unknown -disable-llvm-passes -emit-llvm -o - %s | FileCheck -check-prefixes=NOFP64,ALL %s
 
 typedef __attribute__((ext_vector_type(2))) float float2;
 typedef __attribute__((ext_vector_type(2))) half half2;
 
-#ifdef cl_khr_fp64
+#if defined(cl_khr_fp64) || defined(__opencl_c_fp64)
 typedef __attribute__((ext_vector_type(2))) double double2;
 #endif
 
@@ -28,7 +30,7 @@ kernel void test_printf_half2(half2 arg) {
   printf("%v2hf", arg);
 }
 
-#ifdef cl_khr_fp64
+#if defined(cl_khr_fp64) || defined(__opencl_c_fp64)
 // FP64-LABEL: @test_printf_double2(
 // FP64: call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(2)* @.str.2, i32 0, i32 0), <2 x double> %0)
 kernel void test_printf_double2(double2 arg) {
diff --git a/clang/test/Misc/opencl-c-3.0.incorrect_options.cl b/clang/test/Misc/opencl-c-3.0.incorrect_options.cl
new file mode 100644 (file)
index 0000000..493c5fd
--- /dev/null
@@ -0,0 +1,4 @@
+// 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
+
+// CHECK: error: options cl_khr_fp64 and __opencl_c_fp64 are set to different values
similarity index 71%
rename from clang/test/SemaOpenCL/extensions.cl
rename to clang/test/SemaOpenCL/fp64-fp16-options.cl
index 9738029..617744a 100644 (file)
@@ -5,6 +5,7 @@
 
 // Test with a target not supporting fp64.
 // RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -DNOFP64 -DNOFP16
+// RUN: %clang_cc1 -cl-std=CL3.0 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -DNOFP64 -DNOFP16
 
 // Test with some extensions enabled or disabled by cmd-line args
 //
 // RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=+all
 // RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=+all,-cl_khr_fp64 -DNOFP64
 // RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=-all,+cl_khr_fp64 -DNOFP16
+// RUN: %clang_cc1 -cl-std=CL3.0 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-all -DNOFP64 -DNOFP16
+// RUN: %clang_cc1 -cl-std=CL3.0 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=+all -DFP64
+// RUN: %clang_cc1 -cl-std=CL3.0 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=+all,-__opencl_c_fp64,-cl_khr_fp64 -DNOFP64
 //
 // Concatenating
 // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-cl_khr_fp64 -cl-ext=+cl_khr_fp64
 // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-cl_khr_fp64,+cl_khr_fp64
 // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-all -cl-ext=+cl_khr_fp64 -cl-ext=+cl_khr_fp16 -cl-ext=-cl_khr_fp64 -DNOFP64
 // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-all -cl-ext=+cl_khr_fp64,-cl_khr_fp64,+cl_khr_fp16 -DNOFP64
+// RUN: %clang_cc1 -cl-std=CL3.0 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-__opencl_c_fp64,-cl_khr_fp64 -cl-ext=+__opencl_c_fp64,+cl_khr_fp64 -DFP64
+// RUN: %clang_cc1 -cl-std=CL3.0 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-__opencl_c_fp64,+__opencl_c_fp64,+cl_khr_fp64 -DFP64
+// RUN: %clang_cc1 -cl-std=CL3.0 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-__opencl_c_fp64,-cl_khr_fp64 -DNOFP64
 
 // Test with -finclude-default-header, which includes opencl-c.h. opencl-c.h
 // disables all extensions by default, but supported core extensions for a
@@ -85,18 +92,30 @@ int isfinite(float x) {
 void f2(void) {
   double d;
 #ifdef NOFP64
-// expected-error@-2{{use of type 'double' requires cl_khr_fp64 support}}
+#if (defined(__OPENCL_C_VERSION__) && __OPENCL_C_VERSION__ >= 300)
+// expected-error@-3{{use of type 'double' requires cl_khr_fp64 and __opencl_c_fp64 support}}
+#else
+// expected-error@-5{{use of type 'double' requires cl_khr_fp64 support}}
+#endif
 #endif
 
   typedef double double4 __attribute__((ext_vector_type(4)));
   double4 d4 = {0.0f, 2.0f, 3.0f, 1.0f};
 #ifdef NOFP64
-// expected-error@-3 {{use of type 'double' requires cl_khr_fp64 support}}
+#if (defined(__OPENCL_C_VERSION__) && __OPENCL_C_VERSION__ >= 300)
+// expected-error@-4 {{use of type 'double' requires cl_khr_fp64 and __opencl_c_fp64 support}}
+#else
+// expected-error@-6 {{use of type 'double' requires cl_khr_fp64 support}}
+#endif
 #endif
 
   (void) 1.0;
 #ifdef NOFP64
-// expected-warning@-2{{double precision constant requires cl_khr_fp64, casting to single precision}}
+#if (defined(__OPENCL_C_VERSION__) && __OPENCL_C_VERSION__ >= 300)
+// expected-warning@-3{{double precision constant requires cl_khr_fp64 and __opencl_c_fp64, casting to single precision}}
+#else
+// expected-warning@-5{{double precision constant requires cl_khr_fp64, casting to single precision}}
+#endif
 #endif
 }