9#ifndef LLVM_ADT_LAZYATOMICPOINTER_H
10#define LLVM_ADT_LAZYATOMICPOINTER_H
35 static constexpr uintptr_t getNull() {
return 0; }
36 static constexpr uintptr_t getBusy() {
return UINTPTR_MAX; }
38 static T *makePointer(uintptr_t
Value) {
40 return Value ?
reinterpret_cast<T *
>(
Value) :
nullptr;
42 static uintptr_t makeRaw(
T *
Value) {
43 uintptr_t Raw =
Value ?
reinterpret_cast<uintptr_t
>(
Value) : getNull();
66 uintptr_t RawExistingValue = makeRaw(ExistingValue);
67 if (Storage.compare_exchange_weak(RawExistingValue, makeRaw(NewValue)))
71 if (RawExistingValue == getBusy())
72 ExistingValue =
nullptr;
74 ExistingValue = makePointer(RawExistingValue);
81 uintptr_t RawExistingValue = makeRaw(ExistingValue);
82 const uintptr_t OriginalRawExistingValue = RawExistingValue;
83 if (Storage.compare_exchange_strong(RawExistingValue, makeRaw(NewValue)))
88 while (RawExistingValue == getBusy()) {
89 RawExistingValue = OriginalRawExistingValue;
90 if (Storage.compare_exchange_weak(RawExistingValue, makeRaw(NewValue)))
94 ExistingValue = makePointer(RawExistingValue);
101 uintptr_t RawValue = Storage.load();
102 return RawValue == getBusy() ? nullptr : makePointer(RawValue);
111 uintptr_t Raw = Storage.load();
112 if (Raw != getNull() && Raw != getBusy())
113 return *makePointer(Raw);
117 Storage.compare_exchange_strong(Raw, getBusy()))) {
118 Raw = makeRaw(Generator());
119 assert(Raw != getNull() &&
"Expected non-null from generator");
121 return *makePointer(Raw);
125 while (Raw == getBusy())
126 Raw = Storage.load();
127 assert(Raw != getNull() &&
"Expected non-null from competing generator");
128 return *makePointer(Raw);
132 operator T *()
const {
return load(); }
136 assert(
P &&
"Unexpected null dereference");
145 : Storage(makeRaw(
RHS.
load())) {}
161 std::atomic<uintptr_t> Storage;
#define LLVM_UNLIKELY(EXPR)
#define LLVM_LIKELY(EXPR)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Atomic pointer that's lock-free, but that can coordinate concurrent writes from a lazy generator.
void store(T *Value)
Store a value. Waits for concurrent loadOrGenerate() calls.
LazyAtomicPointer & operator=(T *RHS)
bool compare_exchange_strong(T *&ExistingValue, T *NewValue)
Compare-exchange.
T * load() const
Return the current stored value.
LazyAtomicPointer(const LazyAtomicPointer &RHS)
LazyAtomicPointer(std::nullptr_t)
LazyAtomicPointer & operator=(const LazyAtomicPointer &RHS)
LazyAtomicPointer & operator=(std::nullptr_t)
bool compare_exchange_weak(T *&ExistingValue, T *NewValue)
Compare-exchange.
T & loadOrGenerate(function_ref< T *()> Generator)
Get the current value, or call Generator to generate a value.
T * exchange(T *Value)
Set a value.
LazyAtomicPointer(T *Value)
LLVM Value Representation.
An efficient, type-erasing, non-owning reference to a callable.
This is an optimization pass for GlobalISel generic memory operations.