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, Other: AtomicOrdering::Unordered);
123}
124
125inline bool isStrongerThanMonotonic(AtomicOrdering AO) {
126 return isStrongerThan(AO, Other: AtomicOrdering::Monotonic);
127}
128
129inline bool isAcquireOrStronger(AtomicOrdering AO) {
130 return isAtLeastOrStrongerThan(AO, Other: AtomicOrdering::Acquire);
131}
132
133inline bool isReleaseOrStronger(AtomicOrdering AO) {
134 return isAtLeastOrStrongerThan(AO, Other: 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

source code of llvm/include/llvm/Support/AtomicOrdering.h