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

Reply via email to