Path: blob/main/contrib/llvm-project/llvm/lib/Frontend/Atomic/Atomic.cpp
213799 views
//===--- Atomic.cpp - Codegen of atomic operations ------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/Frontend/Atomic/Atomic.h"9#include "llvm/IR/DerivedTypes.h"10#include "llvm/IR/IRBuilder.h"11#include <utility>1213using namespace llvm;1415bool AtomicInfo::shouldCastToInt(Type *ValTy, bool CmpXchg) {16if (ValTy->isFloatingPointTy())17return ValTy->isX86_FP80Ty() || CmpXchg;18return !ValTy->isIntegerTy() && !ValTy->isPointerTy();19}2021Value *AtomicInfo::EmitAtomicLoadOp(AtomicOrdering AO, bool IsVolatile,22bool CmpXchg) {23Value *Ptr = getAtomicPointer();24Type *AtomicTy = Ty;25if (shouldCastToInt(Ty, CmpXchg))26AtomicTy = IntegerType::get(getLLVMContext(), AtomicSizeInBits);27LoadInst *Load =28Builder->CreateAlignedLoad(AtomicTy, Ptr, AtomicAlign, "atomic-load");29Load->setAtomic(AO);30if (IsVolatile)31Load->setVolatile(true);32decorateWithTBAA(Load);33return Load;34}3536CallInst *AtomicInfo::EmitAtomicLibcall(StringRef fnName, Type *ResultType,37ArrayRef<Value *> Args) {38LLVMContext &ctx = Builder->getContext();39SmallVector<Type *, 6> ArgTys;40for (Value *Arg : Args)41ArgTys.push_back(Arg->getType());42FunctionType *FnType = FunctionType::get(ResultType, ArgTys, false);43Module *M = Builder->GetInsertBlock()->getModule();4445// TODO: Use llvm::TargetLowering for Libcall ABI46AttrBuilder fnAttrBuilder(ctx);47fnAttrBuilder.addAttribute(Attribute::NoUnwind);48fnAttrBuilder.addAttribute(Attribute::WillReturn);49AttributeList fnAttrs =50AttributeList::get(ctx, AttributeList::FunctionIndex, fnAttrBuilder);51FunctionCallee LibcallFn = M->getOrInsertFunction(fnName, FnType, fnAttrs);52CallInst *Call = Builder->CreateCall(LibcallFn, Args);53return Call;54}5556std::pair<Value *, Value *> AtomicInfo::EmitAtomicCompareExchangeLibcall(57Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success,58AtomicOrdering Failure) {59LLVMContext &ctx = getLLVMContext();6061// __atomic_compare_exchange's expected and desired are passed by pointers62// FIXME: types6364// TODO: Get from llvm::TargetMachine / clang::TargetInfo65// if clang shares this codegen in future66constexpr uint64_t IntBits = 32;6768// bool __atomic_compare_exchange(size_t size, void *obj, void *expected,69// void *desired, int success, int failure);7071Value *Args[6] = {72getAtomicSizeValue(),73getAtomicPointer(),74ExpectedVal,75DesiredVal,76Constant::getIntegerValue(IntegerType::get(ctx, IntBits),77APInt(IntBits, static_cast<uint64_t>(Success),78/*signed=*/true)),79Constant::getIntegerValue(IntegerType::get(ctx, IntBits),80APInt(IntBits, static_cast<uint64_t>(Failure),81/*signed=*/true)),82};83auto Result = EmitAtomicLibcall("__atomic_compare_exchange",84IntegerType::getInt1Ty(ctx), Args);85return std::make_pair(ExpectedVal, Result);86}8788std::pair<Value *, Value *> AtomicInfo::EmitAtomicCompareExchangeOp(89Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success,90AtomicOrdering Failure, bool IsVolatile, bool IsWeak) {91// Do the atomic store.92Value *Addr = getAtomicAddressAsAtomicIntPointer();93auto *Inst = Builder->CreateAtomicCmpXchg(Addr, ExpectedVal, DesiredVal,94getAtomicAlignment(), Success,95Failure, SyncScope::System);9697// Other decoration.98Inst->setVolatile(IsVolatile);99Inst->setWeak(IsWeak);100auto *PreviousVal = Builder->CreateExtractValue(Inst, /*Idxs=*/0);101auto *SuccessFailureVal = Builder->CreateExtractValue(Inst, /*Idxs=*/1);102return std::make_pair(PreviousVal, SuccessFailureVal);103}104105std::pair<LoadInst *, AllocaInst *>106AtomicInfo::EmitAtomicLoadLibcall(AtomicOrdering AO) {107LLVMContext &Ctx = getLLVMContext();108Type *SizedIntTy = Type::getIntNTy(Ctx, getAtomicSizeInBits());109Type *ResultTy;110SmallVector<Value *, 6> Args;111AttributeList Attr;112Module *M = Builder->GetInsertBlock()->getModule();113const DataLayout &DL = M->getDataLayout();114Args.push_back(115ConstantInt::get(DL.getIntPtrType(Ctx), this->getAtomicSizeInBits() / 8));116117Value *PtrVal = getAtomicPointer();118PtrVal = Builder->CreateAddrSpaceCast(PtrVal, PointerType::getUnqual(Ctx));119Args.push_back(PtrVal);120121auto CurrentIP = Builder->saveIP();122Builder->restoreIP(AllocaIP);123AllocaInst *AllocaResult =124CreateAlloca(Ty, getAtomicPointer()->getName() + "atomic.temp.load");125Builder->restoreIP(CurrentIP);126const Align AllocaAlignment = DL.getPrefTypeAlign(SizedIntTy);127AllocaResult->setAlignment(AllocaAlignment);128Args.push_back(AllocaResult);129Constant *OrderingVal =130ConstantInt::get(Type::getInt32Ty(Ctx), (int)toCABI(AO));131Args.push_back(OrderingVal);132133ResultTy = Type::getVoidTy(Ctx);134SmallVector<Type *, 6> ArgTys;135for (Value *Arg : Args)136ArgTys.push_back(Arg->getType());137FunctionType *FnType = FunctionType::get(ResultTy, ArgTys, false);138FunctionCallee LibcallFn =139M->getOrInsertFunction("__atomic_load", FnType, Attr);140CallInst *Call = Builder->CreateCall(LibcallFn, Args);141Call->setAttributes(Attr);142return std::make_pair(143Builder->CreateAlignedLoad(Ty, AllocaResult, AllocaAlignment),144AllocaResult);145}146147void AtomicInfo::EmitAtomicStoreLibcall(AtomicOrdering AO, Value *Source) {148LLVMContext &Ctx = getLLVMContext();149SmallVector<Value *, 6> Args;150AttributeList Attr;151Module *M = Builder->GetInsertBlock()->getModule();152const DataLayout &DL = M->getDataLayout();153Args.push_back(154ConstantInt::get(DL.getIntPtrType(Ctx), this->getAtomicSizeInBits() / 8));155156Value *PtrVal = getAtomicPointer();157PtrVal = Builder->CreateAddrSpaceCast(PtrVal, PointerType::getUnqual(Ctx));158Args.push_back(PtrVal);159160auto CurrentIP = Builder->saveIP();161Builder->restoreIP(AllocaIP);162Value *SourceAlloca = Builder->CreateAlloca(Source->getType());163Builder->restoreIP(CurrentIP);164Builder->CreateStore(Source, SourceAlloca);165SourceAlloca = Builder->CreatePointerBitCastOrAddrSpaceCast(166SourceAlloca, Builder->getPtrTy());167Args.push_back(SourceAlloca);168169Constant *OrderingVal =170ConstantInt::get(Type::getInt32Ty(Ctx), (int)toCABI(AO));171Args.push_back(OrderingVal);172173SmallVector<Type *, 6> ArgTys;174for (Value *Arg : Args)175ArgTys.push_back(Arg->getType());176FunctionType *FnType = FunctionType::get(Type::getVoidTy(Ctx), ArgTys, false);177FunctionCallee LibcallFn =178M->getOrInsertFunction("__atomic_store", FnType, Attr);179CallInst *Call = Builder->CreateCall(LibcallFn, Args);180Call->setAttributes(Attr);181}182183std::pair<Value *, Value *> AtomicInfo::EmitAtomicCompareExchange(184Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success,185AtomicOrdering Failure, bool IsVolatile, bool IsWeak) {186if (shouldUseLibcall())187return EmitAtomicCompareExchangeLibcall(ExpectedVal, DesiredVal, Success,188Failure);189190auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success,191Failure, IsVolatile, IsWeak);192return Res;193}194195196