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