[PATCH] D92277: [OpenCL] Refactor of targets OpenCL option settings

Anastasia Stulova via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 15 06:02:11 PST 2021


Anastasia added a comment.

This patch contains very useful improvements to the design along with the behavioral fixes. I see that it opens more opportunities to bring the implementation in line with the conventional flow and therefore simplify the further development of new functionality. More improvements can be easily built on top of this work. I, therefore, suggest we drive towards finalizing this patch asap and I have made a couple of small comments that should hopefully be quick enough to address.



================
Comment at: clang/include/clang/Basic/OpenCLExtensions.def:17
 // If the extensions are to be enumerated without the supported OpenCL version,
-// define OPENCLEXT(ext) where ext is the name of the extension.
+// define OPENCLEXTNAME(ext) where ext is the name of the extension.
 //
----------------
I guess you mean that this extension is not against a specific version i.e. applies to all versions?


================
Comment at: clang/include/clang/Basic/OpenCLExtensions.def:65
+OPENCL_EXTENSION(cl_khr_int64_extended_atomics, 100)
+OPENCL_GENERIC_EXTENSION(cl_khr_3d_image_writes, 100, OCL_C_20, OCL_C_30)
 
----------------
FYI not saying this should be changed now because it is sufficient for the current needs but perhaps we could do something like 

OPENCL_GENERIC_EXTENSION(cl_khr_3d_image_writes, 100, {OCL_C_20, OCL_C_31}, {OCL_C_30})

if we start having non-continuous set of versions where a feature is optional or core.


================
Comment at: clang/include/clang/Basic/OpenCLExtensions.def:79
+OPENCL_EXTENSION(cl_khr_subgroups, 200)
+OPENCL_EXTENSION(cl_khr_subgroup_extended_types, 200)
+OPENCL_EXTENSION(cl_khr_subgroup_non_uniform_vote, 200)
----------------
Is this code accidental? The following extensions `cl_khr_subgroup_*` were recently removed from this file.

https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Basic/OpenCLExtensions.def


