1 //===-- llvm/Support/AtomicOrdering.h ---Atomic Ordering---------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// Atomic ordering constants.
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.
15 //===----------------------------------------------------------------------===//
17 #ifndef LLVM_SUPPORT_ATOMICORDERING_H
18 #define LLVM_SUPPORT_ATOMICORDERING_H
24 /// Atomic ordering for C11 / C++11's memody models.
26 /// These values cannot change because they are shared with standard library
27 /// implementations as well as with other compilers.
28 enum class AtomicOrderingCABI
{
37 bool operator<(AtomicOrderingCABI
, AtomicOrderingCABI
) = delete;
38 bool operator>(AtomicOrderingCABI
, AtomicOrderingCABI
) = delete;
39 bool operator<=(AtomicOrderingCABI
, AtomicOrderingCABI
) = delete;
40 bool operator>=(AtomicOrderingCABI
, AtomicOrderingCABI
) = delete;
42 // Validate an integral value which isn't known to fit within the enum's range
43 // is a valid AtomicOrderingCABI.
44 template <typename Int
> inline bool isValidAtomicOrderingCABI(Int I
) {
45 return (Int
)AtomicOrderingCABI::relaxed
<= I
&&
46 I
<= (Int
)AtomicOrderingCABI::seq_cst
;
49 /// Atomic ordering for LLVM's memory model.
51 /// C++ defines ordering as a lattice. LLVM supplements this with NotAtomic and
52 /// Unordered, which are both below the C++ orders.
54 /// not_atomic-->unordered-->relaxed-->release--------------->acq_rel-->seq_cst
55 /// \-->consume-->acquire--/
56 enum class AtomicOrdering
{
59 Monotonic
= 2, // Equivalent to C++'s relaxed.
60 // Consume = 3, // Not specified yet.
64 SequentiallyConsistent
= 7
67 bool operator<(AtomicOrdering
, AtomicOrdering
) = delete;
68 bool operator>(AtomicOrdering
, AtomicOrdering
) = delete;
69 bool operator<=(AtomicOrdering
, AtomicOrdering
) = delete;
70 bool operator>=(AtomicOrdering
, AtomicOrdering
) = delete;
72 // Validate an integral value which isn't known to fit within the enum's range
73 // is a valid AtomicOrdering.
74 template <typename Int
> inline bool isValidAtomicOrdering(Int I
) {
75 return static_cast<Int
>(AtomicOrdering::NotAtomic
) <= I
&&
76 I
<= static_cast<Int
>(AtomicOrdering::SequentiallyConsistent
);
79 /// String used by LLVM IR to represent atomic ordering.
80 inline const char *toIRString(AtomicOrdering ao
) {
81 static const char *names
[8] = {"not_atomic", "unordered", "monotonic",
82 "consume", "acquire", "release",
83 "acq_rel", "seq_cst"};
84 return names
[static_cast<size_t>(ao
)];
87 /// Returns true if ao is stronger than other as defined by the AtomicOrdering
88 /// lattice, which is based on C++'s definition.
89 inline bool isStrongerThan(AtomicOrdering ao
, AtomicOrdering other
) {
90 static const bool lookup
[8][8] = {
91 // NA UN RX CO AC RE AR SC
92 /* NotAtomic */ {false, false, false, false, false, false, false, false},
93 /* Unordered */ { true, false, false, false, false, false, false, false},
94 /* relaxed */ { true, true, false, false, false, false, false, false},
95 /* consume */ { true, true, true, false, false, false, false, false},
96 /* acquire */ { true, true, true, true, false, false, false, false},
97 /* release */ { true, true, true, false, false, false, false, false},
98 /* acq_rel */ { true, true, true, true, true, true, false, false},
99 /* seq_cst */ { true, true, true, true, true, true, true, false},
101 return lookup
[static_cast<size_t>(ao
)][static_cast<size_t>(other
)];
104 inline bool isAtLeastOrStrongerThan(AtomicOrdering ao
, AtomicOrdering other
) {
105 static const bool lookup
[8][8] = {
106 // NA UN RX CO AC RE AR SC
107 /* NotAtomic */ { true, false, false, false, false, false, false, false},
108 /* Unordered */ { true, true, false, false, false, false, false, false},
109 /* relaxed */ { true, true, true, false, false, false, false, false},
110 /* consume */ { true, true, true, true, false, false, false, false},
111 /* acquire */ { true, true, true, true, true, false, false, false},
112 /* release */ { true, true, true, false, false, true, false, false},
113 /* acq_rel */ { true, true, true, true, true, true, true, false},
114 /* seq_cst */ { true, true, true, true, true, true, true, true},
116 return lookup
[static_cast<size_t>(ao
)][static_cast<size_t>(other
)];
119 inline bool isStrongerThanUnordered(AtomicOrdering ao
) {
120 return isStrongerThan(ao
, AtomicOrdering::Unordered
);
123 inline bool isStrongerThanMonotonic(AtomicOrdering ao
) {
124 return isStrongerThan(ao
, AtomicOrdering::Monotonic
);
127 inline bool isAcquireOrStronger(AtomicOrdering ao
) {
128 return isAtLeastOrStrongerThan(ao
, AtomicOrdering::Acquire
);
131 inline bool isReleaseOrStronger(AtomicOrdering ao
) {
132 return isAtLeastOrStrongerThan(ao
, AtomicOrdering::Release
);
135 inline AtomicOrderingCABI
toCABI(AtomicOrdering ao
) {
136 static const AtomicOrderingCABI lookup
[8] = {
137 /* NotAtomic */ AtomicOrderingCABI::relaxed
,
138 /* Unordered */ AtomicOrderingCABI::relaxed
,
139 /* relaxed */ AtomicOrderingCABI::relaxed
,
140 /* consume */ AtomicOrderingCABI::consume
,
141 /* acquire */ AtomicOrderingCABI::acquire
,
142 /* release */ AtomicOrderingCABI::release
,
143 /* acq_rel */ AtomicOrderingCABI::acq_rel
,
144 /* seq_cst */ AtomicOrderingCABI::seq_cst
,
146 return lookup
[static_cast<size_t>(ao
)];
149 } // end namespace llvm
151 #endif // LLVM_SUPPORT_ATOMICORDERING_H