Skip to content

Commit 9cc2981

Browse files
authored
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).
1 parent 19c8475 commit 9cc2981

20 files changed

+1035
-979
lines changed

Diff for: llvm/include/llvm/CodeGen/AtomicExpandUtils.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ class Value;
2020

2121
/// Parameters (see the expansion example below):
2222
/// (the builder, %addr, %loaded, %new_val, ordering,
23-
/// /* OUT */ %success, /* OUT */ %new_loaded)
24-
using CreateCmpXchgInstFun =
25-
function_ref<void(IRBuilderBase &, Value *, Value *, Value *, Align,
26-
AtomicOrdering, SyncScope::ID, Value *&, Value *&)>;
23+
/// /* OUT */ %success, /* OUT */ %new_loaded,
24+
/// %MetadataSrc)
25+
using CreateCmpXchgInstFun = function_ref<void(
26+
IRBuilderBase &, Value *, Value *, Value *, Align, AtomicOrdering,
27+
SyncScope::ID, Value *&, Value *&, Instruction *)>;
2728

2829
/// Expand an atomic RMW instruction into a loop utilizing
2930
/// cmpxchg. You'll want to make sure your target machine likes cmpxchg

Diff for: llvm/lib/CodeGen/AtomicExpandPass.cpp

+51-40
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class AtomicExpandImpl {
9898
IRBuilderBase &Builder, Type *ResultType, Value *Addr, Align AddrAlign,
9999
AtomicOrdering MemOpOrder, SyncScope::ID SSID,
100100
function_ref<Value *(IRBuilderBase &, Value *)> PerformOp,
101-
CreateCmpXchgInstFun CreateCmpXchg);
101+
CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc);
102102
bool tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI);
103103

104104
bool expandAtomicCmpXchg(AtomicCmpXchgInst *CI);
@@ -194,6 +194,39 @@ static unsigned getAtomicOpSize(AtomicCmpXchgInst *CASI) {
194194
return DL.getTypeStoreSize(CASI->getCompareOperand()->getType());
195195
}
196196

