Skip to content

Commit e108853

Browse files
authored
clang: Allow targets to set custom metadata on atomics (#96906)
Use this to replace the emission of the amdgpu-unsafe-fp-atomics attribute in favor of per-instruction metadata. In the future new fine grained controls should be introduced that also cover the integer cases. Add a wrapper around CreateAtomicRMW that appends the metadata, and update a few use contexts to use it.
1 parent 70a9535 commit e108853

File tree

9 files changed

+505
-32
lines changed

9 files changed

+505
-32
lines changed

clang/lib/CodeGen/CGAtomic.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
727727

728728
llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1);
729729
llvm::AtomicRMWInst *RMWI =
730-
CGF.Builder.CreateAtomicRMW(Op, Ptr, LoadVal1, Order, Scope);
730+
CGF.emitAtomicRMWInst(Op, Ptr, LoadVal1, Order, Scope);
731731
RMWI->setVolatile(E->isVolatile());
732732

733733
// For __atomic_*_fetch operations, perform the operation again to
@@ -2034,6 +2034,17 @@ std::pair<RValue, llvm::Value *> CodeGenFunction::EmitAtomicCompareExchange(
20342034
IsWeak);
20352035
}
20362036

2037+
llvm::AtomicRMWInst *
2038+
CodeGenFunction::emitAtomicRMWInst(llvm::AtomicRMWInst::BinOp Op, Address Addr,
2039+
llvm::Value *Val, llvm::AtomicOrdering Order,
2040+
llvm::SyncScope::ID SSID) {
2041+
2042+
llvm::AtomicRMWInst *RMW =
2043+
Builder.CreateAtomicRMW(Op, Addr, Val, Order, SSID);
2044+
getTargetHooks().setTargetAtomicMetadata(*this, *RMW);
2045+
return RMW;
2046+
}
2047+
20372048
void CodeGenFunction::EmitAtomicUpdate(
20382049
LValue LVal, llvm::AtomicOrdering AO,
20392050
const llvm::function_ref<RValue(RValue)> &UpdateOp, bool IsVolatile) {

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2841,9 +2841,10 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
28412841
isInc ? llvm::Instruction::FAdd : llvm::Instruction::FSub;
28422842
llvm::Value *amt = llvm::ConstantFP::get(
28432843
VMContext, llvm::APFloat(static_cast<float>(1.0)));
2844-
llvm::Value *old =
2845-
Builder.CreateAtomicRMW(aop, LV.getAddress(), amt,
2846-
llvm::AtomicOrdering::SequentiallyConsistent);
2844+
llvm::AtomicRMWInst *old =
2845+
CGF.emitAtomicRMWInst(aop, LV.getAddress(), amt,
2846+
llvm::AtomicOrdering::SequentiallyConsistent);
2847+
28472848
return isPre ? Builder.CreateBinOp(op, old, amt) : old;
28482849
}
28492850
value = EmitLoadOfLValue(LV, E->getExprLoc());
@@ -3583,9 +3584,9 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
35833584
EmitScalarConversion(OpInfo.RHS, E->getRHS()->getType(), LHSTy,
35843585
E->getExprLoc()),
35853586
LHSTy);
3586-
Value *OldVal = Builder.CreateAtomicRMW(
3587-
AtomicOp, LHSLV.getAddress(), Amt,
3588-
llvm::AtomicOrdering::SequentiallyConsistent);
3587+
3588+
llvm::AtomicRMWInst *OldVal =
3589+
CGF.emitAtomicRMWInst(AtomicOp, LHSLV.getAddress(), Amt);
35893590

35903591
// Since operation is atomic, the result type is guaranteed to be the
35913592
// same as the input in LLVM terms.

