Skip to content

Commit 70c65b3

Browse files
committed
Add BuildBuiltins utilities for atomic load,store,cmpxchg
1 parent 27539c3 commit 70c65b3

File tree

17 files changed

+6171
-126
lines changed

17 files changed

+6171
-126
lines changed

llvm/include/llvm/Analysis/TargetLibraryInfo.def

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,11 +462,91 @@ TLI_DEFINE_ENUM_INTERNAL(atomic_load)
462462
TLI_DEFINE_STRING_INTERNAL("__atomic_load")
463463
TLI_DEFINE_SIG_INTERNAL(Void, SizeT, Ptr, Ptr, Int)
464464

465+
/// int8_t __atomic_load_1(void *ptr, int memorder);
466+
TLI_DEFINE_ENUM_INTERNAL(atomic_load_1)
467+
TLI_DEFINE_STRING_INTERNAL("__atomic_load_1")
468+
TLI_DEFINE_SIG_INTERNAL(Int8, Ptr, Int)
469+
470+
/// int16_t __atomic_load_2(void *ptr, int memorder);
471+
TLI_DEFINE_ENUM_INTERNAL(atomic_load_2)
472+
TLI_DEFINE_STRING_INTERNAL("__atomic_load_2")
473+
TLI_DEFINE_SIG_INTERNAL(Int16, Ptr, Int)
474+
475+
/// int32_t __atomic_load_4(void *ptr, int memorder);
476+
TLI_DEFINE_ENUM_INTERNAL(atomic_load_4)
477+
TLI_DEFINE_STRING_INTERNAL("__atomic_load_4")
478+
TLI_DEFINE_SIG_INTERNAL(Int32, Ptr, Int)
479+
480+
/// int64_t __atomic_load_8(void *ptr int memorder);
481+
TLI_DEFINE_ENUM_INTERNAL(atomic_load_8)
482+
TLI_DEFINE_STRING_INTERNAL("__atomic_load_8")
483+
TLI_DEFINE_SIG_INTERNAL(Int64, Ptr, Int)
484+
485+
/// int128_t __atomic_load_16(void *ptr, int memorder);
486+
TLI_DEFINE_ENUM_INTERNAL(atomic_load_16)
487+
TLI_DEFINE_STRING_INTERNAL("__atomic_load_16")
488+
TLI_DEFINE_SIG_INTERNAL(Int128, Ptr, Int)
489+
465490
/// void __atomic_store(size_t size, void *mptr, void *vptr, int smodel);
466491
TLI_DEFINE_ENUM_INTERNAL(atomic_store)
467492
TLI_DEFINE_STRING_INTERNAL("__atomic_store")
468493
TLI_DEFINE_SIG_INTERNAL(Void, SizeT, Ptr, Ptr, Int)
469494

