LLVM 20.0.0git
Atomic.h
Go to the documentation of this file.
1//===--- Atomic.h - Codegen of atomic operations
2//---------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_FRONTEND_ATOMIC_ATOMIC_H
11#define LLVM_FRONTEND_ATOMIC_ATOMIC_H
12
13#include "llvm/ADT/DenseMap.h"
14#include "llvm/IR/DataLayout.h"
16#include "llvm/IR/Intrinsics.h"
17#include "llvm/IR/Module.h"
18#include "llvm/IR/Operator.h"
20
21namespace llvm {
22
23template <typename IRBuilderTy> struct AtomicInfo {
24
25 IRBuilderTy *Builder;
32
33public:
40
41 virtual ~AtomicInfo() = default;
42
46 bool shouldUseLibcall() const { return UseLibcall; }
47 llvm::Type *getAtomicTy() const { return Ty; }
48
49 virtual llvm::Value *getAtomicPointer() const = 0;
50 virtual void decorateWithTBAA(Instruction *I) = 0;
52 const llvm::Twine &Name) const = 0;
53
54 /*
55 * Is the atomic size larger than the underlying value type?
56 * Note that the absence of padding does not mean that atomic
57 * objects are completely interchangeable with non-atomic
58 * objects: we might have promoted the alignment of a type
59 * without making it bigger.
60 */
61 bool hasPadding() const { return (ValueSizeInBits != AtomicSizeInBits); }
62
63 LLVMContext &getLLVMContext() const { return Builder->getContext(); }
64
65 static bool shouldCastToInt(llvm::Type *ValTy, bool CmpXchg) {
66 if (ValTy->isFloatingPointTy())
67 return ValTy->isX86_FP80Ty() || CmpXchg;
68 return !ValTy->isIntegerTy() && !ValTy->isPointerTy();
69 }
70
72 bool CmpXchg = false) {
74 Type *AtomicTy = Ty;
75 if (shouldCastToInt(Ty, CmpXchg))
77 LoadInst *Load =
78 Builder->CreateAlignedLoad(AtomicTy, Ptr, AtomicAlign, "atomic-load");
79 Load->setAtomic(AO);
80 if (IsVolatile)
81 Load->setVolatile(true);
82 decorateWithTBAA(Load);
83 return Load;
84 }
85
86 static CallInst *EmitAtomicLibcall(IRBuilderTy *Builder, StringRef fnName,
87 Type *ResultType, ArrayRef<Value *> Args) {
88 LLVMContext &ctx = Builder->getContext();
90 for (Value *Arg : Args)
91 ArgTys.push_back(Arg->getType());
92 FunctionType *FnType = FunctionType::get(ResultType, ArgTys, false);
93 Module *M = Builder->GetInsertBlock()->getModule();
94
95 // TODO: Use llvm::TargetLowering for Libcall ABI
96 llvm::AttrBuilder fnAttrBuilder(ctx);
97 fnAttrBuilder.addAttribute(llvm::Attribute::NoUnwind);
98 fnAttrBuilder.addAttribute(llvm::Attribute::WillReturn);
100 ctx, llvm::AttributeList::FunctionIndex, fnAttrBuilder);
101 FunctionCallee LibcallFn = M->getOrInsertFunction(fnName, FnType, fnAttrs);
102 CallInst *Call = Builder->CreateCall(LibcallFn, Args);
103 return Call;
104 }
105
108
109 // TODO: Get from llvm::TargetMachine / clang::TargetInfo
110 // if clang shares this codegen in future
111 constexpr uint16_t SizeTBits = 64;
112 constexpr uint16_t BitsPerByte = 8;
113 return llvm::ConstantInt::get(llvm::IntegerType::get(ctx, SizeTBits),
114 AtomicSizeInBits / BitsPerByte);
115 }
116
117 std::pair<llvm::Value *, llvm::Value *> EmitAtomicCompareExchangeLibcall(
118 llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
121
122 // __atomic_compare_exchange's expected and desired are passed by pointers
123 // FIXME: types
124
125 // TODO: Get from llvm::TargetMachine / clang::TargetInfo
126 // if clang shares this codegen in future
127 constexpr uint64_t IntBits = 32;
128
129 // bool __atomic_compare_exchange(size_t size, void *obj, void *expected,
130 // void *desired, int success, int failure);
131 llvm::Value *Args[6] = {
134 ExpectedVal,
135 DesiredVal,
137 llvm::IntegerType::get(ctx, IntBits),
138 llvm::APInt(IntBits, static_cast<uint64_t>(Success),
139 /*signed=*/true)),
141 llvm::IntegerType::get(ctx, IntBits),
142 llvm::APInt(IntBits, static_cast<uint64_t>(Failure),
143 /*signed=*/true)),
144 };
145 auto Result = EmitAtomicLibcall(Builder, "__atomic_compare_exchange",
147 return std::make_pair(ExpectedVal, Result);
148 }
149
151 return addr; // opaque pointer
152 }
153
156 }
157
158 std::pair<llvm::Value *, llvm::Value *>
161 llvm::AtomicOrdering Failure,
162 bool IsVolatile = false, bool IsWeak = false) {
163 // Do the atomic store.
165 auto *Inst = Builder->CreateAtomicCmpXchg(Addr, ExpectedVal, DesiredVal,
167 Failure, llvm::SyncScope::System);
168 // Other decoration.
169 Inst->setVolatile(IsVolatile);
170 Inst->setWeak(IsWeak);
171
172 auto *PreviousVal = Builder->CreateExtractValue(Inst, /*Idxs=*/0);
173 auto *SuccessFailureVal = Builder->CreateExtractValue(Inst, /*Idxs=*/1);
174 return std::make_pair(PreviousVal, SuccessFailureVal);
175 }
176
177 std::pair<llvm::Value *, llvm::Value *>
180 llvm::AtomicOrdering Failure, bool IsVolatile,
181 bool IsWeak) {
182 if (shouldUseLibcall())
183 return EmitAtomicCompareExchangeLibcall(ExpectedVal, DesiredVal, Success,
184 Failure);
185
186 auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success,
187 Failure, IsVolatile, IsWeak);
188 return Res;
189 }
190
191 // void __atomic_load(size_t size, void *mem, void *return, int order);
192 std::pair<llvm::LoadInst *, llvm::AllocaInst *>
195 Type *SizedIntTy = Type::getIntNTy(Ctx, getAtomicSizeInBits());
196 Type *ResultTy;
198 AttributeList Attr;
199 Module *M = Builder->GetInsertBlock()->getModule();
200 const DataLayout &DL = M->getDataLayout();
201 Args.push_back(ConstantInt::get(DL.getIntPtrType(Ctx),
202 this->getAtomicSizeInBits() / 8));
203
204 Value *PtrVal = getAtomicPointer();
205 PtrVal = Builder->CreateAddrSpaceCast(PtrVal, PointerType::getUnqual(Ctx));
206 Args.push_back(PtrVal);
207 AllocaInst *AllocaResult =
208 CreateAlloca(Ty, getAtomicPointer()->getName() + "atomic.temp.load");
209 const Align AllocaAlignment = DL.getPrefTypeAlign(SizedIntTy);
210 AllocaResult->setAlignment(AllocaAlignment);
211 Args.push_back(AllocaResult);
212 Constant *OrderingVal =
213 ConstantInt::get(Type::getInt32Ty(Ctx), (int)toCABI(AO));
214 Args.push_back(OrderingVal);
215
216 ResultTy = Type::getVoidTy(Ctx);
218 for (Value *Arg : Args)
219 ArgTys.push_back(Arg->getType());
220 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys, false);
221 FunctionCallee LibcallFn =
222 M->getOrInsertFunction("__atomic_load", FnType, Attr);
223 CallInst *Call = Builder->CreateCall(LibcallFn, Args);
224 Call->setAttributes(Attr);
225 return std::make_pair(
226 Builder->CreateAlignedLoad(Ty, AllocaResult, AllocaAlignment),
227 AllocaResult);
228 }
229};
230} // end namespace llvm
231
232#endif /* LLVM_FRONTEND_ATOMIC_ATOMIC_H */
#define Success
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file defines the DenseMap class.
uint64_t Addr
std::string Name
Module.h This file contains the declarations for the Module class.
#define I(x, y, z)
Definition: MD5.cpp:58
static StringRef getName(Value *V)
Class for arbitrary precision integers.
Definition: APInt.h:78
an instruction to allocate memory on the stack
Definition: Instructions.h:63
void setAlignment(Align Align)
Definition: Instructions.h:128
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
AttrBuilder & addAttribute(Attribute::AttrKind Val)
Add an attribute to the builder.
static AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute > > Attrs)
Create an AttributeList with the specified parameters in it.
This class represents a function call, abstracting a target machine's calling convention.
This is an important base class in LLVM.
Definition: Constant.h:42
static Constant * getIntegerValue(Type *Ty, const APInt &V)
Return the value for an integer or pointer constant, or a vector thereof, with the given scalar value...
Definition: Constants.cpp:403
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Definition: DerivedTypes.h:170
Class to represent function types.
Definition: DerivedTypes.h:105
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition: Type.cpp:311
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
An instruction for reading from memory.
Definition: Instructions.h:176
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Definition: DerivedTypes.h:686
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
bool isX86_FP80Ty() const
Return true if this is x86 long double.
Definition: Type.h:159
bool isPointerTy() const
True if this is an instance of PointerType.
Definition: Type.h:264
static IntegerType * getInt1Ty(LLVMContext &C)
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static Type * getVoidTy(LLVMContext &C)
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition: Type.h:184
static IntegerType * getInt32Ty(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:237
LLVM Value Representation.
Definition: Value.h:74
@ System
Synchronized with respect to all concurrently executing threads.
Definition: LLVMContext.h:57
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
AtomicOrderingCABI toCABI(AtomicOrdering AO)
AtomicOrdering
Atomic ordering for LLVM's memory model.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
uint64_t AtomicSizeInBits
Definition: Atomic.h:27
bool hasPadding() const
Definition: Atomic.h:61
llvm::Align AtomicAlign
Definition: Atomic.h:29
uint64_t getValueSizeInBits() const
Definition: Atomic.h:45
AtomicInfo(IRBuilderTy *Builder, Type *Ty, uint64_t AtomicSizeInBits, uint64_t ValueSizeInBits, llvm::Align AtomicAlign, llvm::Align ValueAlign, bool UseLibcall)
Definition: Atomic.h:34
uint64_t getAtomicSizeInBits() const
Definition: Atomic.h:44
std::pair< llvm::Value *, llvm::Value * > EmitAtomicCompareExchangeLibcall(llvm::Value *ExpectedVal, llvm::Value *DesiredVal, llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure)
Definition: Atomic.h:117
Type * Ty
Definition: Atomic.h:26
std::pair< llvm::Value *, llvm::Value * > EmitAtomicCompareExchange(llvm::Value *ExpectedVal, llvm::Value *DesiredVal, llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure, bool IsVolatile, bool IsWeak)
Definition: Atomic.h:178
std::pair< llvm::Value *, llvm::Value * > EmitAtomicCompareExchangeOp(llvm::Value *ExpectedVal, llvm::Value *DesiredVal, llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure, bool IsVolatile=false, bool IsWeak=false)
Definition: Atomic.h:159
llvm::Type * getAtomicTy() const
Definition: Atomic.h:47
Value * castToAtomicIntPointer(Value *addr) const
Definition: Atomic.h:150
virtual llvm::AllocaInst * CreateAlloca(llvm::Type *Ty, const llvm::Twine &Name) const =0
static CallInst * EmitAtomicLibcall(IRBuilderTy *Builder, StringRef fnName, Type *ResultType, ArrayRef< Value * > Args)
Definition: Atomic.h:86
static bool shouldCastToInt(llvm::Type *ValTy, bool CmpXchg)
Definition: Atomic.h:65
llvm::Value * EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile, bool CmpXchg=false)
Definition: Atomic.h:71
llvm::Align getAtomicAlignment() const
Definition: Atomic.h:43
bool UseLibcall
Definition: Atomic.h:31
virtual llvm::Value * getAtomicPointer() const =0
virtual void decorateWithTBAA(Instruction *I)=0
LLVMContext & getLLVMContext() const
Definition: Atomic.h:63
IRBuilderTy * Builder
Definition: Atomic.h:25
bool shouldUseLibcall() const
Definition: Atomic.h:46
std::pair< llvm::LoadInst *, llvm::AllocaInst * > EmitAtomicLoadLibcall(llvm::AtomicOrdering AO)
Definition: Atomic.h:193
Value * getAtomicAddressAsAtomicIntPointer() const
Definition: Atomic.h:154
llvm::Align ValueAlign
Definition: Atomic.h:30
uint64_t ValueSizeInBits
Definition: Atomic.h:28
virtual ~AtomicInfo()=default
llvm::Value * getAtomicSizeValue() const
Definition: Atomic.h:106