clang/lib/CodeGen/CGStmtOpenMP.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6326,8 +6326,8 @@ static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X,
63266326
UpdateVal = CGF.Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
63276327
X.getAddress().getElementType());
63286328
}
6329-
llvm::Value *Res =
6330-
CGF.Builder.CreateAtomicRMW(RMWOp, X.getAddress(), UpdateVal, AO);
6329+
llvm::AtomicRMWInst *Res =
6330+
CGF.emitAtomicRMWInst(RMWOp, X.getAddress(), UpdateVal, AO);
63316331
return std::make_pair(true, RValue::get(Res));
63326332
}
63336333

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4160,6 +4160,13 @@ class CodeGenFunction : public CodeGenTypeCache {
41604160
llvm::AtomicOrdering::SequentiallyConsistent,
41614161
bool IsWeak = false, AggValueSlot Slot = AggValueSlot::ignored());
41624162

4163+
/// Emit an atomicrmw instruction, and applying relevant metadata when
4164+
/// applicable.
4165+
llvm::AtomicRMWInst *emitAtomicRMWInst(
4166+
llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val,
4167+
llvm::AtomicOrdering Order = llvm::AtomicOrdering::SequentiallyConsistent,
4168+
llvm::SyncScope::ID SSID = llvm::SyncScope::System);
4169+
41634170
void EmitAtomicUpdate(LValue LVal, llvm::AtomicOrdering AO,
41644171
const llvm::function_ref<RValue(RValue)> &UpdateOp,
41654172
bool IsVolatile);

clang/lib/CodeGen/TargetInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,10 @@ class TargetCodeGenInfo {
334334
llvm::AtomicOrdering Ordering,
335335
llvm::LLVMContext &Ctx) const;
336336

337+
/// Allow the target to apply other metadata to an atomic instruction
338+
virtual void setTargetAtomicMetadata(CodeGenFunction &CGF,
339+
llvm::AtomicRMWInst &RMW) const {}
340+
337341
/// Interface class for filling custom fields of a block literal for OpenCL.
338342
class TargetOpenCLBlockHelper {
339343
public:

clang/lib/CodeGen/Targets/AMDGPU.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,8 @@ class AMDGPUTargetCodeGenInfo : public TargetCodeGenInfo {
311311
SyncScope Scope,
312312
llvm::AtomicOrdering Ordering,
313313
llvm::LLVMContext &Ctx) const override;
314+
void setTargetAtomicMetadata(CodeGenFunction &CGF,
315+
llvm::AtomicRMWInst &RMW) const override;
314316
llvm::Value *createEnqueuedBlockKernel(CodeGenFunction &CGF,
315317
llvm::Function *BlockInvokeFunc,
316318
llvm::Type *BlockTy) const override;
@@ -546,6 +548,23 @@ AMDGPUTargetCodeGenInfo::getLLVMSyncScopeID(const LangOptions &LangOpts,
546548
return Ctx.getOrInsertSyncScopeID(Name);
547549
}
548550

551+
void AMDGPUTargetCodeGenInfo::setTargetAtomicMetadata(
552+
CodeGenFunction &CGF, llvm::AtomicRMWInst &RMW) const {
553+
if (!CGF.getTarget().allowAMDGPUUnsafeFPAtomics())
554+
return;
555+
556+
// TODO: Introduce new, more controlled options that also work for integers,
557+
// and deprecate allowAMDGPUUnsafeFPAtomics.
558+
llvm::AtomicRMWInst::BinOp RMWOp = RMW.getOperation();
559+
if (llvm::AtomicRMWInst::isFPOperation(RMWOp)) {
560+
llvm::MDNode *Empty = llvm::MDNode::get(CGF.getLLVMContext(), {});
561+
RMW.setMetadata("amdgpu.no.fine.grained.memory", Empty);
562+
563+
if (RMWOp == llvm::AtomicRMWInst::FAdd && RMW.getType()->isFloatTy())
564+
RMW.setMetadata("amdgpu.ignore.denormal.mode", Empty);
565+
}
566+
}
567+
549568
bool AMDGPUTargetCodeGenInfo::shouldEmitStaticExternCAliases() const {
550569
return false;
551570
}

0 commit comments

Comments
 (0)