495+
/// void __atomic_store_1(void *ptr, int8_t val, int smodel);
496+
TLI_DEFINE_ENUM_INTERNAL(atomic_store_1)
497+
TLI_DEFINE_STRING_INTERNAL("__atomic_store_1")
498+
TLI_DEFINE_SIG_INTERNAL(Void, Ptr, Int8, Int)
499+
500+
/// void __atomic_store_2(void *ptr, int16_t val, int smodel);
501+
TLI_DEFINE_ENUM_INTERNAL(atomic_store_2)
502+
TLI_DEFINE_STRING_INTERNAL("__atomic_store_2")
503+
TLI_DEFINE_SIG_INTERNAL(Void, Ptr, Int16, Int)
504+
505+
/// void __atomic_store_4(void *ptr, int32_t val, int smodel);
506+
TLI_DEFINE_ENUM_INTERNAL(atomic_store_4)
507+
TLI_DEFINE_STRING_INTERNAL("__atomic_store_4")
508+
TLI_DEFINE_SIG_INTERNAL(Void, Ptr, Int32, Int)
509+
510+
/// void __atomic_store_8(void *ptr, int64_t val, int smodel);
511+
TLI_DEFINE_ENUM_INTERNAL(atomic_store_8)
512+
TLI_DEFINE_STRING_INTERNAL("__atomic_store_8")
513+
TLI_DEFINE_SIG_INTERNAL(Void, Ptr, Int64, Int)
514+
515+
/// void __atomic_store_16(void *ptr, int128_t val, int smodel);
516+
TLI_DEFINE_ENUM_INTERNAL(atomic_store_16)
517+
TLI_DEFINE_STRING_INTERNAL("__atomic_store_16")
518+
TLI_DEFINE_SIG_INTERNAL(Void, Ptr, Int128, Int)
519+
520+
/// bool __atomic_compare_exchange(size_t size, void *ptr, void *expected, void *desired, int success, int failure);
521+
TLI_DEFINE_ENUM_INTERNAL(atomic_compare_exchange)
522+
TLI_DEFINE_STRING_INTERNAL("__atomic_compare_exchange")
523+
TLI_DEFINE_SIG_INTERNAL(Bool, SizeT, Ptr, Ptr, Ptr, Int, Int)
524+
525+
/// bool __atomic_compare_exchange_1(void *ptr, void *expected, uint8_t desired, int success, int failure);
526+
TLI_DEFINE_ENUM_INTERNAL(atomic_compare_exchange_1)
527+
TLI_DEFINE_STRING_INTERNAL("__atomic_compare_exchange_1")
528+
TLI_DEFINE_SIG_INTERNAL(Bool, Ptr, Ptr, Int8, Int, Int)
529+
530+
/// bool __atomic_compare_exchange_2(void *ptr, void *expected, uint16_t desired, int success, int failure);
531+
TLI_DEFINE_ENUM_INTERNAL(atomic_compare_exchange_2)
532+
TLI_DEFINE_STRING_INTERNAL("__atomic_compare_exchange_2")
533+
TLI_DEFINE_SIG_INTERNAL(Bool, Ptr, Ptr, Int16, Int, Int)
534+
535+
/// bool __atomic_compare_exchange_4(void *ptr, void *expected, uint32_t desired, int success, int failure);
536+
TLI_DEFINE_ENUM_INTERNAL(atomic_compare_exchange_4)
537+
TLI_DEFINE_STRING_INTERNAL("__atomic_compare_exchange_4")
538+
TLI_DEFINE_SIG_INTERNAL(Bool, Ptr, Ptr, Int32, Int, Int)
539+
540+
/// bool __atomic_compare_exchange_8(void *ptr, void *expected, uint64_t desired, int success, int failure);
541+
TLI_DEFINE_ENUM_INTERNAL(atomic_compare_exchange_8)
542+
TLI_DEFINE_STRING_INTERNAL("__atomic_compare_exchange_8")
543+
TLI_DEFINE_SIG_INTERNAL(Bool, Ptr, Ptr, Int64, Int, Int)
544+
545+
/// bool __atomic_compare_exchange_16(void *ptr, void *expected, uint128_t desired, int success, int failure);
546+
TLI_DEFINE_ENUM_INTERNAL(atomic_compare_exchange_16)
547+
TLI_DEFINE_STRING_INTERNAL("__atomic_compare_exchange_16")
548+
TLI_DEFINE_SIG_INTERNAL(Bool, Ptr, Ptr, Int128, Int, Int)
549+
470550
/// double __cosh_finite(double x);
471551
TLI_DEFINE_ENUM_INTERNAL(cosh_finite)
472552
TLI_DEFINE_STRING_INTERNAL("__cosh_finite")

llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -33,54 +33,6 @@ struct TargetRegionEntryInfo;
3333
class OffloadEntriesInfoManager;
3434
class OpenMPIRBuilder;
3535

