Home | History | Annotate | Line # | Download | only in Basic
      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   OpenCLWorkGroup,
     44   OpenCLDevice,
     45   OpenCLAllSVMDevices,
     46   OpenCLSubGroup,
     47   Last = OpenCLSubGroup
     48 };
     49 
     50 inline llvm::StringRef getAsString(SyncScope S) {
     51   switch (S) {
     52   case SyncScope::OpenCLWorkGroup:
     53     return "opencl_workgroup";
     54   case SyncScope::OpenCLDevice:
     55     return "opencl_device";
     56   case SyncScope::OpenCLAllSVMDevices:
     57     return "opencl_allsvmdevices";
     58   case SyncScope::OpenCLSubGroup:
     59     return "opencl_subgroup";
     60   }
     61   llvm_unreachable("Invalid synch scope");
     62 }
     63 
     64 /// Defines the kind of atomic scope models.
     65 enum class AtomicScopeModelKind { None, OpenCL };
     66 
     67 /// Defines the interface for synch scope model.
     68 class AtomicScopeModel {
     69 public:
     70   virtual ~AtomicScopeModel() {}
     71   /// Maps language specific synch scope values to internal
     72   /// SyncScope enum.
     73   virtual SyncScope map(unsigned S) const = 0;
     74 
     75   /// Check if the compile-time constant synch scope value
     76   /// is valid.
     77   virtual bool isValid(unsigned S) const = 0;
     78 
     79   /// Get all possible synch scope values that might be
     80   /// encountered at runtime for the current language.
     81   virtual ArrayRef<unsigned> getRuntimeValues() const = 0;
     82 
     83   /// If atomic builtin function is called with invalid
     84   /// synch scope value at runtime, it will fall back to a valid
     85   /// synch scope value returned by this function.
     86   virtual unsigned getFallBackValue() const = 0;
     87 
     88   /// Create an atomic scope model by AtomicScopeModelKind.
     89   /// \return an empty std::unique_ptr for AtomicScopeModelKind::None.
     90   static std::unique_ptr<AtomicScopeModel> create(AtomicScopeModelKind K);
     91 };
     92 
     93 /// Defines the synch scope model for OpenCL.
     94 class AtomicScopeOpenCLModel : public AtomicScopeModel {
     95 public:
     96   /// The enum values match the pre-defined macros
     97   /// __OPENCL_MEMORY_SCOPE_*, which are used to define memory_scope_*
     98   /// enums in opencl-c-base.h.
     99   enum ID {
    100     WorkGroup = 1,
    101     Device = 2,
    102     AllSVMDevices = 3,
    103     SubGroup = 4,
    104     Last = SubGroup
    105   };
    106 
    107   AtomicScopeOpenCLModel() {}
    108 
    109   SyncScope map(unsigned S) const override {
    110     switch (static_cast<ID>(S)) {
    111     case WorkGroup:
    112       return SyncScope::OpenCLWorkGroup;
    113     case Device:
    114       return SyncScope::OpenCLDevice;
    115     case AllSVMDevices:
    116       return SyncScope::OpenCLAllSVMDevices;
    117     case SubGroup:
    118       return SyncScope::OpenCLSubGroup;
    119     }
    120     llvm_unreachable("Invalid language synch scope value");
    121   }
    122 
    123   bool isValid(unsigned S) const override {
    124     return S >= static_cast<unsigned>(WorkGroup) &&
    125            S <= static_cast<unsigned>(Last);
    126   }
    127 
    128   ArrayRef<unsigned> getRuntimeValues() const override {
    129     static_assert(Last == SubGroup, "Does not include all synch scopes");
    130     static const unsigned Scopes[] = {
    131         static_cast<unsigned>(WorkGroup), static_cast<unsigned>(Device),
    132         static_cast<unsigned>(AllSVMDevices), static_cast<unsigned>(SubGroup)};
    133     return llvm::makeArrayRef(Scopes);
    134   }
    135 
    136   unsigned getFallBackValue() const override {
    137     return static_cast<unsigned>(AllSVMDevices);
    138   }
    139 };
    140 
    141 inline std::unique_ptr<AtomicScopeModel>
    142 AtomicScopeModel::create(AtomicScopeModelKind K) {
    143   switch (K) {
    144   case AtomicScopeModelKind::None:
    145     return std::unique_ptr<AtomicScopeModel>{};
    146   case AtomicScopeModelKind::OpenCL:
    147     return std::make_unique<AtomicScopeOpenCLModel>();
    148   }
    149   llvm_unreachable("Invalid atomic scope model kind");
    150 }
    151 }
    152 
    153 #endif
    154