SyncScope.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- SyncScope.h - Atomic synchronization scopes ------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// \file
  15. /// Provides definitions for the atomic synchronization scopes.
  16. ///
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_CLANG_BASIC_SYNCSCOPE_H
  19. #define LLVM_CLANG_BASIC_SYNCSCOPE_H
  20. #include "clang/Basic/LangOptions.h"
  21. #include "llvm/ADT/ArrayRef.h"
  22. #include "llvm/ADT/StringRef.h"
  23. #include <memory>
  24. namespace clang {
  25. /// Defines synch scope values used internally by clang.
  26. ///
  27. /// The enum values start from 0 and are contiguous. They are mainly used for
  28. /// enumerating all supported synch scope values and mapping them to LLVM
  29. /// synch scopes. Their numerical values may be different from the corresponding
  30. /// synch scope enums used in source languages.
  31. ///
  32. /// In atomic builtin and expressions, language-specific synch scope enums are
  33. /// used. Currently only OpenCL memory scope enums are supported and assumed
  34. /// to be used by all languages. However, in the future, other languages may
  35. /// define their own set of synch scope enums. The language-specific synch scope
  36. /// values are represented by class AtomicScopeModel and its derived classes.
  37. ///
  38. /// To add a new enum value:
  39. /// Add the enum value to enum class SyncScope.
  40. /// Update enum value Last if necessary.
  41. /// Update getAsString.
  42. ///
  43. enum class SyncScope {
  44. HIPSingleThread,
  45. HIPWavefront,
  46. HIPWorkgroup,
  47. HIPAgent,
  48. HIPSystem,
  49. OpenCLWorkGroup,
  50. OpenCLDevice,
  51. OpenCLAllSVMDevices,
  52. OpenCLSubGroup,
  53. Last = OpenCLSubGroup
  54. };
  55. inline llvm::StringRef getAsString(SyncScope S) {
  56. switch (S) {
  57. case SyncScope::HIPSingleThread:
  58. return "hip_singlethread";
  59. case SyncScope::HIPWavefront:
  60. return "hip_wavefront";
  61. case SyncScope::HIPWorkgroup:
  62. return "hip_workgroup";
  63. case SyncScope::HIPAgent:
  64. return "hip_agent";
  65. case SyncScope::HIPSystem:
  66. return "hip_system";
  67. case SyncScope::OpenCLWorkGroup:
  68. return "opencl_workgroup";
  69. case SyncScope::OpenCLDevice:
  70. return "opencl_device";
  71. case SyncScope::OpenCLAllSVMDevices:
  72. return "opencl_allsvmdevices";
  73. case SyncScope::OpenCLSubGroup:
  74. return "opencl_subgroup";
  75. }
  76. llvm_unreachable("Invalid synch scope");
  77. }
  78. /// Defines the kind of atomic scope models.
  79. enum class AtomicScopeModelKind { None, OpenCL, HIP };
  80. /// Defines the interface for synch scope model.
  81. class AtomicScopeModel {
  82. public:
  83. virtual ~AtomicScopeModel() {}
  84. /// Maps language specific synch scope values to internal
  85. /// SyncScope enum.
  86. virtual SyncScope map(unsigned S) const = 0;
  87. /// Check if the compile-time constant synch scope value
  88. /// is valid.
  89. virtual bool isValid(unsigned S) const = 0;
  90. /// Get all possible synch scope values that might be
  91. /// encountered at runtime for the current language.
  92. virtual ArrayRef<unsigned> getRuntimeValues() const = 0;
  93. /// If atomic builtin function is called with invalid
  94. /// synch scope value at runtime, it will fall back to a valid
  95. /// synch scope value returned by this function.
  96. virtual unsigned getFallBackValue() const = 0;
  97. /// Create an atomic scope model by AtomicScopeModelKind.
  98. /// \return an empty std::unique_ptr for AtomicScopeModelKind::None.
  99. static std::unique_ptr<AtomicScopeModel> create(AtomicScopeModelKind K);
  100. };
  101. /// Defines the synch scope model for OpenCL.
  102. class AtomicScopeOpenCLModel : public AtomicScopeModel {
  103. public:
  104. /// The enum values match the pre-defined macros
  105. /// __OPENCL_MEMORY_SCOPE_*, which are used to define memory_scope_*
  106. /// enums in opencl-c-base.h.
  107. enum ID {
  108. WorkGroup = 1,
  109. Device = 2,
  110. AllSVMDevices = 3,
  111. SubGroup = 4,
  112. Last = SubGroup
  113. };
  114. AtomicScopeOpenCLModel() {}
  115. SyncScope map(unsigned S) const override {
  116. switch (static_cast<ID>(S)) {
  117. case WorkGroup:
  118. return SyncScope::OpenCLWorkGroup;
  119. case Device:
  120. return SyncScope::OpenCLDevice;
  121. case AllSVMDevices:
  122. return SyncScope::OpenCLAllSVMDevices;
  123. case SubGroup:
  124. return SyncScope::OpenCLSubGroup;
  125. }
  126. llvm_unreachable("Invalid language synch scope value");
  127. }
  128. bool isValid(unsigned S) const override {
  129. return S >= static_cast<unsigned>(WorkGroup) &&
  130. S <= static_cast<unsigned>(Last);
  131. }
  132. ArrayRef<unsigned> getRuntimeValues() const override {
  133. static_assert(Last == SubGroup, "Does not include all synch scopes");
  134. static const unsigned Scopes[] = {
  135. static_cast<unsigned>(WorkGroup), static_cast<unsigned>(Device),
  136. static_cast<unsigned>(AllSVMDevices), static_cast<unsigned>(SubGroup)};
  137. return llvm::makeArrayRef(Scopes);
  138. }
  139. unsigned getFallBackValue() const override {
  140. return static_cast<unsigned>(AllSVMDevices);
  141. }
  142. };
  143. /// Defines the synch scope model for HIP.
  144. class AtomicScopeHIPModel : public AtomicScopeModel {
  145. public:
  146. /// The enum values match the pre-defined macros
  147. /// __HIP_MEMORY_SCOPE_*, which are used to define memory_scope_*
  148. /// enums in hip-c.h.
  149. enum ID {
  150. SingleThread = 1,
  151. Wavefront = 2,
  152. Workgroup = 3,
  153. Agent = 4,
  154. System = 5,
  155. Last = System
  156. };
  157. AtomicScopeHIPModel() {}
  158. SyncScope map(unsigned S) const override {
  159. switch (static_cast<ID>(S)) {
  160. case SingleThread:
  161. return SyncScope::HIPSingleThread;
  162. case Wavefront:
  163. return SyncScope::HIPWavefront;
  164. case Workgroup:
  165. return SyncScope::HIPWorkgroup;
  166. case Agent:
  167. return SyncScope::HIPAgent;
  168. case System:
  169. return SyncScope::HIPSystem;
  170. }
  171. llvm_unreachable("Invalid language synch scope value");
  172. }
  173. bool isValid(unsigned S) const override {
  174. return S >= static_cast<unsigned>(SingleThread) &&
  175. S <= static_cast<unsigned>(Last);
  176. }
  177. ArrayRef<unsigned> getRuntimeValues() const override {
  178. static_assert(Last == System, "Does not include all synch scopes");
  179. static const unsigned Scopes[] = {
  180. static_cast<unsigned>(SingleThread), static_cast<unsigned>(Wavefront),
  181. static_cast<unsigned>(Workgroup), static_cast<unsigned>(Agent),
  182. static_cast<unsigned>(System)};
  183. return llvm::makeArrayRef(Scopes);
  184. }
  185. unsigned getFallBackValue() const override {
  186. return static_cast<unsigned>(System);
  187. }
  188. };
  189. inline std::unique_ptr<AtomicScopeModel>
  190. AtomicScopeModel::create(AtomicScopeModelKind K) {
  191. switch (K) {
  192. case AtomicScopeModelKind::None:
  193. return std::unique_ptr<AtomicScopeModel>{};
  194. case AtomicScopeModelKind::OpenCL:
  195. return std::make_unique<AtomicScopeOpenCLModel>();
  196. case AtomicScopeModelKind::HIP:
  197. return std::make_unique<AtomicScopeHIPModel>();
  198. }
  199. llvm_unreachable("Invalid atomic scope model kind");
  200. }
  201. } // namespace clang
  202. #endif
  203. #ifdef __GNUC__
  204. #pragma GCC diagnostic pop
  205. #endif