[llvm][OpenMP][NFC] Cleanup AtomicInfo (#119199)
This PR refactors functionality from llvm/include/llvm/Frontend/Atomic/Atomic.h into llvm/lib/llvm/Frontend/Atomic/Atomic.cpp.
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
//===--- Atomic.h - Codegen of atomic operations
|
||||
//---------------------------===//
|
||||
//===--- Atomic.h - Codegen of atomic operations ------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@@ -10,46 +9,39 @@
|
||||
#ifndef LLVM_FRONTEND_ATOMIC_ATOMIC_H
|
||||
#define LLVM_FRONTEND_ATOMIC_ATOMIC_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/Operator.h"
|
||||
#include "llvm/IR/RuntimeLibcalls.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template <typename IRBuilderTy> struct AtomicInfo {
|
||||
|
||||
IRBuilderTy *Builder;
|
||||
class AtomicInfo {
|
||||
protected:
|
||||
IRBuilderBase *Builder;
|
||||
Type *Ty;
|
||||
uint64_t AtomicSizeInBits;
|
||||
uint64_t ValueSizeInBits;
|
||||
llvm::Align AtomicAlign;
|
||||
llvm::Align ValueAlign;
|
||||
Align AtomicAlign;
|
||||
Align ValueAlign;
|
||||
bool UseLibcall;
|
||||
|
||||
public:
|
||||
AtomicInfo(IRBuilderTy *Builder, Type *Ty, uint64_t AtomicSizeInBits,
|
||||
uint64_t ValueSizeInBits, llvm::Align AtomicAlign,
|
||||
llvm::Align ValueAlign, bool UseLibcall)
|
||||
AtomicInfo(IRBuilderBase *Builder, Type *Ty, uint64_t AtomicSizeInBits,
|
||||
uint64_t ValueSizeInBits, Align AtomicAlign, Align ValueAlign,
|
||||
bool UseLibcall)
|
||||
: Builder(Builder), Ty(Ty), AtomicSizeInBits(AtomicSizeInBits),
|
||||
ValueSizeInBits(ValueSizeInBits), AtomicAlign(AtomicAlign),
|
||||
ValueAlign(ValueAlign), UseLibcall(UseLibcall) {}
|
||||
|
||||
virtual ~AtomicInfo() = default;
|
||||
|
||||
llvm::Align getAtomicAlignment() const { return AtomicAlign; }
|
||||
Align getAtomicAlignment() const { return AtomicAlign; }
|
||||
uint64_t getAtomicSizeInBits() const { return AtomicSizeInBits; }
|
||||
uint64_t getValueSizeInBits() const { return ValueSizeInBits; }
|
||||
bool shouldUseLibcall() const { return UseLibcall; }
|
||||
llvm::Type *getAtomicTy() const { return Ty; }
|
||||
Type *getAtomicTy() const { return Ty; }
|
||||
|
||||
virtual llvm::Value *getAtomicPointer() const = 0;
|
||||
virtual Value *getAtomicPointer() const = 0;
|
||||
virtual void decorateWithTBAA(Instruction *I) = 0;
|
||||
virtual llvm::AllocaInst *CreateAlloca(llvm::Type *Ty,
|
||||
const llvm::Twine &Name) const = 0;
|
||||
virtual AllocaInst *CreateAlloca(Type *Ty, const Twine &Name) const = 0;
|
||||
|
||||
/*
|
||||
* Is the atomic size larger than the underlying value type?
|
||||
@@ -62,90 +54,28 @@ public:
|
||||
|
||||
LLVMContext &getLLVMContext() const { return Builder->getContext(); }
|
||||
|
||||
static bool shouldCastToInt(llvm::Type *ValTy, bool CmpXchg) {
|
||||
if (ValTy->isFloatingPointTy())
|
||||
return ValTy->isX86_FP80Ty() || CmpXchg;
|
||||
return !ValTy->isIntegerTy() && !ValTy->isPointerTy();
|
||||
}
|
||||
bool shouldCastToInt(Type *ValTy, bool CmpXchg);
|
||||
|
||||
llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile,
|
||||
bool CmpXchg = false) {
|
||||
Value *Ptr = getAtomicPointer();
|
||||
Type *AtomicTy = Ty;
|
||||
if (shouldCastToInt(Ty, CmpXchg))
|
||||
AtomicTy = llvm::IntegerType::get(getLLVMContext(), AtomicSizeInBits);
|
||||
LoadInst *Load =
|
||||
Builder->CreateAlignedLoad(AtomicTy, Ptr, AtomicAlign, "atomic-load");
|
||||
Load->setAtomic(AO);
|
||||
if (IsVolatile)
|
||||
Load->setVolatile(true);
|
||||
decorateWithTBAA(Load);
|
||||
return Load;
|
||||
}
|
||||
Value *EmitAtomicLoadOp(AtomicOrdering AO, bool IsVolatile,
|
||||
bool CmpXchg = false);
|
||||
|
||||
static CallInst *EmitAtomicLibcall(IRBuilderTy *Builder, StringRef fnName,
|
||||
Type *ResultType, ArrayRef<Value *> Args) {
|
||||
LLVMContext &ctx = Builder->getContext();
|
||||
SmallVector<Type *, 6> ArgTys;
|
||||
for (Value *Arg : Args)
|
||||
ArgTys.push_back(Arg->getType());
|
||||
FunctionType *FnType = FunctionType::get(ResultType, ArgTys, false);
|
||||
Module *M = Builder->GetInsertBlock()->getModule();
|
||||
CallInst *EmitAtomicLibcall(StringRef fnName, Type *ResultType,
|
||||
ArrayRef<Value *> Args);
|
||||
|
||||
// TODO: Use llvm::TargetLowering for Libcall ABI
|
||||
llvm::AttrBuilder fnAttrBuilder(ctx);
|
||||
fnAttrBuilder.addAttribute(llvm::Attribute::NoUnwind);
|
||||
fnAttrBuilder.addAttribute(llvm::Attribute::WillReturn);
|
||||
llvm::AttributeList fnAttrs = llvm::AttributeList::get(
|
||||
ctx, llvm::AttributeList::FunctionIndex, fnAttrBuilder);
|
||||
FunctionCallee LibcallFn = M->getOrInsertFunction(fnName, FnType, fnAttrs);
|
||||
CallInst *Call = Builder->CreateCall(LibcallFn, Args);
|
||||
return Call;
|
||||
}
|
||||
|
||||
llvm::Value *getAtomicSizeValue() const {
|
||||
Value *getAtomicSizeValue() const {
|
||||
LLVMContext &ctx = getLLVMContext();
|
||||
|
||||
// TODO: Get from llvm::TargetMachine / clang::TargetInfo
|
||||
// if clang shares this codegen in future
|
||||
// if clang shares this codegen in future
|
||||
constexpr uint16_t SizeTBits = 64;
|
||||
constexpr uint16_t BitsPerByte = 8;
|
||||
return llvm::ConstantInt::get(llvm::IntegerType::get(ctx, SizeTBits),
|
||||
AtomicSizeInBits / BitsPerByte);
|
||||
return ConstantInt::get(IntegerType::get(ctx, SizeTBits),
|
||||
AtomicSizeInBits / BitsPerByte);
|
||||
}
|
||||
|
||||
std::pair<llvm::Value *, llvm::Value *> EmitAtomicCompareExchangeLibcall(
|
||||
llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
|
||||
llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure) {
|
||||
LLVMContext &ctx = getLLVMContext();
|
||||
|
||||
// __atomic_compare_exchange's expected and desired are passed by pointers
|
||||
// FIXME: types
|
||||
|
||||
// TODO: Get from llvm::TargetMachine / clang::TargetInfo
|
||||
// if clang shares this codegen in future
|
||||
constexpr uint64_t IntBits = 32;
|
||||
|
||||
// bool __atomic_compare_exchange(size_t size, void *obj, void *expected,
|
||||
// void *desired, int success, int failure);
|
||||
llvm::Value *Args[6] = {
|
||||
getAtomicSizeValue(),
|
||||
getAtomicPointer(),
|
||||
ExpectedVal,
|
||||
DesiredVal,
|
||||
llvm::Constant::getIntegerValue(
|
||||
llvm::IntegerType::get(ctx, IntBits),
|
||||
llvm::APInt(IntBits, static_cast<uint64_t>(Success),
|
||||
/*signed=*/true)),
|
||||
llvm::Constant::getIntegerValue(
|
||||
llvm::IntegerType::get(ctx, IntBits),
|
||||
llvm::APInt(IntBits, static_cast<uint64_t>(Failure),
|
||||
/*signed=*/true)),
|
||||
};
|
||||
auto Result = EmitAtomicLibcall(Builder, "__atomic_compare_exchange",
|
||||
llvm::IntegerType::getInt1Ty(ctx), Args);
|
||||
return std::make_pair(ExpectedVal, Result);
|
||||
}
|
||||
std::pair<Value *, Value *>
|
||||
EmitAtomicCompareExchangeLibcall(Value *ExpectedVal, Value *DesiredVal,
|
||||
AtomicOrdering Success,
|
||||
AtomicOrdering Failure);
|
||||
|
||||
Value *castToAtomicIntPointer(Value *addr) const {
|
||||
return addr; // opaque pointer
|
||||
@@ -155,77 +85,17 @@ public:
|
||||
return castToAtomicIntPointer(getAtomicPointer());
|
||||
}
|
||||
|
||||
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) {
|
||||
// Do the atomic store.
|
||||
Value *Addr = getAtomicAddressAsAtomicIntPointer();
|
||||
auto *Inst = Builder->CreateAtomicCmpXchg(Addr, ExpectedVal, DesiredVal,
|
||||
getAtomicAlignment(), Success,
|
||||
Failure, llvm::SyncScope::System);
|
||||
// Other decoration.
|
||||
Inst->setVolatile(IsVolatile);
|
||||
Inst->setWeak(IsWeak);
|
||||
std::pair<Value *, Value *>
|
||||
EmitAtomicCompareExchangeOp(Value *ExpectedVal, Value *DesiredVal,
|
||||
AtomicOrdering Success, AtomicOrdering Failure,
|
||||
bool IsVolatile = false, bool IsWeak = false);
|
||||
|
||||
auto *PreviousVal = Builder->CreateExtractValue(Inst, /*Idxs=*/0);
|
||||
auto *SuccessFailureVal = Builder->CreateExtractValue(Inst, /*Idxs=*/1);
|
||||
return std::make_pair(PreviousVal, SuccessFailureVal);
|
||||
}
|
||||
std::pair<Value *, Value *>
|
||||
EmitAtomicCompareExchange(Value *ExpectedVal, Value *DesiredVal,
|
||||
AtomicOrdering Success, AtomicOrdering Failure,
|
||||
bool IsVolatile, bool IsWeak);
|
||||
|
||||
std::pair<llvm::Value *, llvm::Value *>
|
||||
EmitAtomicCompareExchange(llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
|
||||
llvm::AtomicOrdering Success,
|
||||
llvm::AtomicOrdering Failure, bool IsVolatile,
|
||||
bool IsWeak) {
|
||||
if (shouldUseLibcall())
|
||||
return EmitAtomicCompareExchangeLibcall(ExpectedVal, DesiredVal, Success,
|
||||
Failure);
|
||||
|
||||
auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success,
|
||||
Failure, IsVolatile, IsWeak);
|
||||
return Res;
|
||||
}
|
||||
|
||||
// void __atomic_load(size_t size, void *mem, void *return, int order);
|
||||
std::pair<llvm::LoadInst *, llvm::AllocaInst *>
|
||||
EmitAtomicLoadLibcall(llvm::AtomicOrdering AO) {
|
||||
LLVMContext &Ctx = getLLVMContext();
|
||||
Type *SizedIntTy = Type::getIntNTy(Ctx, getAtomicSizeInBits());
|
||||
Type *ResultTy;
|
||||
SmallVector<Value *, 6> Args;
|
||||
AttributeList Attr;
|
||||
Module *M = Builder->GetInsertBlock()->getModule();
|
||||
const DataLayout &DL = M->getDataLayout();
|
||||
Args.push_back(ConstantInt::get(DL.getIntPtrType(Ctx),
|
||||
this->getAtomicSizeInBits() / 8));
|
||||
|
||||
Value *PtrVal = getAtomicPointer();
|
||||
PtrVal = Builder->CreateAddrSpaceCast(PtrVal, PointerType::getUnqual(Ctx));
|
||||
Args.push_back(PtrVal);
|
||||
AllocaInst *AllocaResult =
|
||||
CreateAlloca(Ty, getAtomicPointer()->getName() + "atomic.temp.load");
|
||||
const Align AllocaAlignment = DL.getPrefTypeAlign(SizedIntTy);
|
||||
AllocaResult->setAlignment(AllocaAlignment);
|
||||
Args.push_back(AllocaResult);
|
||||
Constant *OrderingVal =
|
||||
ConstantInt::get(Type::getInt32Ty(Ctx), (int)toCABI(AO));
|
||||
Args.push_back(OrderingVal);
|
||||
|
||||
ResultTy = Type::getVoidTy(Ctx);
|
||||
SmallVector<Type *, 6> ArgTys;
|
||||
for (Value *Arg : Args)
|
||||
ArgTys.push_back(Arg->getType());
|
||||
FunctionType *FnType = FunctionType::get(ResultTy, ArgTys, false);
|
||||
FunctionCallee LibcallFn =
|
||||
M->getOrInsertFunction("__atomic_load", FnType, Attr);
|
||||
CallInst *Call = Builder->CreateCall(LibcallFn, Args);
|
||||
Call->setAttributes(Attr);
|
||||
return std::make_pair(
|
||||
Builder->CreateAlignedLoad(Ty, AllocaResult, AllocaAlignment),
|
||||
AllocaResult);
|
||||
}
|
||||
std::pair<LoadInst *, AllocaInst *> EmitAtomicLoadLibcall(AtomicOrdering AO);
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
|
||||
@@ -480,16 +480,15 @@ public:
|
||||
T(Triple(M.getTargetTriple())) {}
|
||||
~OpenMPIRBuilder();
|
||||
|
||||
class AtomicInfo : public llvm::AtomicInfo<IRBuilder<>> {
|
||||
class AtomicInfo : public llvm::AtomicInfo {
|
||||
llvm::Value *AtomicVar;
|
||||
|
||||
public:
|
||||
AtomicInfo(IRBuilder<> *Builder, llvm::Type *Ty, uint64_t AtomicSizeInBits,
|
||||
uint64_t ValueSizeInBits, llvm::Align AtomicAlign,
|
||||
llvm::Align ValueAlign, bool UseLibcall, llvm::Value *AtomicVar)
|
||||
: llvm::AtomicInfo<IRBuilder<>>(Builder, Ty, AtomicSizeInBits,
|
||||
ValueSizeInBits, AtomicAlign,
|
||||
ValueAlign, UseLibcall),
|
||||
: llvm::AtomicInfo(Builder, Ty, AtomicSizeInBits, ValueSizeInBits,
|
||||
AtomicAlign, ValueAlign, UseLibcall),
|
||||
AtomicVar(AtomicVar) {}
|
||||
|
||||
llvm::Value *getAtomicPointer() const override { return AtomicVar; }
|
||||
@@ -3156,15 +3155,6 @@ private:
|
||||
AtomicUpdateCallbackTy &UpdateOp, bool VolatileX,
|
||||
bool IsXBinopExpr);
|
||||
|
||||
std::pair<llvm::LoadInst *, llvm::AllocaInst *>
|
||||
EmitAtomicLoadLibcall(Value *X, Type *XElemTy, llvm::AtomicOrdering AO,
|
||||
uint64_t AtomicSizeInBits);
|
||||
|
||||
std::pair<llvm::Value *, llvm::Value *> EmitAtomicCompareExchangeLibcall(
|
||||
Value *X, Type *XElemTy, uint64_t AtomicSizeInBits,
|
||||
llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
|
||||
llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure);
|
||||
|
||||
/// Emit the binary op. described by \p RMWOp, using \p Src1 and \p Src2 .
|
||||
///
|
||||
/// \Return The instruction
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//===--- Atomic.h - Codegen of atomic operations
|
||||
//---------------------------===//
|
||||
//===--- Atomic.cpp - Codegen of atomic operations ------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@@ -8,7 +7,148 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Frontend/Atomic/Atomic.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include <utility>
|
||||
|
||||
namespace {} // namespace
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {} // end namespace llvm
|
||||
bool AtomicInfo::shouldCastToInt(Type *ValTy, bool CmpXchg) {
|
||||
if (ValTy->isFloatingPointTy())
|
||||
return ValTy->isX86_FP80Ty() || CmpXchg;
|
||||
return !ValTy->isIntegerTy() && !ValTy->isPointerTy();
|
||||
}
|
||||
|
||||
Value *AtomicInfo::EmitAtomicLoadOp(AtomicOrdering AO, bool IsVolatile,
|
||||
bool CmpXchg) {
|
||||
Value *Ptr = getAtomicPointer();
|
||||
Type *AtomicTy = Ty;
|
||||
if (shouldCastToInt(Ty, CmpXchg))
|
||||
AtomicTy = IntegerType::get(getLLVMContext(), AtomicSizeInBits);
|
||||
LoadInst *Load =
|
||||
Builder->CreateAlignedLoad(AtomicTy, Ptr, AtomicAlign, "atomic-load");
|
||||
Load->setAtomic(AO);
|
||||
if (IsVolatile)
|
||||
Load->setVolatile(true);
|
||||
decorateWithTBAA(Load);
|
||||
return Load;
|
||||
}
|
||||
|
||||
CallInst *AtomicInfo::EmitAtomicLibcall(StringRef fnName, Type *ResultType,
|
||||
ArrayRef<Value *> Args) {
|
||||
LLVMContext &ctx = Builder->getContext();
|
||||
SmallVector<Type *, 6> ArgTys;
|
||||
for (Value *Arg : Args)
|
||||
ArgTys.push_back(Arg->getType());
|
||||
FunctionType *FnType = FunctionType::get(ResultType, ArgTys, false);
|
||||
Module *M = Builder->GetInsertBlock()->getModule();
|
||||
|
||||
// TODO: Use llvm::TargetLowering for Libcall ABI
|
||||
AttrBuilder fnAttrBuilder(ctx);
|
||||
fnAttrBuilder.addAttribute(Attribute::NoUnwind);
|
||||
fnAttrBuilder.addAttribute(Attribute::WillReturn);
|
||||
AttributeList fnAttrs =
|
||||
AttributeList::get(ctx, AttributeList::FunctionIndex, fnAttrBuilder);
|
||||
FunctionCallee LibcallFn = M->getOrInsertFunction(fnName, FnType, fnAttrs);
|
||||
CallInst *Call = Builder->CreateCall(LibcallFn, Args);
|
||||
return Call;
|
||||
}
|
||||
|
||||
std::pair<Value *, Value *> AtomicInfo::EmitAtomicCompareExchangeLibcall(
|
||||
Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success,
|
||||
AtomicOrdering Failure) {
|
||||
LLVMContext &ctx = getLLVMContext();
|
||||
|
||||
// __atomic_compare_exchange's expected and desired are passed by pointers
|
||||
// FIXME: types
|
||||
|
||||
// TODO: Get from llvm::TargetMachine / clang::TargetInfo
|
||||
// if clang shares this codegen in future
|
||||
constexpr uint64_t IntBits = 32;
|
||||
|
||||
// bool __atomic_compare_exchange(size_t size, void *obj, void *expected,
|
||||
// void *desired, int success, int failure);
|
||||
|
||||
Value *Args[6] = {
|
||||
getAtomicSizeValue(),
|
||||
getAtomicPointer(),
|
||||
ExpectedVal,
|
||||
DesiredVal,
|
||||
Constant::getIntegerValue(IntegerType::get(ctx, IntBits),
|
||||
APInt(IntBits, static_cast<uint64_t>(Success),
|
||||
/*signed=*/true)),
|
||||
Constant::getIntegerValue(IntegerType::get(ctx, IntBits),
|
||||
APInt(IntBits, static_cast<uint64_t>(Failure),
|
||||
/*signed=*/true)),
|
||||
};
|
||||
auto Result = EmitAtomicLibcall("__atomic_compare_exchange",
|
||||
IntegerType::getInt1Ty(ctx), Args);
|
||||
return std::make_pair(ExpectedVal, Result);
|
||||
}
|
||||
|
||||
std::pair<Value *, Value *> AtomicInfo::EmitAtomicCompareExchangeOp(
|
||||
Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success,
|
||||
AtomicOrdering Failure, bool IsVolatile, bool IsWeak) {
|
||||
// Do the atomic store.
|
||||
Value *Addr = getAtomicAddressAsAtomicIntPointer();
|
||||
auto *Inst = Builder->CreateAtomicCmpXchg(Addr, ExpectedVal, DesiredVal,
|
||||
getAtomicAlignment(), Success,
|
||||
Failure, SyncScope::System);
|
||||
|
||||
// Other decoration.
|
||||
Inst->setVolatile(IsVolatile);
|
||||
Inst->setWeak(IsWeak);
|
||||
auto *PreviousVal = Builder->CreateExtractValue(Inst, /*Idxs=*/0);
|
||||
auto *SuccessFailureVal = Builder->CreateExtractValue(Inst, /*Idxs=*/1);
|
||||
return std::make_pair(PreviousVal, SuccessFailureVal);
|
||||
}
|
||||
|
||||
std::pair<LoadInst *, AllocaInst *>
|
||||
AtomicInfo::EmitAtomicLoadLibcall(AtomicOrdering AO) {
|
||||
LLVMContext &Ctx = getLLVMContext();
|
||||
Type *SizedIntTy = Type::getIntNTy(Ctx, getAtomicSizeInBits());
|
||||
Type *ResultTy;
|
||||
SmallVector<Value *, 6> Args;
|
||||
AttributeList Attr;
|
||||
Module *M = Builder->GetInsertBlock()->getModule();
|
||||
const DataLayout &DL = M->getDataLayout();
|
||||
Args.push_back(
|
||||
ConstantInt::get(DL.getIntPtrType(Ctx), this->getAtomicSizeInBits() / 8));
|
||||
|
||||
Value *PtrVal = getAtomicPointer();
|
||||
PtrVal = Builder->CreateAddrSpaceCast(PtrVal, PointerType::getUnqual(Ctx));
|
||||
Args.push_back(PtrVal);
|
||||
AllocaInst *AllocaResult =
|
||||
CreateAlloca(Ty, getAtomicPointer()->getName() + "atomic.temp.load");
|
||||
const Align AllocaAlignment = DL.getPrefTypeAlign(SizedIntTy);
|
||||
AllocaResult->setAlignment(AllocaAlignment);
|
||||
Args.push_back(AllocaResult);
|
||||
Constant *OrderingVal =
|
||||
ConstantInt::get(Type::getInt32Ty(Ctx), (int)toCABI(AO));
|
||||
Args.push_back(OrderingVal);
|
||||
|
||||
ResultTy = Type::getVoidTy(Ctx);
|
||||
SmallVector<Type *, 6> ArgTys;
|
||||
for (Value *Arg : Args)
|
||||
ArgTys.push_back(Arg->getType());
|
||||
FunctionType *FnType = FunctionType::get(ResultTy, ArgTys, false);
|
||||
FunctionCallee LibcallFn =
|
||||
M->getOrInsertFunction("__atomic_load", FnType, Attr);
|
||||
CallInst *Call = Builder->CreateCall(LibcallFn, Args);
|
||||
Call->setAttributes(Attr);
|
||||
return std::make_pair(
|
||||
Builder->CreateAlignedLoad(Ty, AllocaResult, AllocaAlignment),
|
||||
AllocaResult);
|
||||
}
|
||||
|
||||
std::pair<Value *, Value *> AtomicInfo::EmitAtomicCompareExchange(
|
||||
Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success,
|
||||
AtomicOrdering Failure, bool IsVolatile, bool IsWeak) {
|
||||
if (shouldUseLibcall())
|
||||
return EmitAtomicCompareExchangeLibcall(ExpectedVal, DesiredVal, Success,
|
||||
Failure);
|
||||
|
||||
auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success,
|
||||
Failure, IsVolatile, IsWeak);
|
||||
return Res;
|
||||
}
|
||||
|
||||
@@ -22,4 +22,5 @@ add_llvm_component_library(LLVMFrontendOpenMP
|
||||
Scalar
|
||||
BitReader
|
||||
FrontendOffloading
|
||||
FrontendAtomic
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user