36-
/// Move the instruction after an InsertPoint to the beginning of another
37-
/// BasicBlock.
38-
///
39-
/// The instructions after \p IP are moved to the beginning of \p New which must
40-
/// not have any PHINodes. If \p CreateBranch is true, a branch instruction to
41-
/// \p New will be added such that there is no semantic change. Otherwise, the
42-
/// \p IP insert block remains degenerate and it is up to the caller to insert a
43-
/// terminator. \p DL is used as the debug location for the branch instruction
44-
/// if one is created.
45-
void spliceBB(IRBuilderBase::InsertPoint IP, BasicBlock *New, bool CreateBranch,
46-
DebugLoc DL);
47-
48-
/// Splice a BasicBlock at an IRBuilder's current insertion point. Its new
49-
/// insert location will stick to after the instruction before the insertion
50-
/// point (instead of moving with the instruction the InsertPoint stores
51-
/// internally).
52-
void spliceBB(IRBuilder<> &Builder, BasicBlock *New, bool CreateBranch);
53-
54-
/// Split a BasicBlock at an InsertPoint, even if the block is degenerate
55-
/// (missing the terminator).
56-
///
57-
/// llvm::SplitBasicBlock and BasicBlock::splitBasicBlock require a well-formed
58-
/// BasicBlock. \p Name is used for the new successor block. If \p CreateBranch
59-
/// is true, a branch to the new successor will new created such that
60-
/// semantically there is no change; otherwise the block of the insertion point
61-
/// remains degenerate and it is the caller's responsibility to insert a
62-
/// terminator. \p DL is used as the debug location for the branch instruction
63-
/// if one is created. Returns the new successor block.
64-
BasicBlock *splitBB(IRBuilderBase::InsertPoint IP, bool CreateBranch,
65-
DebugLoc DL, llvm::Twine Name = {});
66-
67-
/// Split a BasicBlock at \p Builder's insertion point, even if the block is
68-
/// degenerate (missing the terminator). Its new insert location will stick to
69-
/// after the instruction before the insertion point (instead of moving with the
70-
/// instruction the InsertPoint stores internally).
71-
BasicBlock *splitBB(IRBuilderBase &Builder, bool CreateBranch,
72-
llvm::Twine Name = {});
73-
74-
/// Split a BasicBlock at \p Builder's insertion point, even if the block is
75-
/// degenerate (missing the terminator). Its new insert location will stick to
76-
/// after the instruction before the insertion point (instead of moving with the
77-
/// instruction the InsertPoint stores internally).
78-
BasicBlock *splitBB(IRBuilder<> &Builder, bool CreateBranch, llvm::Twine Name);
79-
80-
/// Like splitBB, but reuses the current block's name for the new name.
81-
BasicBlock *splitBBWithSuffix(IRBuilderBase &Builder, bool CreateBranch,
82-
llvm::Twine Suffix = ".split");
83-
8436
/// Captures attributes that affect generating LLVM-IR using the
8537
/// OpenMPIRBuilder and related classes. Note that not all attributes are
8638
/// required for all classes or functions. In some use cases the configuration

llvm/include/llvm/Support/AtomicOrdering.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,28 @@ inline AtomicOrderingCABI toCABI(AtomicOrdering AO) {
158158
return lookup[static_cast<size_t>(AO)];
159159
}
160160

161+
inline AtomicOrdering fromCABI(AtomicOrderingCABI AO) {
162+
// Acquire is the the closest but still stronger ordering of consume.
163+
static const AtomicOrdering lookup[8] = {
164+
/* relaxed */ AtomicOrdering::Monotonic,
165+
/* consume */ AtomicOrdering::Acquire,
166+
/* acquire */ AtomicOrdering::Acquire,
167+
/* release */ AtomicOrdering::Release,
168+
/* acq_rel */ AtomicOrdering::AcquireRelease,
169+
/* acq_seq */ AtomicOrdering::SequentiallyConsistent,
170+
};
171+
return lookup[static_cast<size_t>(AO)];
172+
}
173+
174+
inline AtomicOrdering fromCABI(int64_t AO) {
175+
if (!isValidAtomicOrderingCABI(AO)) {
176+
// This fallback is what CGAtomic does
177+
return AtomicOrdering::Monotonic;
178+
}
179+
assert(isValidAtomicOrderingCABI(AO));
180+
return fromCABI(static_cast<AtomicOrderingCABI>(AO));
181+
}
182+
161183
} // end namespace llvm
162184

163185
#endif // LLVM_SUPPORT_ATOMICORDERING_H

llvm/include/llvm/Testing/Support/Error.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,48 @@ class ValueMatchesPoly {
8080
M Matcher;
8181
};
8282

83+
template <typename RefT> class StoreResultMatcher {
84+
class Impl : public testing::MatcherInterface<
85+
const llvm::detail::ExpectedHolder<RefT> &> {
86+
public:
87+
explicit Impl(RefT &Ref) : Ref(Ref) {}
88+
89+
bool
90+
MatchAndExplain(const llvm::detail::ExpectedHolder<RefT> &Holder,
91+
testing::MatchResultListener *listener) const override {
92+
// If failed to get a value, fail the ASSERT/EXPECT and do not store any
93+
// value
94+
if (!Holder.Success())
95+
return false;
96+
97+
// Succeeded with a value, remember it
98+
Ref = *Holder.Exp;
99+
100+
return true;
101+
}
102+
103+
void DescribeTo(std::ostream *OS) const override { *OS << "succeeded"; }
104+
105+
void DescribeNegationTo(std::ostream *OS) const override {
106+
*OS << "failed";
107+
}
108+
109+
private:
110+
RefT &Ref;
111+
};
112+
113+
public:
114+
explicit StoreResultMatcher(RefT &Ref) : Ref(Ref) {}
115+
116+
template <typename T>
117+
operator testing::Matcher<const llvm::detail::ExpectedHolder<T> &>() const {
118+
return MakeMatcher(new Impl(Ref));
119+
}
120+
121+
private:
122+
RefT &Ref;
123+
};
124+
83125
template <typename InfoT>
84126
class ErrorMatchesMono : public testing::MatcherInterface<const ErrorHolder &> {
85127
public:
@@ -222,6 +264,13 @@ detail::ValueMatchesPoly<M> HasValue(M Matcher) {
222264
return detail::ValueMatchesPoly<M>(Matcher);
223265
}
224266

267+
/// Matches on Expected<T> values that succeed, but also stores its value into a
268+
/// variable.
269+
template <typename RefT>
270+
detail::StoreResultMatcher<RefT> StoreResult(RefT &Ref) {
271+
return detail::StoreResultMatcher<RefT>(Ref);
272+
}
273+
225274
} // namespace llvm
226275

