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