From 24fc8f01a40310e91838ab742b4940369786ba90 Mon Sep 17 00:00:00 2001 From: NimishMishra <42909663+NimishMishra@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:56:44 +0530 Subject: [PATCH] [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. --- llvm/include/llvm/Frontend/Atomic/Atomic.h | 202 ++++-------------- .../llvm/Frontend/OpenMP/OMPIRBuilder.h | 16 +- llvm/lib/Frontend/Atomic/Atomic.cpp | 148 ++++++++++++- llvm/lib/Frontend/OpenMP/CMakeLists.txt | 1 + 4 files changed, 184 insertions(+), 183 deletions(-) diff --git a/llvm/include/llvm/Frontend/Atomic/Atomic.h b/llvm/include/llvm/Frontend/Atomic/Atomic.h index 3942d06144ce1..9f46fde6292a9 100644 --- a/llvm/include/llvm/Frontend/Atomic/Atomic.h +++ b/llvm/include/llvm/Frontend/Atomic/Atomic.h @@ -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 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 @@ template struct AtomicInfo { 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 Args) { - LLVMContext &ctx = Builder->getContext(); - SmallVector 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 - 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; - } + CallInst *EmitAtomicLibcall(StringRef fnName, Type *ResultType, + ArrayRef Args); - 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 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(Success), - /*signed=*/true)), - llvm::Constant::getIntegerValue( - llvm::IntegerType::get(ctx, IntBits), - llvm::APInt(IntBits, static_cast(Failure), - /*signed=*/true)), - }; - auto Result = EmitAtomicLibcall(Builder, "__atomic_compare_exchange", - llvm::IntegerType::getInt1Ty(ctx), Args); - return std::make_pair(ExpectedVal, Result); - } + std::pair + EmitAtomicCompareExchangeLibcall(Value *ExpectedVal, Value *DesiredVal, + AtomicOrdering Success, + AtomicOrdering Failure); Value *castToAtomicIntPointer(Value *addr) const { return addr; // opaque pointer @@ -155,77 +85,17 @@ template struct AtomicInfo { return castToAtomicIntPointer(getAtomicPointer()); } - std::pair - 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); - - auto *PreviousVal = Builder->CreateExtractValue(Inst, /*Idxs=*/0); - auto *SuccessFailureVal = Builder->CreateExtractValue(Inst, /*Idxs=*/1); - return std::make_pair(PreviousVal, SuccessFailureVal); - } + std::pair + EmitAtomicCompareExchangeOp(Value *ExpectedVal, Value *DesiredVal, + AtomicOrdering Success, AtomicOrdering Failure, + bool IsVolatile = false, bool IsWeak = false); - std::pair - 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; - } + std::pair + EmitAtomicCompareExchange(Value *ExpectedVal, Value *DesiredVal, + AtomicOrdering Success, AtomicOrdering Failure, + bool IsVolatile, bool IsWeak); - // void __atomic_load(size_t size, void *mem, void *return, int order); - std::pair - EmitAtomicLoadLibcall(llvm::AtomicOrdering AO) { - LLVMContext &Ctx = getLLVMContext(); - Type *SizedIntTy = Type::getIntNTy(Ctx, getAtomicSizeInBits()); - Type *ResultTy; - SmallVector 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 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 EmitAtomicLoadLibcall(AtomicOrdering AO); }; } // end namespace llvm diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h index 9a7c7f72711cc..4ce47b1c05d9b 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h @@ -480,16 +480,15 @@ class OpenMPIRBuilder { T(Triple(M.getTargetTriple())) {} ~OpenMPIRBuilder(); - class AtomicInfo : public llvm::AtomicInfo> { + 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>(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 @@ class OpenMPIRBuilder { AtomicUpdateCallbackTy &UpdateOp, bool VolatileX, bool IsXBinopExpr); - std::pair - EmitAtomicLoadLibcall(Value *X, Type *XElemTy, llvm::AtomicOrdering AO, - uint64_t AtomicSizeInBits); - - std::pair 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 diff --git a/llvm/lib/Frontend/Atomic/Atomic.cpp b/llvm/lib/Frontend/Atomic/Atomic.cpp index b54312293f9b0..c9f9a9dcfb702 100644 --- a/llvm/lib/Frontend/Atomic/Atomic.cpp +++ b/llvm/lib/Frontend/Atomic/Atomic.cpp @@ -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 -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 Args) { + LLVMContext &ctx = Builder->getContext(); + SmallVector 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 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(Success), + /*signed=*/true)), + Constant::getIntegerValue(IntegerType::get(ctx, IntBits), + APInt(IntBits, static_cast(Failure), + /*signed=*/true)), + }; + auto Result = EmitAtomicLibcall("__atomic_compare_exchange", + IntegerType::getInt1Ty(ctx), Args); + return std::make_pair(ExpectedVal, Result); +} + +std::pair 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 +AtomicInfo::EmitAtomicLoadLibcall(AtomicOrdering AO) { + LLVMContext &Ctx = getLLVMContext(); + Type *SizedIntTy = Type::getIntNTy(Ctx, getAtomicSizeInBits()); + Type *ResultTy; + SmallVector 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 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 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; +} diff --git a/llvm/lib/Frontend/OpenMP/CMakeLists.txt b/llvm/lib/Frontend/OpenMP/CMakeLists.txt index 82d2a9ae7c533..35c607866a94e 100644 --- a/llvm/lib/Frontend/OpenMP/CMakeLists.txt +++ b/llvm/lib/Frontend/OpenMP/CMakeLists.txt @@ -22,4 +22,5 @@ add_llvm_component_library(LLVMFrontendOpenMP Scalar BitReader FrontendOffloading + FrontendAtomic )