================
Comment at: clang/include/clang/Basic/OpenCLOptions.h:25
+// optional core feature.
+enum OpenCLVersionID : unsigned int {
+  OCL_C_10 = 0x1,
----------------
I suggest putting this in an anonymous namespace along with `encodeOpenCLVersion` and `OpenCLVersionIsContainedInMask`, as they are only to be used locally.


================
Comment at: clang/include/clang/Basic/OpenCLOptions.h:55
+// OpenCL C version mask
+static inline bool OpenCLVersionIsContainedInMask(const LangOptions &LO,
+                                                  unsigned Mask) {
----------------
A small renaming
`OpenCLVersionIsContainedInMask` -> `isOpenCLVersionContainedInMask`


================
Comment at: clang/include/clang/Basic/OpenCLOptions.h:62
 
-  /// Check if \c Ext is supported as an (optional) OpenCL core features for
-  /// the given OpenCL version.
-  ///
-  /// \param Ext - Extension to look up.
-  /// \param LO - \c LangOptions specifying the OpenCL version.
-  /// \returns \c true if \c Ext is known and supported, \c false otherwise.
-  bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const {
-    auto E = OptMap.find(Ext);
-    if (E == OptMap.end()) {
-      return false;
-    }
-    // In C++ mode all extensions should work at least as in v2.0.
-    auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
-    auto I = E->getValue();
-    return I.Supported && I.Avail <= CLVer && I.Core != ~0U && CLVer >= I.Core;
-  }
+struct OpenCLOptionInfo {
+  // Option starts to be available in this OpenCL version
----------------
I think it would be better to keep it in `OpenCLOptions`, as we don't intend this to be used stand-alone also considering that it's a `struct`? I understand that this is now being used in Targets too but that use should hopefully be eliminated in the future.


================
Comment at: clang/include/clang/Basic/OpenCLOptions.h:106
 
-  void addSupport(const OpenCLOptions &Opts) {
-    for (auto &I:Opts.OptMap)
-      if (I.second.Supported)
-        OptMap[I.getKey()].Supported = true;
-  }
+  llvm::StringMap<OpenCLOptionInfo> OptMap;
 
----------------
I think this map deserves type alias since it's used in quite many places.


================
Comment at: clang/lib/Basic/OpenCLOptions.cpp:96
+void OpenCLOptions::disableAll() {
+  for (llvm::StringMap<OpenCLOptionInfo>::iterator I = OptMap.begin(),
+                                                   E = OptMap.end();
----------------
Maybe this could also be switched to a range based loop along with the one below.


================
Comment at: clang/lib/Basic/TargetInfo.cpp:360
+    // Set core features based on OpenCL version
+    for (auto CoreExt : clang::getCoreFeatures(Opts))
+      getTargetOpts().OpenCLFeaturesMap[CoreExt] = true;
----------------
I still think the target map should be immutable and especially we should not change it silently based on the language compiled even if we have done it before but that caused incorrect behavior i.e. successfully compiling for the architectures that didn't support the features.

If I look at existing targets they already set most of the core features apart from 3d image writes. Perhaps it is reasonable to just drop this code? I don't think it makes the issue worse, in fact, I think it will make the behavior slightly better because now a diagnostic will occur if there is an attempt to use the unsupported feature although the diagnostic won't be the optimal one.  After all it will still remain the responsibility of the user to get the right combination of a language version and a target.

It would be reasonable however to introduce a diagnostic that would report a mismatch between the language version and the hardware support available. We report similar diagnostics in `CompilerInvocation` already. But I don't think we have to do it in this patch because it doesn't introduce any regression. We already have a bug although the behavior of this bug will change. And perhaps if we add `OpenCLOptions` as a part of `LangOpts` at some point this will become straightforward to diagnose. However, I suggest we add information about this issue in a FIXME or perhaps this deserves a clang bug!


================
Comment at: clang/lib/Basic/Targets.cpp:728
+    // Check if extension is supported by target or is a core feature
+    auto It = getTargetOpts().OpenCLFeaturesMap.find(Name);
+    if ((It != getTargetOpts().OpenCLFeaturesMap.end()) && It->getValue() &&
----------------
I still think it would be better if we just iterate over the elements in this map? We should keep the includes of `clang/Basic/OpenCLExtensions.def ` to a minimum.


================
Comment at: clang/lib/Basic/Targets.cpp:730
+    if ((It != getTargetOpts().OpenCLFeaturesMap.end()) && It->getValue() &&
+        OpenCLOptionInfo(AvailVer, CoreVersions, OptionalVersions)
+            .isAvailableIn(Opts))
----------------
I think this defines should belong elsewhere, this will eliminate the need to create the temporary object `OpenCLOptionInfo`.  But I appreciate there is only limited amount of refactoring we can do in one patch.

How about we at least add a `FIXME` explaining that some further refactoring is needed to move the macro definition with the rest of macros from `LangOpts`.




================
Comment at: clang/lib/Basic/Targets.cpp:725
+    if ((It != OpenCLFeaturesMap.end() && It->getValue()) ||
+        OpenCLOptionInfo(AvailVer, CoreVersions, OptionalVersions)
+            .IsCoreIn(Opts))
----------------
azabaznov wrote:
> Anastasia wrote:
> > I think we should find different place for those now.
> > 
> > Ideally, we should iterate though the map in `OpenCLOptions` and set the define for the supported ones.
> > 
> > I suggest we move this into `clang::InitializePreprocessor` which means `Preprocessor` might need a reference to `OpenCLOptions` which is the right thing to do because it needs to know the features that require the macro, the same as for `LangOpts`. This means we will need to change the initialization time of `OpenCLOptions` member in Sema or potentially even reparent it elsewhere... perhaps to `CompilerInstance` where `LangOpts` and `TargetInfo` seems to be created already?
> > I suggest we move this into clang::InitializePreprocessor which means
> 
> I think I'm going to introduce `InitializeOpenCLFeatureTestMacros(TargetInfo, LangOptions)` in `InitPreprocessor.cpp`.
> 
> > This means we will need to change the initialization time of OpenCLOptions member in Sema or potentially even reparent it elsewhere... perhaps to CompilerInstance where LangOpts and TargetInfo seems to be created already
> 
> This seems too invasive for me since `CompilerInstance` is a different purpose class; and it already holds `Sema` and `TargetInfo`. `OpenCLOptions` should mainly be used for parsing, so I would like to suggest avoiding using it elsewhere. Furthermore, with the proposed flow `OpenCLOptions.h` can be removed later  and some simple helpers can be used to check the availability of features/extensions.
> 
> However, I see your point: we have two identical pieces of code in `TargetInfo::getOpenCLFeatureDefines` and `OpenCLOptions::addSupport`. I think I'll try to get rid of this duplication by transferring setting of core features into `TargetInfo::adjust` which seems pretty right thing to do. What do you think?
> This seems too invasive for me since CompilerInstance is a different purpose class; and it already holds Sema and TargetInfo. OpenCLOptions should mainly be used for parsing, so I would like to suggest avoiding using it elsewhere. 

Yes, it is a bigger change I agree. But it is closer to the conventional flow in my opinion. This is how it works for `LangOpts` and `OpenCLOpts` don't seem to be different to `LangOpts`, especially now after your refactoring. Perhaps we should just move `OpenCLOpts` to `LangOpts`? Then `Sema` can access `OpenCLOpts`  through `LangOpts` as well as modify them because they are immutable. We can then just add the defines along with the rest of `LangOpts` in `clang::InitializePreprocessor`.

If you look at `CompilerInvocation` then you will see that while `LangOpts` are set `TargetInfo` are also taken into account. Then `LangOpts` are modified using pragmas for example in `Parser::HandlePragmaFPContract()`.

> Furthermore, with the proposed flow OpenCLOptions.h can be removed later and some simple helpers can be used to check the availability of features/extensions.

Ok, this would also be a nice alternative but we will still need to store information about optional/core versions and etc somewhere? Would it not be needed for pragmas?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D92277/new/

https://reviews.llvm.org/D92277



More information about the cfe-commits mailing list