1 //===--- SyncScope.h - Atomic synchronization scopes ------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief Provides definitions for the atomic synchronization scopes.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_BASIC_SYNCSCOPE_H
16 #define LLVM_CLANG_BASIC_SYNCSCOPE_H
18 #include "clang/Basic/LangOptions.h"
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/StringRef.h"
25 /// \brief Defines synch scope values used internally by clang.
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.
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.
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.
43 enum class SyncScope {
51 inline llvm::StringRef getAsString(SyncScope S) {
53 case SyncScope::OpenCLWorkGroup:
54 return "opencl_workgroup";
55 case SyncScope::OpenCLDevice:
56 return "opencl_device";
57 case SyncScope::OpenCLAllSVMDevices:
58 return "opencl_allsvmdevices";
59 case SyncScope::OpenCLSubGroup:
60 return "opencl_subgroup";
62 llvm_unreachable("Invalid synch scope");
65 /// \brief Defines the kind of atomic scope models.
66 enum class AtomicScopeModelKind { None, OpenCL };
68 /// \brief Defines the interface for synch scope model.
69 class AtomicScopeModel {
71 virtual ~AtomicScopeModel() {}
72 /// \brief Maps language specific synch scope values to internal
74 virtual SyncScope map(unsigned S) const = 0;
76 /// \brief Check if the compile-time constant synch scope value
78 virtual bool isValid(unsigned S) const = 0;
80 /// \brief Get all possible synch scope values that might be
81 /// encountered at runtime for the current language.
82 virtual ArrayRef<unsigned> getRuntimeValues() const = 0;
84 /// \brief If atomic builtin function is called with invalid
85 /// synch scope value at runtime, it will fall back to a valid
86 /// synch scope value returned by this function.
87 virtual unsigned getFallBackValue() const = 0;
89 /// \brief Create an atomic scope model by AtomicScopeModelKind.
90 /// \return an empty std::unique_ptr for AtomicScopeModelKind::None.
91 static std::unique_ptr<AtomicScopeModel> create(AtomicScopeModelKind K);
94 /// \brief Defines the synch scope model for OpenCL.
95 class AtomicScopeOpenCLModel : public AtomicScopeModel {
97 /// The enum values match the pre-defined macros
98 /// __OPENCL_MEMORY_SCOPE_*, which are used to define memory_scope_*
99 /// enums in opencl-c.h.
108 AtomicScopeOpenCLModel() {}
110 SyncScope map(unsigned S) const override {
111 switch (static_cast<ID>(S)) {
113 return SyncScope::OpenCLWorkGroup;
115 return SyncScope::OpenCLDevice;
117 return SyncScope::OpenCLAllSVMDevices;
119 return SyncScope::OpenCLSubGroup;
121 llvm_unreachable("Invalid language synch scope value");
124 bool isValid(unsigned S) const override {
125 return S >= static_cast<unsigned>(WorkGroup) &&
126 S <= static_cast<unsigned>(Last);
129 ArrayRef<unsigned> getRuntimeValues() const override {
130 static_assert(Last == SubGroup, "Does not include all synch scopes");
131 static const unsigned Scopes[] = {
132 static_cast<unsigned>(WorkGroup), static_cast<unsigned>(Device),
133 static_cast<unsigned>(AllSVMDevices), static_cast<unsigned>(SubGroup)};
134 return llvm::makeArrayRef(Scopes);
137 unsigned getFallBackValue() const override {
138 return static_cast<unsigned>(AllSVMDevices);
142 inline std::unique_ptr<AtomicScopeModel>
143 AtomicScopeModel::create(AtomicScopeModelKind K) {
145 case AtomicScopeModelKind::None:
146 return std::unique_ptr<AtomicScopeModel>{};
147 case AtomicScopeModelKind::OpenCL:
148 return llvm::make_unique<AtomicScopeOpenCLModel>();
150 llvm_unreachable("Invalid atomic scope model kind");