diff options
author | Matt Arsenault <Matthew.Arsenault@amd.com> | 2024-10-31 11:54:07 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-31 11:54:07 -0700 |
commit | 9cc298108a7bb34d0126028a529ecdcb0ade9baf (patch) | |
tree | bf09ca974fac70f69dcc9b0609c5fd0dfe1c3806 /llvm/lib/CodeGen/AtomicExpandPass.cpp | |
parent | 19c8475871faee5ebb06281034872a85a2552675 (diff) | |
download | llvm-9cc298108a7bb34d0126028a529ecdcb0ade9baf.zip llvm-9cc298108a7bb34d0126028a529ecdcb0ade9baf.tar.gz llvm-9cc298108a7bb34d0126028a529ecdcb0ade9baf.tar.bz2 |
AtomicExpand: Copy metadata from atomicrmw to cmpxchg (#109409)
When expanding an atomicrmw with a cmpxchg, preserve any metadata
attached to it. This will avoid unwanted double expansions
in a future commit.
The initial load should also probably receive the same metadata
(which for some reason is not emitted as an atomic).
Diffstat (limited to 'llvm/lib/CodeGen/AtomicExpandPass.cpp')
-rw-r--r-- | llvm/lib/CodeGen/AtomicExpandPass.cpp | 91 |
1 files changed, 51 insertions, 40 deletions
diff --git a/llvm/lib/CodeGen/AtomicExpandPass.cpp b/llvm/lib/CodeGen/AtomicExpandPass.cpp index 3d4e2cb..0aff4f1 100644 --- a/llvm/lib/CodeGen/AtomicExpandPass.cpp +++ b/llvm/lib/CodeGen/AtomicExpandPass.cpp @@ -98,7 +98,7 @@ private: IRBuilderBase &Builder, Type *ResultType, Value *Addr, Align AddrAlign, AtomicOrdering MemOpOrder, SyncScope::ID SSID, function_ref<Value *(IRBuilderBase &, Value *)> PerformOp, - CreateCmpXchgInstFun CreateCmpXchg); + CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc); bool tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI); bool expandAtomicCmpXchg(AtomicCmpXchgInst *CI); @@ -194,6 +194,39 @@ static unsigned getAtomicOpSize(AtomicCmpXchgInst *CASI) { return DL.getTypeStoreSize(CASI->getCompareOperand()->getType()); } +/// Copy metadata that's safe to preserve when widening atomics. +static void copyMetadataForAtomic(Instruction &Dest, + const Instruction &Source) { + SmallVector<std::pair<unsigned, MDNode *>, 8> MD; + Source.getAllMetadata(MD); + LLVMContext &Ctx = Dest.getContext(); + MDBuilder MDB(Ctx); + + for (auto [ID, N] : MD) { + switch (ID) { + case LLVMContext::MD_dbg: + case LLVMContext::MD_tbaa: + case LLVMContext::MD_tbaa_struct: + case LLVMContext::MD_alias_scope: + case LLVMContext::MD_noalias: + case LLVMContext::MD_noalias_addrspace: + case LLVMContext::MD_access_group: + case LLVMContext::MD_mmra: + Dest.setMetadata(ID, N); + break; + default: + if (ID == Ctx.getMDKindID("amdgpu.no.remote.memory")) + Dest.setMetadata(ID, N); + else if (ID == Ctx.getMDKindID("amdgpu.no.fine.grained.memory")) + Dest.setMetadata(ID, N); + + // Losing amdgpu.ignore.denormal.mode, but it doesn't matter for current + // uses. + break; + } + } +} + // Determine if a particular atomic operation has a supported size, // and is of appropriate alignment, to be passed through for target // lowering. (Versus turning into a __atomic libcall) @@ -600,7 +633,8 @@ void AtomicExpandImpl::expandAtomicStore(StoreInst *SI) { static void createCmpXchgInstFun(IRBuilderBase &Builder, Value *Addr, Value *Loaded, Value *NewVal, Align AddrAlign, AtomicOrdering MemOpOrder, SyncScope::ID SSID, - Value *&Success, Value *&NewLoaded) { + Value *&Success, Value *&NewLoaded, + Instruction *MetadataSrc) { Type *OrigTy = NewVal->getType(); // This code can go away when cmpxchg supports FP and vector types. @@ -612,9 +646,12 @@ static void createCmpXchgInstFun(IRBuilderBase &Builder, Value *Addr, Loaded = Builder.CreateBitCast(Loaded, IntTy); } - Value *Pair = Builder.CreateAtomicCmpXchg( + AtomicCmpXchgInst *Pair = Builder.CreateAtomicCmpXchg( Addr, Loaded, NewVal, AddrAlign, MemOpOrder, AtomicCmpXchgInst::getStrongestFailureOrdering(MemOpOrder), SSID); + if (MetadataSrc) + copyMetadataForAtomic(*Pair, *MetadataSrc); + Success = Builder.CreateExtractValue(Pair, 1, "success"); NewLoaded = Builder.CreateExtractValue(Pair, 0, "newloaded"); @@ -951,9 +988,9 @@ void AtomicExpandImpl::expandPartwordAtomicRMW( Value *OldResult; if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) { - OldResult = insertRMWCmpXchgLoop(Builder, PMV.WordType, PMV.AlignedAddr, - PMV.AlignedAddrAlignment, MemOpOrder, SSID, - PerformPartwordOp, createCmpXchgInstFun); + OldResult = insertRMWCmpXchgLoop( + Builder, PMV.WordType, PMV.AlignedAddr, PMV.AlignedAddrAlignment, + MemOpOrder, SSID, PerformPartwordOp, createCmpXchgInstFun, AI); } else { assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC); OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr, @@ -966,36 +1003,6 @@ void AtomicExpandImpl::expandPartwordAtomicRMW( AI->eraseFromParent(); } -/// Copy metadata that's safe to preserve when widening atomics. -static void copyMetadataForAtomic(Instruction &Dest, - const Instruction &Source) { - SmallVector<std::pair<unsigned, MDNode *>, 8> MD; - Source.getAllMetadata(MD); - LLVMContext &Ctx = Dest.getContext(); - MDBuilder MDB(Ctx); - - for (auto [ID, N] : MD) { - switch (ID) { - case LLVMContext::MD_dbg: - case LLVMContext::MD_tbaa: - case LLVMContext::MD_tbaa_struct: - case LLVMContext::MD_alias_scope: - case LLVMContext::MD_noalias: - case LLVMContext::MD_access_group: - case LLVMContext::MD_mmra: - Dest.setMetadata(ID, N); - break; - default: - if (ID == Ctx.getMDKindID("amdgpu.no.remote.memory")) - Dest.setMetadata(ID, N); - else if (ID == Ctx.getMDKindID("amdgpu.no.fine.grained.memory")) - Dest.setMetadata(ID, N); - - break; - } - } -} - // Widen the bitwise atomicrmw (or/xor/and) to the minimum supported width. AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) { ReplacementIRBuilder Builder(AI, *DL); @@ -1591,7 +1598,7 @@ Value *AtomicExpandImpl::insertRMWCmpXchgLoop( IRBuilderBase &Builder, Type *ResultTy, Value *Addr, Align AddrAlign, AtomicOrdering MemOpOrder, SyncScope::ID SSID, function_ref<Value *(IRBuilderBase &, Value *)> PerformOp, - CreateCmpXchgInstFun CreateCmpXchg) { + CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc) { LLVMContext &Ctx = Builder.getContext(); BasicBlock *BB = Builder.GetInsertBlock(); Function *F = BB->getParent(); @@ -1637,7 +1644,7 @@ Value *AtomicExpandImpl::insertRMWCmpXchgLoop( MemOpOrder == AtomicOrdering::Unordered ? AtomicOrdering::Monotonic : MemOpOrder, - SSID, Success, NewLoaded); + SSID, Success, NewLoaded, MetadataSrc); assert(Success && NewLoaded); Loaded->addIncoming(NewLoaded, LoopBB); @@ -1686,7 +1693,7 @@ bool llvm::expandAtomicRMWToCmpXchg(AtomicRMWInst *AI, return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded, AI->getValOperand()); }, - CreateCmpXchg); + CreateCmpXchg, /*MetadataSrc=*/AI); AI->replaceAllUsesWith(Loaded); AI->eraseFromParent(); @@ -1838,11 +1845,15 @@ void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *I) { expandAtomicRMWToCmpXchg( I, [this](IRBuilderBase &Builder, Value *Addr, Value *Loaded, Value *NewVal, Align Alignment, AtomicOrdering MemOpOrder, - SyncScope::ID SSID, Value *&Success, Value *&NewLoaded) { + SyncScope::ID SSID, Value *&Success, Value *&NewLoaded, + Instruction *MetadataSrc) { // Create the CAS instruction normally... AtomicCmpXchgInst *Pair = Builder.CreateAtomicCmpXchg( Addr, Loaded, NewVal, Alignment, MemOpOrder, AtomicCmpXchgInst::getStrongestFailureOrdering(MemOpOrder), SSID); + if (MetadataSrc) + copyMetadataForAtomic(*Pair, *MetadataSrc); + Success = Builder.CreateExtractValue(Pair, 1, "success"); NewLoaded = Builder.CreateExtractValue(Pair, 0, "newloaded"); |