227276
#endif

llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "llvm/ADT/SetVector.h"
2121
#include "llvm/IR/BasicBlock.h"
2222
#include "llvm/IR/Dominators.h"
23+
#include "llvm/IR/IRBuilder.h"
2324
#include <cassert>
2425

2526
namespace llvm {
@@ -384,6 +385,54 @@ void SplitLandingPadPredecessors(
384385
DomTreeUpdater *DTU = nullptr, LoopInfo *LI = nullptr,
385386
MemorySSAUpdater *MSSAU = nullptr, bool PreserveLCSSA = false);
386387

388+
/// Move the instruction after an InsertPoint to the beginning of another
389+
/// BasicBlock.
390+
///
391+
/// The instructions after \p IP are moved to the beginning of \p New which must
392+
/// not have any PHINodes. If \p CreateBranch is true, a branch instruction to
393+
/// \p New will be added such that there is no semantic change. Otherwise, the
394+
/// \p IP insert block remains degenerate and it is up to the caller to insert a
395+
/// terminator. \p DL is used as the debug location for the branch instruction
396+
/// if one is created.
397+
void spliceBB(IRBuilderBase::InsertPoint IP, BasicBlock *New, bool CreateBranch,
398+
DebugLoc DL);
399+
400+
/// Splice a BasicBlock at an IRBuilder's current insertion point. Its new
401+
/// insert location will stick to after the instruction before the insertion
402+
/// point (instead of moving with the instruction the InsertPoint stores
403+
/// internally).
404+
void spliceBB(IRBuilder<> &Builder, BasicBlock *New, bool CreateBranch);
405+
406+
/// Split a BasicBlock at an InsertPoint, even if the block is degenerate
407+
/// (missing the terminator).
408+
///
409+
/// llvm::SplitBasicBlock and BasicBlock::splitBasicBlock require a well-formed
410+
/// BasicBlock. \p Name is used for the new successor block. If \p CreateBranch
411+
/// is true, a branch to the new successor will new created such that
412+
/// semantically there is no change; otherwise the block of the insertion point
413+
/// remains degenerate and it is the caller's responsibility to insert a
414+
/// terminator. \p DL is used as the debug location for the branch instruction
415+
/// if one is created. Returns the new successor block.
416+
BasicBlock *splitBB(IRBuilderBase::InsertPoint IP, bool CreateBranch,
417+
DebugLoc DL, llvm::Twine Name = {});
418+
419+
/// Split a BasicBlock at \p Builder's insertion point, even if the block is
420+
/// degenerate (missing the terminator). Its new insert location will stick to
421+
/// after the instruction before the insertion point (instead of moving with the
422+
/// instruction the InsertPoint stores internally).
423+
BasicBlock *splitBB(IRBuilderBase &Builder, bool CreateBranch,
424+
llvm::Twine Name = {});
425+
426+
/// Split a BasicBlock at \p Builder's insertion point, even if the block is
427+
/// degenerate (missing the terminator). Its new insert location will stick to
428+
/// after the instruction before the insertion point (instead of moving with the
429+
/// instruction the InsertPoint stores internally).
430+
BasicBlock *splitBB(IRBuilder<> &Builder, bool CreateBranch, llvm::Twine Name);
431+
432+
/// Like splitBB, but reuses the current block's name for the new name.
433+
BasicBlock *splitBBWithSuffix(IRBuilderBase &Builder, bool CreateBranch,
434+
llvm::Twine Suffix = ".split");
435+
387436
/// This method duplicates the specified return instruction into a predecessor
388437
/// which ends in an unconditional branch. If the return instruction returns a
389438
/// value defined by a PHI, propagate the right value into the return. It

0 commit comments

Comments
 (0)