1//===-- llvm/Support/AtomicOrdering.h ---Atomic Ordering---------*- 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/// Atomic ordering constants. 11/// 12/// These values are used by LLVM to represent atomic ordering for C++11's 13/// memory model and more, as detailed in docs/Atomics.rst. 14/// 15//===----------------------------------------------------------------------===// 16 17#ifndef LLVM_SUPPORT_ATOMICORDERING_H 18#define LLVM_SUPPORT_ATOMICORDERING_H 19 20#include <cstddef> 21 22namespace llvm { 23 24/// Atomic ordering for C11 / C++11's memory models. 25/// 26/// These values cannot change because they are shared with standard library 27/// implementations as well as with other compilers. 28enum class AtomicOrderingCABI { 29 relaxed = 0, 30 consume = 1, 31 acquire = 2, 32 release = 3, 33 acq_rel = 4, 34 seq_cst = 5, 35}; 36 37bool operator<(AtomicOrderingCABI, AtomicOrderingCABI) = delete; 38bool operator>(AtomicOrderingCABI, AtomicOrderingCABI) = delete; 39bool operator<=(AtomicOrderingCABI, AtomicOrderingCABI) = delete; 40bool operator>=(AtomicOrderingCABI, AtomicOrderingCABI) = delete; 41 42// Validate an integral value which isn't known to fit within the enum's range 43// is a valid AtomicOrderingCABI. 44template <typename Int> inline bool isValidAtomicOrderingCABI(Int I) { 45 return (Int)AtomicOrderingCABI::relaxed <= I && 46 I <= (Int)AtomicOrderingCABI::seq_cst; 47} 48 49/// Atomic ordering for LLVM's memory model. 50/// 51/// C++ defines ordering as a lattice. LLVM supplements this with NotAtomic and 52/// Unordered, which are both below the C++ orders. 53/// 54/// not_atomic-->unordered-->relaxed-->release--------------->acq_rel-->seq_cst 55/// \-->consume-->acquire--/ 56enum class AtomicOrdering : unsigned { 57 NotAtomic = 0, 58 Unordered = 1, 59 Monotonic = 2, // Equivalent to C++'s relaxed. 60 // Consume = 3, // Not specified yet. 61 Acquire = 4, 62 Release = 5, 63 AcquireRelease = 6, 64 SequentiallyConsistent = 7, 65 LAST = SequentiallyConsistent 66}; 67 68bool operator<(AtomicOrdering, AtomicOrdering) = delete; 69bool operator>(AtomicOrdering, AtomicOrdering) = delete; 70bool operator<=(AtomicOrdering, AtomicOrdering) = delete; 71bool operator>=(AtomicOrdering, AtomicOrdering) = delete; 72 73// Validate an integral value which isn't known to fit within the enum's range 74// is a valid AtomicOrdering. 75template <typename Int> inline bool isValidAtomicOrdering(Int I) { 76 return static_cast<Int>(AtomicOrdering::NotAtomic) <= I && 77 I <= static_cast<Int>(AtomicOrdering::SequentiallyConsistent) && 78 I != 3; 79} 80 81/// String used by LLVM IR to represent atomic ordering. 82inline const char *toIRString(AtomicOrdering ao) { 83 static const char *names[8] = {"not_atomic", "unordered", "monotonic", 84 "consume", "acquire", "release", 85 "acq_rel", "seq_cst"}; 86 return names[static_cast<size_t>(ao)]; 87} 88 89/// Returns true if ao is stronger than other as defined by the AtomicOrdering 90/// lattice, which is based on C++'s definition. 91inline bool isStrongerThan(AtomicOrdering AO, AtomicOrdering Other) { 92 static const bool lookup[8][8] = { 93 // NA UN RX CO AC RE AR SC 94 /* NotAtomic */ {false, false, false, false, false, false, false, false}, 95 /* Unordered */ { true, false, false, false, false, false, false, false}, 96 /* relaxed */ { true, true, false, false, false, false, false, false}, 97 /* consume */ { true, true, true, false, false, false, false, false}, 98 /* acquire */ { true, true, true, true, false, false, false, false}, 99 /* release */ { true, true, true, false, false, false, false, false}, 100 /* acq_rel */ { true, true, true, true, true, true, false, false}, 101 /* seq_cst */ { true, true, true, true, true, true, true, false}, 102 }; 103 return lookup[static_cast<size_t>(AO)][static_cast<size_t>(Other)]; 104} 105 106inline bool isAtLeastOrStrongerThan(AtomicOrdering AO, AtomicOrdering Other) { 107 static const bool lookup[8][8] = { 108 // NA UN RX CO AC RE AR SC 109 /* NotAtomic */ { true, false, false, false, false, false, false, false}, 110 /* Unordered */ { true, true, false, false, false, false, false, false}, 111 /* relaxed */ { true, true, true, false, false, false, false, false}, 112 /* consume */ { true, true, true, true, false, false, false, false}, 113 /* acquire */ { true, true, true, true, true, false, false, false}, 114 /* release */ { true, true, true, false, false, true, false, false}, 115 /* acq_rel */ { true, true, true, true, true, true, true, false}, 116 /* seq_cst */ { true, true, true, true, true, true, true, true}, 117 }; 118 return lookup[static_cast<size_t>(AO)][static_cast<size_t>(Other)]; 119} 120 121inline bool isStrongerThanUnordered(AtomicOrdering AO) { 122 return isStrongerThan(AO, AtomicOrdering::Unordered); 123} 124 125inline bool isStrongerThanMonotonic(AtomicOrdering AO) { 126 return isStrongerThan(AO, AtomicOrdering::Monotonic); 127} 128 129inline bool isAcquireOrStronger(AtomicOrdering AO) { 130 return isAtLeastOrStrongerThan(AO, AtomicOrdering::Acquire); 131} 132 133inline bool isReleaseOrStronger(AtomicOrdering AO) { 134 return isAtLeastOrStrongerThan(AO, AtomicOrdering::Release); 135} 136 137/// Return a single atomic ordering that is at least as strong as both the \p AO 138/// and \p Other orderings for an atomic operation. 139inline AtomicOrdering getMergedAtomicOrdering(AtomicOrdering AO, 140 AtomicOrdering Other) { 141 if ((AO == AtomicOrdering::Acquire && Other == AtomicOrdering::Release) || 142 (AO == AtomicOrdering::Release && Other == AtomicOrdering::Acquire)) 143 return AtomicOrdering::AcquireRelease; 144 return isStrongerThan(AO, Other) ? AO : Other; 145} 146 147inline AtomicOrderingCABI toCABI(AtomicOrdering AO) { 148 static const AtomicOrderingCABI lookup[8] = { 149 /* NotAtomic */ AtomicOrderingCABI::relaxed, 150 /* Unordered */ AtomicOrderingCABI::relaxed, 151 /* relaxed */ AtomicOrderingCABI::relaxed, 152 /* consume */ AtomicOrderingCABI::consume, 153 /* acquire */ AtomicOrderingCABI::acquire, 154 /* release */ AtomicOrderingCABI::release, 155 /* acq_rel */ AtomicOrderingCABI::acq_rel, 156 /* seq_cst */ AtomicOrderingCABI::seq_cst, 157 }; 158 return lookup[static_cast<size_t>(AO)]; 159} 160 161} // end namespace llvm 162 163#endif // LLVM_SUPPORT_ATOMICORDERING_H 164