SyncScope.h revision 360784
194742Sobrien//===--- SyncScope.h - Atomic synchronization scopes ------------*- C++ -*-===//
294742Sobrien//
3146890Speter// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4146890Speter// See https://llvm.org/LICENSE.txt for license information.
5179626Speter// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6146890Speter//
7146890Speter//===----------------------------------------------------------------------===//
8146890Speter///
9146890Speter/// \file
10146890Speter/// Provides definitions for the atomic synchronization scopes.
11146890Speter///
12146890Speter//===----------------------------------------------------------------------===//
13146890Speter
14146890Speter#ifndef LLVM_CLANG_BASIC_SYNCSCOPE_H
15146890Speter#define LLVM_CLANG_BASIC_SYNCSCOPE_H
16146890Speter
17146890Speter#include "clang/Basic/LangOptions.h"
18146890Speter#include "llvm/ADT/ArrayRef.h"
19146890Speter#include "llvm/ADT/StringRef.h"
20146890Speter#include <memory>
2194742Sobrien
2295253Srunamespace clang {
23159014Sjmg
2494742Sobrien/// Defines synch scope values used internally by clang.
2596991Srwatson///
2696991Srwatson/// The enum values start from 0 and are contiguous. They are mainly used for
2796991Srwatson/// enumerating all supported synch scope values and mapping them to LLVM
28102773Srwatson/// synch scopes. Their numerical values may be different from the corresponding
29102773Srwatson/// synch scope enums used in source languages.
30156279Srwatson///
31156279Srwatson/// In atomic builtin and expressions, language-specific synch scope enums are
3294917Simp/// used. Currently only OpenCL memory scope enums are supported and assumed
33126445Sobrien/// to be used by all languages. However, in the future, other languages may
3494917Simp/// define their own set of synch scope enums. The language-specific synch scope
35146933Simp/// values are represented by class AtomicScopeModel and its derived classes.
3694847Sjhb///
3794847Sjhb/// To add a new enum value:
3894847Sjhb///   Add the enum value to enum class SyncScope.
39158888Swilko///   Update enum value Last if necessary.
40158888Swilko///   Update getAsString.
4194915Sken///
4299607Smjacobenum class SyncScope {
4394915Sken  OpenCLWorkGroup,
4494915Sken  OpenCLDevice,
4594915Sken  OpenCLAllSVMDevices,
4694915Sken  OpenCLSubGroup,
4794915Sken  Last = OpenCLSubGroup
4894915Sken};
4994915Sken
5094915Skeninline llvm::StringRef getAsString(SyncScope S) {
51169922Sjfv  switch (S) {
5297611Sbillf  case SyncScope::OpenCLWorkGroup:
5394918Sgshapiro    return "opencl_workgroup";
5494918Sgshapiro  case SyncScope::OpenCLDevice:
5594918Sgshapiro    return "opencl_device";
5694918Sgshapiro  case SyncScope::OpenCLAllSVMDevices:
5794918Sgshapiro    return "opencl_allsvmdevices";
58106187Sdes  case SyncScope::OpenCLSubGroup:
59106187Sdes    return "opencl_subgroup";
6095455Sdes  }
6198750Sdes  llvm_unreachable("Invalid synch scope");
6299606Sdes}
6399606Sdes
6499606Sdes/// Defines the kind of atomic scope models.
6596268Sgadenum class AtomicScopeModelKind { None, OpenCL };
6696268Sgad
67116233Sgad/// Defines the interface for synch scope model.
68139390Sgadclass AtomicScopeModel {
69139390Sgadpublic:
70139390Sgad  virtual ~AtomicScopeModel() {}
7196332Speter  /// Maps language specific synch scope values to internal
7296332Speter  /// SyncScope enum.
7396332Speter  virtual SyncScope map(unsigned S) const = 0;
74100314Sru
75146921Sru  /// Check if the compile-time constant synch scope value
76146921Sru  /// is valid.
7797611Sbillf  virtual bool isValid(unsigned S) const = 0;
78190171Srnoland
79111061Sjmallett  /// Get all possible synch scope values that might be
8099732Sjoerg  /// encountered at runtime for the current language.
8199732Sjoerg  virtual ArrayRef<unsigned> getRuntimeValues() const = 0;
82115825Sfanf
83126445Sobrien  /// If atomic builtin function is called with invalid
84117645Sdwmalone  /// synch scope value at runtime, it will fall back to a valid
85118204Sbp  /// synch scope value returned by this function.
86118204Sbp  virtual unsigned getFallBackValue() const = 0;
87118204Sbp
88118204Sbp  /// Create an atomic scope model by AtomicScopeModelKind.
89127337Smlaier  /// \return an empty std::unique_ptr for AtomicScopeModelKind::None.
90126445Sobrien  static std::unique_ptr<AtomicScopeModel> create(AtomicScopeModelKind K);
91146837Sobrien};
92146837Sobrien
93146837Sobrien/// Defines the synch scope model for OpenCL.
94146837Sobrienclass AtomicScopeOpenCLModel : public AtomicScopeModel {
95133182Spjdpublic:
96148779Spjd  /// The enum values match the pre-defined macros
97133182Spjd  /// __OPENCL_MEMORY_SCOPE_*, which are used to define memory_scope_*
98133182Spjd  /// enums in opencl-c-base.h.
99133182Spjd  enum ID {
100133182Spjd    WorkGroup = 1,
101133841Spjd    Device = 2,
102143521Spjd    AllSVMDevices = 3,
103133182Spjd    SubGroup = 4,
104148779Spjd    Last = SubGroup
105133182Spjd  };
106168419Spjd
107132311Salfred  AtomicScopeOpenCLModel() {}
108132311Salfred
109132311Salfred  SyncScope map(unsigned S) const override {
110132268Salfred    switch (static_cast<ID>(S)) {
111158323Srodrigc    case WorkGroup:
112158323Srodrigc      return SyncScope::OpenCLWorkGroup;
113195405Sflz    case Device:
114146960Simp      return SyncScope::OpenCLDevice;
115148772Scperciva    case AllSVMDevices:
116148871Scperciva      return SyncScope::OpenCLAllSVMDevices;
117161748Scperciva    case SubGroup:
118162226Ssimon      return SyncScope::OpenCLSubGroup;
119149464Semax    }
120149464Semax    llvm_unreachable("Invalid language synch scope value");
121149464Semax  }
122149464Semax
123149464Semax  bool isValid(unsigned S) const override {
124151618Sceri    return S >= static_cast<unsigned>(WorkGroup) &&
125179534Srafan           S <= static_cast<unsigned>(Last);
126200194Scperciva  }
127200194Scperciva
128204061Sedwin  ArrayRef<unsigned> getRuntimeValues() const override {
129204061Sedwin    static_assert(Last == SubGroup, "Does not include all synch scopes");
130204061Sedwin    static const unsigned Scopes[] = {
131204061Sedwin        static_cast<unsigned>(WorkGroup), static_cast<unsigned>(Device),
132204061Sedwin        static_cast<unsigned>(AllSVMDevices), static_cast<unsigned>(SubGroup)};
133204061Sedwin    return llvm::makeArrayRef(Scopes);
134115822Sdougb  }
135115822Sdougb
136115822Sdougb  unsigned getFallBackValue() const override {
137115822Sdougb    return static_cast<unsigned>(AllSVMDevices);
138115822Sdougb  }
139115822Sdougb};
140115822Sdougb
141146629Sschweikhinline std::unique_ptr<AtomicScopeModel>
142146629SschweikhAtomicScopeModel::create(AtomicScopeModelKind K) {
143146629Sschweikh  switch (K) {
144115822Sdougb  case AtomicScopeModelKind::None:
145115822Sdougb    return std::unique_ptr<AtomicScopeModel>{};
146146586Sschweikh  case AtomicScopeModelKind::OpenCL:
147115822Sdougb    return std::make_unique<AtomicScopeOpenCLModel>();
148  }
149  llvm_unreachable("Invalid atomic scope model kind");
150}
151}
152
153#endif
154