llvm.org GIT mirror llvm / 1b711b2
NFC: unify clang / LLVM atomic ordering This makes the C11 / C++11 *ABI* atomic ordering accessible from LLVM, as discussed in http://reviews.llvm.org/D18200#inline-151433 This re-applies r266573 which I had reverted in r266576. Original review: http://reviews.llvm.org/D18875 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266640 91177308-0d34-0410-b5e6-96231b3b80d8 JF Bastien 4 years ago
3 changed file(s) with 160 addition(s) and 118 deletion(s). Raw diff Collapse all Expand all
2424 #include "llvm/IR/DerivedTypes.h"
2525 #include "llvm/IR/Function.h"
2626 #include "llvm/IR/InstrTypes.h"
27 #include "llvm/Support/AtomicOrdering.h"
2728 #include "llvm/Support/ErrorHandling.h"
2829 #include
2930
3536 class DataLayout;
3637 class LLVMContext;
3738
38 /// C++ defines ordering as a lattice. LLVM supplements this with NotAtomic and
39 /// Unordered, which are both below the C++ orders. See docs/Atomics.rst for
40 /// details.
41 ///
42 /// not_atomic-->unordered-->relaxed-->release--------------->acq_rel-->seq_cst
43 /// \-->consume-->acquire--/
44 enum class AtomicOrdering {
45 NotAtomic = 0,
46 Unordered = 1,
47 Monotonic = 2, // Equivalent to C++'s relaxed.
48 // Consume = 3, // Not specified yet.
49 Acquire = 4,
50 Release = 5,
51 AcquireRelease = 6,
52 SequentiallyConsistent = 7
53 };
54
55 bool operator<(AtomicOrdering, AtomicOrdering) = delete;
56 bool operator>(AtomicOrdering, AtomicOrdering) = delete;
57 bool operator<=(AtomicOrdering, AtomicOrdering) = delete;
58 bool operator>=(AtomicOrdering, AtomicOrdering) = delete;
59
60 /// String used by LLVM IR to represent atomic ordering.
61 static inline const char *toIRString(AtomicOrdering ao) {
62 static const char *names[8] = {"not_atomic", "unordered", "monotonic",
63 "consume", "acquire", "release",
64 "acq_rel", "seq_cst"};
65 return names[(size_t)ao];
66 }
67
68 /// Returns true if ao is stronger than other as defined by the AtomicOrdering
69 /// lattice, which is based on C++'s definition.
70 static inline bool isStrongerThan(AtomicOrdering ao, AtomicOrdering other) {
71 static const bool lookup[8][8] = {
72 // NA UN RX CO AC RE AR SC
73 /* NotAtomic */ {0, 0, 0, 0, 0, 0, 0, 0},
74 /* Unordered */ {1, 0, 0, 0, 0, 0, 0, 0},
75 /* relaxed */ {1, 1, 0, 0, 0, 0, 0, 0},
76 /* consume */ {1, 1, 1, 0, 0, 0, 0, 0},
77 /* acquire */ {1, 1, 1, 1, 0, 0, 0, 0},
78 /* release */ {1, 1, 1, 0, 0, 0, 0, 0},
79 /* acq_rel */ {1, 1, 1, 1, 1, 1, 0, 0},
80 /* seq_cst */ {1, 1, 1, 1, 1, 1, 1, 0},
81 };
82 return lookup[(size_t)ao][(size_t)other];
83 }
84
85 static inline bool isAtLeastOrStrongerThan(AtomicOrdering ao,
86 AtomicOrdering other) {
87 static const bool lookup[8][8] = {
88 // NA UN RX CO AC RE AR SC
89 /* NotAtomic */ {1, 0, 0, 0, 0, 0, 0, 0},
90 /* Unordered */ {1, 1, 0, 0, 0, 0, 0, 0},
91 /* relaxed */ {1, 1, 1, 0, 0, 0, 0, 0},
92 /* consume */ {1, 1, 1, 1, 0, 0, 0, 0},
93 /* acquire */ {1, 1, 1, 1, 1, 0, 0, 0},
94 /* release */ {1, 1, 1, 0, 0, 1, 0, 0},
95 /* acq_rel */ {1, 1, 1, 1, 1, 1, 1, 0},
96 /* seq_cst */ {1, 1, 1, 1, 1, 1, 1, 1},
97 };
98 return lookup[(size_t)ao][(size_t)other];
99 }
100
101 static inline bool isStrongerThanUnordered(AtomicOrdering Ord) {
102 return isStrongerThan(Ord, AtomicOrdering::Unordered);
103 }
104
105 static inline bool isStrongerThanMonotonic(AtomicOrdering Ord) {
106 return isStrongerThan(Ord, AtomicOrdering::Monotonic);
107 }
108
109 static inline bool isAcquireOrStronger(AtomicOrdering Ord) {
110 return isAtLeastOrStrongerThan(Ord, AtomicOrdering::Acquire);
111 }
112
113 static inline bool isReleaseOrStronger(AtomicOrdering Ord) {
114 return isAtLeastOrStrongerThan(Ord, AtomicOrdering::Release);
115 }
116
11739 enum SynchronizationScope {
11840 SingleThread = 0,
11941 CrossThread = 1
12042 };
121
12243
12344 //===----------------------------------------------------------------------===//
12445 // AllocaInst Class
0 //===-- llvm/Support/AtomicOrdering.h ---Atomic Ordering---------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// \brief 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 namespace llvm {
21
22 /// Atomic ordering for C11 / C++11's memody models.
23 ///
24 /// These values cannot change because they are shared with standard library
25 /// implementations as well as with other compilers.
26 enum class AtomicOrderingCABI {
27 relaxed = 0,
28 consume = 1,
29 acquire = 2,
30 release = 3,
31 acq_rel = 4,
32 seq_cst = 5,
33 };
34
35 bool operator<(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
36 bool operator>(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
37 bool operator<=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
38 bool operator>=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
39
40 // Validate an integral value which isn't known to fit within the enum's range
41 // is a valid AtomicOrderingCABI.
42 template static inline bool isValidAtomicOrderingCABI(Int I) {
43 return (Int)AtomicOrderingCABI::relaxed <= I &&
44 I <= (Int)AtomicOrderingCABI::seq_cst;
45 }
46
47 /// Atomic ordering for LLVM's memory model.
48 ///
49 /// C++ defines ordering as a lattice. LLVM supplements this with NotAtomic and
50 /// Unordered, which are both below the C++ orders.
51 ///
52 /// not_atomic-->unordered-->relaxed-->release--------------->acq_rel-->seq_cst
53 /// \-->consume-->acquire--/
54 enum class AtomicOrdering {
55 NotAtomic = 0,
56 Unordered = 1,
57 Monotonic = 2, // Equivalent to C++'s relaxed.
58 // Consume = 3, // Not specified yet.
59 Acquire = 4,
60 Release = 5,
61 AcquireRelease = 6,
62 SequentiallyConsistent = 7
63 };
64
65 bool operator<(AtomicOrdering, AtomicOrdering) = delete;
66 bool operator>(AtomicOrdering, AtomicOrdering) = delete;
67 bool operator<=(AtomicOrdering, AtomicOrdering) = delete;
68 bool operator>=(AtomicOrdering, AtomicOrdering) = delete;
69
70 // Validate an integral value which isn't known to fit within the enum's range
71 // is a valid AtomicOrdering.
72 template static inline bool isValidAtomicOrdering(Int I) {
73 return (Int)AtomicOrdering::NotAtomic <= I &&
74 I <= (Int)AtomicOrdering::SequentiallyConsistent;
75 }
76
77 /// String used by LLVM IR to represent atomic ordering.
78 static inline const char *toIRString(AtomicOrdering ao) {
79 static const char *names[8] = {"not_atomic", "unordered", "monotonic",
80 "consume", "acquire", "release",
81 "acq_rel", "seq_cst"};
82 return names[(size_t)ao];
83 }
84
85 /// Returns true if ao is stronger than other as defined by the AtomicOrdering
86 /// lattice, which is based on C++'s definition.
87 static inline bool isStrongerThan(AtomicOrdering ao, AtomicOrdering other) {
88 static const bool lookup[8][8] = {
89 // NA UN RX CO AC RE AR SC
90 /* NotAtomic */ {0, 0, 0, 0, 0, 0, 0, 0},
91 /* Unordered */ {1, 0, 0, 0, 0, 0, 0, 0},
92 /* relaxed */ {1, 1, 0, 0, 0, 0, 0, 0},
93 /* consume */ {1, 1, 1, 0, 0, 0, 0, 0},
94 /* acquire */ {1, 1, 1, 1, 0, 0, 0, 0},
95 /* release */ {1, 1, 1, 0, 0, 0, 0, 0},
96 /* acq_rel */ {1, 1, 1, 1, 1, 1, 0, 0},
97 /* seq_cst */ {1, 1, 1, 1, 1, 1, 1, 0},
98 };
99 return lookup[(size_t)ao][(size_t)other];
100 }
101
102 static inline bool isAtLeastOrStrongerThan(AtomicOrdering ao,
103 AtomicOrdering other) {
104 static const bool lookup[8][8] = {
105 // NA UN RX CO AC RE AR SC
106 /* NotAtomic */ {1, 0, 0, 0, 0, 0, 0, 0},
107 /* Unordered */ {1, 1, 0, 0, 0, 0, 0, 0},
108 /* relaxed */ {1, 1, 1, 0, 0, 0, 0, 0},
109 /* consume */ {1, 1, 1, 1, 0, 0, 0, 0},
110 /* acquire */ {1, 1, 1, 1, 1, 0, 0, 0},
111 /* release */ {1, 1, 1, 0, 0, 1, 0, 0},
112 /* acq_rel */ {1, 1, 1, 1, 1, 1, 1, 0},
113 /* seq_cst */ {1, 1, 1, 1, 1, 1, 1, 1},
114 };
115 return lookup[(size_t)ao][(size_t)other];
116 }
117
118 static inline bool isStrongerThanUnordered(AtomicOrdering ao) {
119 return isStrongerThan(ao, AtomicOrdering::Unordered);
120 }
121
122 static inline bool isStrongerThanMonotonic(AtomicOrdering ao) {
123 return isStrongerThan(ao, AtomicOrdering::Monotonic);
124 }
125
126 static inline bool isAcquireOrStronger(AtomicOrdering ao) {
127 return isAtLeastOrStrongerThan(ao, AtomicOrdering::Acquire);
128 }
129
130 static inline bool isReleaseOrStronger(AtomicOrdering ao) {
131 return isAtLeastOrStrongerThan(ao, AtomicOrdering::Release);
132 }
133
134 static inline AtomicOrderingCABI toCABI(AtomicOrdering ao) {
135 static const AtomicOrderingCABI lookup[8] = {
136 /* NotAtomic */ AtomicOrderingCABI::relaxed,
137 /* Unordered */ AtomicOrderingCABI::relaxed,
138 /* relaxed */ AtomicOrderingCABI::relaxed,
139 /* consume */ AtomicOrderingCABI::consume,
140 /* acquire */ AtomicOrderingCABI::acquire,
141 /* release */ AtomicOrderingCABI::release,
142 /* acq_rel */ AtomicOrderingCABI::acq_rel,
143 /* seq_cst */ AtomicOrderingCABI::seq_cst,
144 };
145 return lookup[(size_t)ao];
146 }
147
148 } // End namespace llvm
149
150 #endif
936936 return true;
937937 }
938938
939 // This converts from LLVM's internal AtomicOrdering enum to the
940 // memory_order_* value required by the __atomic_* libcalls.
941 static int libcallAtomicModel(AtomicOrdering AO) {
942 enum {
943 AO_ABI_memory_order_relaxed = 0,
944 AO_ABI_memory_order_consume = 1,
945 AO_ABI_memory_order_acquire = 2,
946 AO_ABI_memory_order_release = 3,
947 AO_ABI_memory_order_acq_rel = 4,
948 AO_ABI_memory_order_seq_cst = 5
949 };
950
951 switch (AO) {
952 case AtomicOrdering::NotAtomic:
953 llvm_unreachable("Expected atomic memory order.");
954 case AtomicOrdering::Unordered:
955 case AtomicOrdering::Monotonic:
956 return AO_ABI_memory_order_relaxed;
957 // Not implemented yet in llvm:
958 // case AtomicOrdering::Consume:
959 // return AO_ABI_memory_order_consume;
960 case AtomicOrdering::Acquire:
961 return AO_ABI_memory_order_acquire;
962 case AtomicOrdering::Release:
963 return AO_ABI_memory_order_release;
964 case AtomicOrdering::AcquireRelease:
965 return AO_ABI_memory_order_acq_rel;
966 case AtomicOrdering::SequentiallyConsistent:
967 return AO_ABI_memory_order_seq_cst;
968 }
969 llvm_unreachable("Unknown atomic memory order.");
970 }
971
972939 // In order to use one of the sized library calls such as
973940 // __atomic_fetch_add_4, the alignment must be sufficient, the size
974941 // must be one of the potentially-specialized sizes, and the value
11501117 // TODO: the "order" argument type is "int", not int32. So
11511118 // getInt32Ty may be wrong if the arch uses e.g. 16-bit ints.
11521119 ConstantInt *SizeVal64 = ConstantInt::get(Type::getInt64Ty(Ctx), Size);
1120 assert(Ordering != AtomicOrdering::NotAtomic && "expect atomic MO");
11531121 Constant *OrderingVal =
1154 ConstantInt::get(Type::getInt32Ty(Ctx), libcallAtomicModel(Ordering));
1155 Constant *Ordering2Val = CASExpected
1156 ? ConstantInt::get(Type::getInt32Ty(Ctx),
1157 libcallAtomicModel(Ordering2))
1158 : nullptr;
1122 ConstantInt::get(Type::getInt32Ty(Ctx), (int)toCABI(Ordering));
1123 Constant *Ordering2Val = nullptr;
1124 if (CASExpected) {
1125 assert(Ordering2 != AtomicOrdering::NotAtomic && "expect atomic MO");
1126 Ordering2Val =
1127 ConstantInt::get(Type::getInt32Ty(Ctx), (int)toCABI(Ordering2));
1128 }
11591129 bool HasResult = I->getType() != Type::getVoidTy(Ctx);
11601130
11611131 RTLIB::Libcall RTLibType;