LLVM 20.0.0git
Atomic.cpp
Go to the documentation of this file.
1//===--- Atomic.cpp - Codegen of atomic operations ------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
11#include "llvm/IR/IRBuilder.h"
12#include <utility>
13
14using namespace llvm;
15
16bool AtomicInfo::shouldCastToInt(Type *ValTy, bool CmpXchg) {
17 if (ValTy->isFloatingPointTy())
18 return ValTy->isX86_FP80Ty() || CmpXchg;
19 return !ValTy->isIntegerTy() && !ValTy->isPointerTy();
20}
21
23 bool CmpXchg) {
25 Type *AtomicTy = Ty;
26 if (shouldCastToInt(Ty, CmpXchg))
28 LoadInst *Load =
29 Builder->CreateAlignedLoad(AtomicTy, Ptr, AtomicAlign, "atomic-load");
30 Load->setAtomic(AO);
31 if (IsVolatile)
32 Load->setVolatile(true);
33 decorateWithTBAA(Load);
34 return Load;
35}
36
38 ArrayRef<Value *> Args) {
41 for (Value *Arg : Args)
42 ArgTys.push_back(Arg->getType());
43 FunctionType *FnType = FunctionType::get(ResultType, ArgTys, false);
45
46 // TODO: Use llvm::TargetLowering for Libcall ABI
47 AttrBuilder fnAttrBuilder(ctx);
48 fnAttrBuilder.addAttribute(Attribute::NoUnwind);
49 fnAttrBuilder.addAttribute(Attribute::WillReturn);
50 AttributeList fnAttrs =
52 FunctionCallee LibcallFn = M->getOrInsertFunction(fnName, FnType, fnAttrs);
53 CallInst *Call = Builder->CreateCall(LibcallFn, Args);
54 return Call;
55}
56
58 Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success,
59 AtomicOrdering Failure) {
61
62 // __atomic_compare_exchange's expected and desired are passed by pointers
63 // FIXME: types
64
65 // TODO: Get from llvm::TargetMachine / clang::TargetInfo
66 // if clang shares this codegen in future
67 constexpr uint64_t IntBits = 32;
68
69 // bool __atomic_compare_exchange(size_t size, void *obj, void *expected,
70 // void *desired, int success, int failure);
71
72 Value *Args[6] = {
75 ExpectedVal,
76 DesiredVal,
78 APInt(IntBits, static_cast<uint64_t>(Success),
79 /*signed=*/true)),
81 APInt(IntBits, static_cast<uint64_t>(Failure),
82 /*signed=*/true)),
83 };
84 auto Result = EmitAtomicLibcall("__atomic_compare_exchange",
85 IntegerType::getInt1Ty(ctx), Args);
86 return std::make_pair(ExpectedVal, Result);
87}
88
89std::pair<Value *, Value *> AtomicInfo::EmitAtomicCompareExchangeOp(
90 Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success,
91 AtomicOrdering Failure, bool IsVolatile, bool IsWeak) {
92 // Do the atomic store.
94 auto *Inst = Builder->CreateAtomicCmpXchg(Addr, ExpectedVal, DesiredVal,
96 Failure, SyncScope::System);
97
98 // Other decoration.
99 Inst->setVolatile(IsVolatile);
100 Inst->setWeak(IsWeak);
101 auto *PreviousVal = Builder->CreateExtractValue(Inst, /*Idxs=*/0);
102 auto *SuccessFailureVal = Builder->CreateExtractValue(Inst, /*Idxs=*/1);
103 return std::make_pair(PreviousVal, SuccessFailureVal);
104}
105
106std::pair<LoadInst *, AllocaInst *>
109 Type *SizedIntTy = Type::getIntNTy(Ctx, getAtomicSizeInBits());
110 Type *ResultTy;
112 AttributeList Attr;
114 const DataLayout &DL = M->getDataLayout();
115 Args.push_back(
116 ConstantInt::get(DL.getIntPtrType(Ctx), this->getAtomicSizeInBits() / 8));
117
118 Value *PtrVal = getAtomicPointer();
119 PtrVal = Builder->CreateAddrSpaceCast(PtrVal, PointerType::getUnqual(Ctx));
120 Args.push_back(PtrVal);
121 AllocaInst *AllocaResult =
122 CreateAlloca(Ty, getAtomicPointer()->getName() + "atomic.temp.load");
123 const Align AllocaAlignment = DL.getPrefTypeAlign(SizedIntTy);
124 AllocaResult->setAlignment(AllocaAlignment);
125 Args.push_back(AllocaResult);
126 Constant *OrderingVal =
127 ConstantInt::get(Type::getInt32Ty(Ctx), (int)toCABI(AO));
128 Args.push_back(OrderingVal);
129
130 ResultTy = Type::getVoidTy(Ctx);
132 for (Value *Arg : Args)
133 ArgTys.push_back(Arg->getType());
134 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys, false);
135 FunctionCallee LibcallFn =
136 M->getOrInsertFunction("__atomic_load", FnType, Attr);
137 CallInst *Call = Builder->CreateCall(LibcallFn, Args);
138 Call->setAttributes(Attr);
139 return std::make_pair(
140 Builder->CreateAlignedLoad(Ty, AllocaResult, AllocaAlignment),
141 AllocaResult);
142}
143
144std::pair<Value *, Value *> AtomicInfo::EmitAtomicCompareExchange(
145 Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success,
146 AtomicOrdering Failure, bool IsVolatile, bool IsWeak) {
147 if (shouldUseLibcall())
148 return EmitAtomicCompareExchangeLibcall(ExpectedVal, DesiredVal, Success,
149 Failure);
150
151 auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success,
152 Failure, IsVolatile, IsWeak);
153 return Res;
154}
#define Success
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
uint64_t Addr
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
void setVolatile(bool V)
Specify whether this is a volatile cmpxchg.
Definition: Instructions.h:559
Align AtomicAlign
Definition: Atomic.h:22
IRBuilderBase * Builder
Definition: Atomic.h:18
std::pair< Value *, Value * > EmitAtomicCompareExchange(Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success, AtomicOrdering Failure, bool IsVolatile, bool IsWeak)
Definition: Atomic.cpp:144
virtual AllocaInst * CreateAlloca(Type *Ty, const Twine &Name) const =0
std::pair< LoadInst *, AllocaInst * > EmitAtomicLoadLibcall(AtomicOrdering AO)
Definition: Atomic.cpp:107
std::pair< Value *, Value * > EmitAtomicCompareExchangeOp(Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success, AtomicOrdering Failure, bool IsVolatile=false, bool IsWeak=false)
Definition: Atomic.cpp:89
uint64_t getAtomicSizeInBits() const
Definition: Atomic.h:37
Value * EmitAtomicLoadOp(AtomicOrdering AO, bool IsVolatile, bool CmpXchg=false)
Definition: Atomic.cpp:22
virtual Value * getAtomicPointer() const =0
std::pair< Value *, Value * > EmitAtomicCompareExchangeLibcall(Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success, AtomicOrdering Failure)
Definition: Atomic.cpp:57
bool shouldCastToInt(Type *ValTy, bool CmpXchg)
Definition: Atomic.cpp:16
uint64_t AtomicSizeInBits
Definition: Atomic.h:20
LLVMContext & getLLVMContext() const
Definition: Atomic.h:55
Value * getAtomicAddressAsAtomicIntPointer() const
Definition: Atomic.h:84
virtual void decorateWithTBAA(Instruction *I)=0
CallInst * EmitAtomicLibcall(StringRef fnName, Type *ResultType, ArrayRef< Value * > Args)
Definition: Atomic.cpp:37
Value * getAtomicSizeValue() const
Definition: Atomic.h:65
bool shouldUseLibcall() const
Definition: Atomic.h:39
Type * Ty
Definition: Atomic.h:19
Align getAtomicAlignment() const
Definition: Atomic.h:36
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.
const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
Definition: BasicBlock.cpp:292
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.
AtomicCmpXchgInst * CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SyncScope::ID SSID=SyncScope::System)
Definition: IRBuilder.h:1843
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
Definition: IRBuilder.h:1809
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition: IRBuilder.h:2549
BasicBlock * GetInsertBlock() const
Definition: IRBuilder.h:188
LLVMContext & getContext() const
Definition: IRBuilder.h:190
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2443
Value * CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:2151
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
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