Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:51

0001 //===--- SyncScope.h - Atomic synchronization scopes ------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 /// Provides definitions for the atomic synchronization scopes.
0011 ///
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_BASIC_SYNCSCOPE_H
0015 #define LLVM_CLANG_BASIC_SYNCSCOPE_H
0016 
0017 #include "clang/Basic/LangOptions.h"
0018 #include "llvm/ADT/ArrayRef.h"
0019 #include "llvm/ADT/StringRef.h"
0020 #include <memory>
0021 
0022 namespace clang {
0023 
0024 /// Defines synch scope values used internally by clang.
0025 ///
0026 /// The enum values start from 0 and are contiguous. They are mainly used for
0027 /// enumerating all supported synch scope values and mapping them to LLVM
0028 /// synch scopes. Their numerical values may be different from the corresponding
0029 /// synch scope enums used in source languages.
0030 ///
0031 /// In atomic builtin and expressions, language-specific synch scope enums are
0032 /// used. Currently only OpenCL memory scope enums are supported and assumed
0033 /// to be used by all languages. However, in the future, other languages may
0034 /// define their own set of synch scope enums. The language-specific synch scope
0035 /// values are represented by class AtomicScopeModel and its derived classes.
0036 ///
0037 /// To add a new enum value:
0038 ///   Add the enum value to enum class SyncScope.
0039 ///   Update enum value Last if necessary.
0040 ///   Update getAsString.
0041 ///
0042 enum class SyncScope {
0043   SystemScope,
0044   DeviceScope,
0045   WorkgroupScope,
0046   WavefrontScope,
0047   SingleScope,
0048   HIPSingleThread,
0049   HIPWavefront,
0050   HIPWorkgroup,
0051   HIPAgent,
0052   HIPSystem,
0053   OpenCLWorkGroup,
0054   OpenCLDevice,
0055   OpenCLAllSVMDevices,
0056   OpenCLSubGroup,
0057   Last = OpenCLSubGroup
0058 };
0059 
0060 inline llvm::StringRef getAsString(SyncScope S) {
0061   switch (S) {
0062   case SyncScope::SystemScope:
0063     return "system_scope";
0064   case SyncScope::DeviceScope:
0065     return "device_scope";
0066   case SyncScope::WorkgroupScope:
0067     return "workgroup_scope";
0068   case SyncScope::WavefrontScope:
0069     return "wavefront_scope";
0070   case SyncScope::SingleScope:
0071     return "single_scope";
0072   case SyncScope::HIPSingleThread:
0073     return "hip_singlethread";
0074   case SyncScope::HIPWavefront:
0075     return "hip_wavefront";
0076   case SyncScope::HIPWorkgroup:
0077     return "hip_workgroup";
0078   case SyncScope::HIPAgent:
0079     return "hip_agent";
0080   case SyncScope::HIPSystem:
0081     return "hip_system";
0082   case SyncScope::OpenCLWorkGroup:
0083     return "opencl_workgroup";
0084   case SyncScope::OpenCLDevice:
0085     return "opencl_device";
0086   case SyncScope::OpenCLAllSVMDevices:
0087     return "opencl_allsvmdevices";
0088   case SyncScope::OpenCLSubGroup:
0089     return "opencl_subgroup";
0090   }
0091   llvm_unreachable("Invalid synch scope");
0092 }
0093 
0094 /// Defines the kind of atomic scope models.
0095 enum class AtomicScopeModelKind { None, OpenCL, HIP, Generic };
0096 
0097 /// Defines the interface for synch scope model.
0098 class AtomicScopeModel {
0099 public:
0100   virtual ~AtomicScopeModel() {}
0101   /// Maps language specific synch scope values to internal
0102   /// SyncScope enum.
0103   virtual SyncScope map(unsigned S) const = 0;
0104 
0105   /// Check if the compile-time constant synch scope value
0106   /// is valid.
0107   virtual bool isValid(unsigned S) const = 0;
0108 
0109   /// Get all possible synch scope values that might be
0110   /// encountered at runtime for the current language.
0111   virtual ArrayRef<unsigned> getRuntimeValues() const = 0;
0112 
0113   /// If atomic builtin function is called with invalid
0114   /// synch scope value at runtime, it will fall back to a valid
0115   /// synch scope value returned by this function.
0116   virtual unsigned getFallBackValue() const = 0;
0117 
0118   /// Create an atomic scope model by AtomicScopeModelKind.
0119   /// \return an empty std::unique_ptr for AtomicScopeModelKind::None.
0120   static std::unique_ptr<AtomicScopeModel> create(AtomicScopeModelKind K);
0121 };
0122 
0123 /// Defines the synch scope model for OpenCL.
0124 class AtomicScopeOpenCLModel : public AtomicScopeModel {
0125 public:
0126   /// The enum values match the pre-defined macros
0127   /// __OPENCL_MEMORY_SCOPE_*, which are used to define memory_scope_*
0128   /// enums in opencl-c-base.h.
0129   enum ID {
0130     WorkGroup = 1,
0131     Device = 2,
0132     AllSVMDevices = 3,
0133     SubGroup = 4,
0134     Last = SubGroup
0135   };
0136 
0137   AtomicScopeOpenCLModel() {}
0138 
0139   SyncScope map(unsigned S) const override {
0140     switch (static_cast<ID>(S)) {
0141     case WorkGroup:
0142       return SyncScope::OpenCLWorkGroup;
0143     case Device:
0144       return SyncScope::OpenCLDevice;
0145     case AllSVMDevices:
0146       return SyncScope::OpenCLAllSVMDevices;
0147     case SubGroup:
0148       return SyncScope::OpenCLSubGroup;
0149     }
0150     llvm_unreachable("Invalid language synch scope value");
0151   }
0152 
0153   bool isValid(unsigned S) const override {
0154     return S >= static_cast<unsigned>(WorkGroup) &&
0155            S <= static_cast<unsigned>(Last);
0156   }
0157 
0158   ArrayRef<unsigned> getRuntimeValues() const override {
0159     static_assert(Last == SubGroup, "Does not include all synch scopes");
0160     static const unsigned Scopes[] = {
0161         static_cast<unsigned>(WorkGroup), static_cast<unsigned>(Device),
0162         static_cast<unsigned>(AllSVMDevices), static_cast<unsigned>(SubGroup)};
0163     return llvm::ArrayRef(Scopes);
0164   }
0165 
0166   unsigned getFallBackValue() const override {
0167     return static_cast<unsigned>(AllSVMDevices);
0168   }
0169 };
0170 
0171 /// Defines the synch scope model for HIP.
0172 class AtomicScopeHIPModel : public AtomicScopeModel {
0173 public:
0174   /// The enum values match the pre-defined macros
0175   /// __HIP_MEMORY_SCOPE_*, which are used to define memory_scope_*
0176   /// enums in hip-c.h.
0177   enum ID {
0178     SingleThread = 1,
0179     Wavefront = 2,
0180     Workgroup = 3,
0181     Agent = 4,
0182     System = 5,
0183     Last = System
0184   };
0185 
0186   AtomicScopeHIPModel() {}
0187 
0188   SyncScope map(unsigned S) const override {
0189     switch (static_cast<ID>(S)) {
0190     case SingleThread:
0191       return SyncScope::HIPSingleThread;
0192     case Wavefront:
0193       return SyncScope::HIPWavefront;
0194     case Workgroup:
0195       return SyncScope::HIPWorkgroup;
0196     case Agent:
0197       return SyncScope::HIPAgent;
0198     case System:
0199       return SyncScope::HIPSystem;
0200     }
0201     llvm_unreachable("Invalid language synch scope value");
0202   }
0203 
0204   bool isValid(unsigned S) const override {
0205     return S >= static_cast<unsigned>(SingleThread) &&
0206            S <= static_cast<unsigned>(Last);
0207   }
0208 
0209   ArrayRef<unsigned> getRuntimeValues() const override {
0210     static_assert(Last == System, "Does not include all synch scopes");
0211     static const unsigned Scopes[] = {
0212         static_cast<unsigned>(SingleThread), static_cast<unsigned>(Wavefront),
0213         static_cast<unsigned>(Workgroup), static_cast<unsigned>(Agent),
0214         static_cast<unsigned>(System)};
0215     return llvm::ArrayRef(Scopes);
0216   }
0217 
0218   unsigned getFallBackValue() const override {
0219     return static_cast<unsigned>(System);
0220   }
0221 };
0222 
0223 /// Defines the generic atomic scope model.
0224 class AtomicScopeGenericModel : public AtomicScopeModel {
0225 public:
0226   /// The enum values match predefined built-in macros __ATOMIC_SCOPE_*.
0227   enum ID {
0228     System = 0,
0229     Device = 1,
0230     Workgroup = 2,
0231     Wavefront = 3,
0232     Single = 4,
0233     Last = Single
0234   };
0235 
0236   AtomicScopeGenericModel() = default;
0237 
0238   SyncScope map(unsigned S) const override {
0239     switch (static_cast<ID>(S)) {
0240     case Device:
0241       return SyncScope::DeviceScope;
0242     case System:
0243       return SyncScope::SystemScope;
0244     case Workgroup:
0245       return SyncScope::WorkgroupScope;
0246     case Wavefront:
0247       return SyncScope::WavefrontScope;
0248     case Single:
0249       return SyncScope::SingleScope;
0250     }
0251     llvm_unreachable("Invalid language sync scope value");
0252   }
0253 
0254   bool isValid(unsigned S) const override {
0255     return S <= static_cast<unsigned>(Last);
0256   }
0257 
0258   ArrayRef<unsigned> getRuntimeValues() const override {
0259     static_assert(Last == Single, "Does not include all sync scopes");
0260     static const unsigned Scopes[] = {
0261         static_cast<unsigned>(Device), static_cast<unsigned>(System),
0262         static_cast<unsigned>(Workgroup), static_cast<unsigned>(Wavefront),
0263         static_cast<unsigned>(Single)};
0264     return llvm::ArrayRef(Scopes);
0265   }
0266 
0267   unsigned getFallBackValue() const override {
0268     return static_cast<unsigned>(System);
0269   }
0270 };
0271 
0272 inline std::unique_ptr<AtomicScopeModel>
0273 AtomicScopeModel::create(AtomicScopeModelKind K) {
0274   switch (K) {
0275   case AtomicScopeModelKind::None:
0276     return std::unique_ptr<AtomicScopeModel>{};
0277   case AtomicScopeModelKind::OpenCL:
0278     return std::make_unique<AtomicScopeOpenCLModel>();
0279   case AtomicScopeModelKind::HIP:
0280     return std::make_unique<AtomicScopeHIPModel>();
0281   case AtomicScopeModelKind::Generic:
0282     return std::make_unique<AtomicScopeGenericModel>();
0283   }
0284   llvm_unreachable("Invalid atomic scope model kind");
0285 }
0286 } // namespace clang
0287 
0288 #endif