Coverage Report

Created: 2022-01-18 06:27

/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
9.90k
AtomicScopeModel::create(AtomicScopeModelKind K) {
210
9.90k
  switch (K) {
211
8.82k
  case AtomicScopeModelKind::None:
212
8.82k
    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
9.90k
  }
218
0
  llvm_unreachable("Invalid atomic scope model kind");
219
0
}
220
} // namespace clang
221
222
#endif