197+
/// Copy metadata that's safe to preserve when widening atomics.
198+
static void copyMetadataForAtomic(Instruction &Dest,
199+
const Instruction &Source) {
200+
SmallVector<std::pair<unsigned, MDNode *>, 8> MD;
201+
Source.getAllMetadata(MD);
202+
LLVMContext &Ctx = Dest.getContext();
203+
MDBuilder MDB(Ctx);
204+
205+
for (auto [ID, N] : MD) {
206+
switch (ID) {
207+
case LLVMContext::MD_dbg:
208+
case LLVMContext::MD_tbaa:
209+
case LLVMContext::MD_tbaa_struct:
210+
case LLVMContext::MD_alias_scope:
211+
case LLVMContext::MD_noalias:
212+
case LLVMContext::MD_noalias_addrspace:
213+
case LLVMContext::MD_access_group:
214+
case LLVMContext::MD_mmra:
215+
Dest.setMetadata(ID, N);
216+
break;
217+
default:
218+
if (ID == Ctx.getMDKindID("amdgpu.no.remote.memory"))
219+
Dest.setMetadata(ID, N);
220+
else if (ID == Ctx.getMDKindID("amdgpu.no.fine.grained.memory"))
221+
Dest.setMetadata(ID, N);
222+
223+
// Losing amdgpu.ignore.denormal.mode, but it doesn't matter for current
224+
// uses.
225+
break;
226+
}
227+
}
228+
}
229+
197230
// Determine if a particular atomic operation has a supported size,
198231
// and is of appropriate alignment, to be passed through for target
199232
// lowering. (Versus turning into a __atomic libcall)
@@ -600,7 +633,8 @@ void AtomicExpandImpl::expandAtomicStore(StoreInst *SI) {
600633
static void createCmpXchgInstFun(IRBuilderBase &Builder, Value *Addr,
601634
Value *Loaded, Value *NewVal, Align AddrAlign,
602635
AtomicOrdering MemOpOrder, SyncScope::ID SSID,
603-
Value *&Success, Value *&NewLoaded) {
636+
Value *&Success, Value *&NewLoaded,
637+
Instruction *MetadataSrc) {
604638
Type *OrigTy = NewVal->getType();
605639

606640
// This code can go away when cmpxchg supports FP and vector types.
@@ -612,9 +646,12 @@ static void createCmpXchgInstFun(IRBuilderBase &Builder, Value *Addr,
612646
Loaded = Builder.CreateBitCast(Loaded, IntTy);
613647
}
614648

615-
Value *Pair = Builder.CreateAtomicCmpXchg(
649+
AtomicCmpXchgInst *Pair = Builder.CreateAtomicCmpXchg(
616650
Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
617651
AtomicCmpXchgInst::getStrongestFailureOrdering(MemOpOrder), SSID);
652+
if (MetadataSrc)
653+
copyMetadataForAtomic(*Pair, *MetadataSrc);
654+
618655
Success = Builder.CreateExtractValue(Pair, 1, "success");
619656
NewLoaded = Builder.CreateExtractValue(Pair, 0, "newloaded");
620657

@@ -951,9 +988,9 @@ void AtomicExpandImpl::expandPartwordAtomicRMW(
951988

952989
Value *OldResult;
953990
if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
954-
OldResult = insertRMWCmpXchgLoop(Builder, PMV.WordType, PMV.AlignedAddr,
955-
PMV.AlignedAddrAlignment, MemOpOrder, SSID,
956-
PerformPartwordOp, createCmpXchgInstFun);
991+
OldResult = insertRMWCmpXchgLoop(
992+
Builder, PMV.WordType, PMV.AlignedAddr, PMV.AlignedAddrAlignment,
993+
MemOpOrder, SSID, PerformPartwordOp, createCmpXchgInstFun, AI);
957994
} else {
958995
assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
959996
OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
@@ -966,36 +1003,6 @@ void AtomicExpandImpl::expandPartwordAtomicRMW(
9661003
AI->eraseFromParent();
9671004
}
9681005

969-
/// Copy metadata that's safe to preserve when widening atomics.
970-
static void copyMetadataForAtomic(Instruction &Dest,
971-
const Instruction &Source) {
972-
SmallVector<std::pair<unsigned, MDNode *>, 8> MD;
973-
Source.getAllMetadata(MD);
974-
LLVMContext &Ctx = Dest.getContext();
975-
MDBuilder MDB(Ctx);
976-
977-
for (auto [ID, N] : MD) {
978-
switch (ID) {
979-
case LLVMContext::MD_dbg:
980-
case LLVMContext::MD_tbaa:
981-
case LLVMContext::MD_tbaa_struct:
982-
case LLVMContext::MD_alias_scope:
983-
case LLVMContext::MD_noalias:
984-
case LLVMContext::MD_access_group:
985-
case LLVMContext::MD_mmra:
986-
Dest.setMetadata(ID, N);
987-
break;
988-
default:
989-
if (ID == Ctx.getMDKindID("amdgpu.no.remote.memory"))
990-
Dest.setMetadata(ID, N);
991-
else if (ID == Ctx.getMDKindID("amdgpu.no.fine.grained.memory"))
992-
Dest.setMetadata(ID, N);
993-
994-
break;
995-
}
996-
}
997-
}
998-
9991006
// Widen the bitwise atomicrmw (or/xor/and) to the minimum supported width.
10001007
AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
10011008
ReplacementIRBuilder Builder(AI, *DL);
@@ -1591,7 +1598,7 @@ Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
15911598
IRBuilderBase &Builder, Type *ResultTy, Value *Addr, Align AddrAlign,
15921599
AtomicOrdering MemOpOrder, SyncScope::ID SSID,
15931600
function_ref<Value *(IRBuilderBase &, Value *)> PerformOp,
1594-
CreateCmpXchgInstFun CreateCmpXchg) {
1601+
CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc) {
15951602
LLVMContext &Ctx = Builder.getContext();
15961603
BasicBlock *BB = Builder.GetInsertBlock();
15971604
Function *F = BB->getParent();
@@ -1637,7 +1644,7 @@ Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
16371644
MemOpOrder == AtomicOrdering::Unordered
16381645
? AtomicOrdering::Monotonic
16391646
: MemOpOrder,
1640-
SSID, Success, NewLoaded);
1647+
SSID, Success, NewLoaded, MetadataSrc);
16411648
assert(Success && NewLoaded);
16421649

16431650
Loaded->addIncoming(NewLoaded, LoopBB);
@@ -1686,7 +1693,7 @@ bool llvm::expandAtomicRMWToCmpXchg(AtomicRMWInst *AI,
16861693
return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
16871694
AI->getValOperand());
16881695
},
1689-
CreateCmpXchg);
1696+
CreateCmpXchg, /*MetadataSrc=*/AI);
16901697

16911698
AI->replaceAllUsesWith(Loaded);
16921699
AI->eraseFromParent();
@@ -1838,11 +1845,15 @@ void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *I) {
18381845
expandAtomicRMWToCmpXchg(
18391846
I, [this](IRBuilderBase &Builder, Value *Addr, Value *Loaded,
18401847
Value *NewVal, Align Alignment, AtomicOrdering MemOpOrder,
1841-
SyncScope::ID SSID, Value *&Success, Value *&NewLoaded) {
1848+
SyncScope::ID SSID, Value *&Success, Value *&NewLoaded,
1849+
Instruction *MetadataSrc) {
18421850
// Create the CAS instruction normally...
18431851
AtomicCmpXchgInst *Pair = Builder.CreateAtomicCmpXchg(
18441852
Addr, Loaded, NewVal, Alignment, MemOpOrder,
18451853
AtomicCmpXchgInst::getStrongestFailureOrdering(MemOpOrder), SSID);
1854+
if (MetadataSrc)
1855+
copyMetadataForAtomic(*Pair, *MetadataSrc);
1856+
18461857
Success = Builder.CreateExtractValue(Pair, 1, "success");
18471858
NewLoaded = Builder.CreateExtractValue(Pair, 0, "newloaded");
18481859

0 commit comments

Comments
 (0)