https://github.com/chsigg updated https://github.com/llvm/llvm-project/pull/217588
>From cdec5191bf16cfeea5436aaca62c3616c491c3b4 Mon Sep 17 00:00:00 2001 From: Christian Sigg <[email protected]> Date: Wed, 19 Aug 2026 14:51:10 +0200 Subject: [PATCH] [mlir][LLVM] Add ignore_denormal_mode UnitAttr to LLVM::AtomicRMWOp --- .../include/mlir/Dialect/LLVMIR/LLVMOpBase.td | 7 +++++ mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td | 27 +++++++++++++++---- .../mlir/Dialect/LLVMIR/ROCDLDialect.td | 3 +-- mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 15 ++++++----- .../ROCDL/ROCDLToLLVMIRTranslation.cpp | 6 ----- mlir/test/Dialect/LLVMIR/invalid.mlir | 8 ++++++ mlir/test/Dialect/LLVMIR/roundtrip.mlir | 4 +++ .../test/Target/LLVMIR/Import/instructions.ll | 4 +++ mlir/test/Target/LLVMIR/llvmir.mlir | 2 ++ mlir/test/Target/LLVMIR/rocdl.mlir | 2 -- 10 files changed, 56 insertions(+), 22 deletions(-) diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td index a787840663171..9b0b8fc2109c0 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td @@ -216,6 +216,13 @@ class LLVM_MemOpPatterns { code setVolatileCode = [{ inst->setVolatile($volatile_); }]; + code setIgnoreDenormalModeCode = [{ + if ($ignore_denormal_mode) { + llvm::MDNode *metadata = llvm::MDNode::get(inst->getContext(), {}); + inst->setMetadata(llvm::LLVMContext::MD_atomic_ignore_denormal_mode, + metadata); + } + }]; code setSyncScopeCode = [{ if ($syncscope.has_value()) { llvm::LLVMContext &llvmContext = builder.getContext(); diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index faeab607d6846..089bcc56838d0 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -2370,12 +2370,14 @@ def LLVM_AtomicRMWOp : LLVM_MemAccessOpBase<"atomicrmw", [ LLVM_AtomicRMWType:$val, AtomicOrdering:$ordering, OptionalAttr<StrAttr>:$syncscope, OptionalAttr<I64Attr>:$alignment, - UnitAttr:$volatile_); + UnitAttr:$volatile_, + UnitAttr:$ignore_denormal_mode); // Append the aliasing related attributes defined in LLVM_MemAccessOpBase. let arguments = !con(args, aliasAttrs); let results = (outs LLVM_AtomicRMWType:$res); let assemblyFormat = [{ - (`volatile` $volatile_^)? $bin_op $ptr `,` $val + (`volatile` $volatile_^)? (`ignore_denormal_mode` $ignore_denormal_mode^)? + $bin_op $ptr `,` $val (`syncscope` `(` $syncscope^ `)`)? $ordering attr-dict `:` qualified(type($ptr)) `,` type($val) }]; @@ -2386,6 +2388,7 @@ def LLVM_AtomicRMWOp : LLVM_MemAccessOpBase<"atomicrmw", [ convertAtomicOrderingToLLVM($ordering)); $res = inst; }] # setVolatileCode + # setIgnoreDenormalModeCode # setSyncScopeCode # setAlignmentCode # setAccessGroupsMetadataCode @@ -2396,16 +2399,30 @@ def LLVM_AtomicRMWOp : LLVM_MemAccessOpBase<"atomicrmw", [ $res = LLVM::AtomicRMWOp::create($_builder, $_location, convertAtomicBinOpFromLLVM(atomicInst->getOperation()), $ptr, $val, convertAtomicOrderingFromLLVM(atomicInst->getOrdering()), - getLLVMSyncScope(atomicInst), alignment, atomicInst->isVolatile()); + getLLVMSyncScope(atomicInst), alignment, atomicInst->isVolatile(), + atomicInst->hasMetadata(llvm::LLVMContext::MD_atomic_ignore_denormal_mode)); }]; - list<int> llvmArgIndices = [-1, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1]; + list<int> llvmArgIndices = [-1, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; let builders = [ OpBuilder<(ins "LLVM::AtomicBinOp":$binOp, "Value":$ptr, "Value":$val, "LLVM::AtomicOrdering":$ordering, CArg<"StringRef", "StringRef()">:$syncscope, - CArg<"unsigned", "0">:$alignment, CArg<"bool", "false">:$isVolatile + CArg<"unsigned", "0">:$alignment, CArg<"bool", "false">:$isVolatile, + CArg<"bool", "false">:$ignoreDenormalMode )> ]; + let extraClassDeclaration = [{ + bool isFloatingPointOperation() { + return getBinOp() == AtomicBinOp::fadd || + getBinOp() == AtomicBinOp::fsub || + getBinOp() == AtomicBinOp::fmin || + getBinOp() == AtomicBinOp::fmax || + getBinOp() == AtomicBinOp::fminimum || + getBinOp() == AtomicBinOp::fmaximum || + getBinOp() == AtomicBinOp::fminimumnum || + getBinOp() == AtomicBinOp::fmaximumnum; + } + }]; let hasVerifier = 1; } diff --git a/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.td b/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.td index 0807cf8cf04a4..f4800ae454226 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.td +++ b/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.td @@ -154,8 +154,7 @@ def ROCDL_Dialect : Dialect { // Correspond to LLVM metadata of the same name "::mlir::UnitAttr":$last_use, "::mlir::UnitAttr":$no_remote_memory, - "::mlir::UnitAttr":$no_fine_grained_memory, - "::mlir::UnitAttr":$ignore_denormal_mode + "::mlir::UnitAttr":$no_fine_grained_memory ); let useDefaultAttributePrinterParser = 1; diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp index 374ad4a9dcb83..6a0247b9998eb 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -3735,22 +3735,19 @@ OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) { return getValue(); } void AtomicRMWOp::build(OpBuilder &builder, OperationState &state, AtomicBinOp binOp, Value ptr, Value val, AtomicOrdering ordering, StringRef syncscope, - unsigned alignment, bool isVolatile) { + unsigned alignment, bool isVolatile, + bool ignoreDenormalMode) { build(builder, state, val.getType(), binOp, ptr, val, ordering, !syncscope.empty() ? builder.getStringAttr(syncscope) : nullptr, alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isVolatile, + ignoreDenormalMode, /*access_groups=*/nullptr, /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr); } LogicalResult AtomicRMWOp::verify() { auto valType = getVal().getType(); - if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub || - getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax || - getBinOp() == AtomicBinOp::fminimum || - getBinOp() == AtomicBinOp::fmaximum || - getBinOp() == AtomicBinOp::fminimumnum || - getBinOp() == AtomicBinOp::fmaximumnum) { + if (isFloatingPointOperation()) { if (isCompatibleVectorType(valType)) { if (isScalableVectorType(valType)) return emitOpError("expected LLVM IR fixed vector type"); @@ -3773,6 +3770,10 @@ LogicalResult AtomicRMWOp::verify() { return emitOpError("expected LLVM IR integer type"); } + if (getIgnoreDenormalMode() && !isFloatingPointOperation()) + return emitOpError( + "expected floating-point operation with 'ignore_denormal_mode'"); + if (static_cast<unsigned>(getOrdering()) < static_cast<unsigned>(AtomicOrdering::monotonic)) return emitOpError() << "expected at least '" diff --git a/mlir/lib/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.cpp index 82d020bd8f864..a629fc92005ae 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.cpp @@ -239,12 +239,6 @@ class ROCDLDialectLLVMIRTranslationInterface i->setMetadata("amdgpu.no.fine.grained.memory", llvm::MDNode::get(llvmContext, {})); } - if (dialect->getIgnoreDenormalModeAttrHelper().getName() == - attribute.getName()) { - for (llvm::Instruction *i : instructions) - i->setMetadata(llvm::LLVMContext::MD_atomic_ignore_denormal_mode, - llvm::MDNode::get(llvmContext, {})); - } return success(); } diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir index b61856b422876..2a776ab4d008c 100644 --- a/mlir/test/Dialect/LLVMIR/invalid.mlir +++ b/mlir/test/Dialect/LLVMIR/invalid.mlir @@ -831,6 +831,14 @@ func.func @atomicrmw_expected_int(%f32_ptr : !llvm.ptr, %f32 : f32) { // ----- +func.func @atomicrmw_expected_float_ignore_denormal_mode(%i32_ptr : !llvm.ptr, %i32 : i32) { + // expected-error@+1 {{expected floating-point operation with 'ignore_denormal_mode'}} + %0 = llvm.atomicrmw ignore_denormal_mode add %i32_ptr, %i32 monotonic : !llvm.ptr, i32 + llvm.return +} + +// ----- + func.func @cmpxchg_mismatched_value_operands(%ptr : !llvm.ptr, %i32 : i32, %i64 : i64) { // expected-error@+1 {{op failed to verify that operand #1 and operand #2 have the same type}} %0 = "llvm.cmpxchg"(%ptr, %i32, %i64) {success_ordering=2,failure_ordering=2} : (!llvm.ptr, i32, i64) -> !llvm.struct<(i32, i1)> diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir index e8490d55f2c05..209dc0040aded 100644 --- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir +++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir @@ -563,6 +563,10 @@ func.func @atomicrmw(%ptr : !llvm.ptr, %f32 : f32, %f16_vec : vector<2xf16>) { %2 = llvm.atomicrmw fmin %ptr, %f16_vec monotonic : !llvm.ptr, vector<2xf16> // CHECK: llvm.atomicrmw fminimumnum %{{.*}}, %{{.*}} monotonic : !llvm.ptr, f32 %3 = llvm.atomicrmw fminimumnum %ptr, %f32 monotonic : !llvm.ptr, f32 + // CHECK: llvm.atomicrmw ignore_denormal_mode fadd %{{.*}}, %{{.*}} monotonic : !llvm.ptr, f32 + %4 = llvm.atomicrmw ignore_denormal_mode fadd %ptr, %f32 monotonic : !llvm.ptr, f32 + // CHECK: llvm.atomicrmw volatile ignore_denormal_mode fsub %{{.*}}, %{{.*}} syncscope("singlethread") monotonic {alignment = 16 : i64} : !llvm.ptr, f32 + %5 = llvm.atomicrmw volatile ignore_denormal_mode fsub %ptr, %f32 syncscope("singlethread") monotonic {alignment = 16 : i64} : !llvm.ptr, f32 llvm.return } diff --git a/mlir/test/Target/LLVMIR/Import/instructions.ll b/mlir/test/Target/LLVMIR/Import/instructions.ll index 6fae74dcf9895..9a13da558faf5 100644 --- a/mlir/test/Target/LLVMIR/Import/instructions.ll +++ b/mlir/test/Target/LLVMIR/Import/instructions.ll @@ -485,9 +485,13 @@ define void @atomic_rmw(ptr %ptr1, i32 %val1, ptr %ptr2, float %val2) { ; CHECK-SAME: syncscope("singlethread") ; CHECK-SAME: {alignment = 8 : i64} %22 = atomicrmw volatile udec_wrap ptr %ptr1, i32 %val1 syncscope("singlethread") acquire, align 8 + ; CHECK: llvm.atomicrmw ignore_denormal_mode fadd %[[PTR2]], %[[VAL2]] acquire + %23 = atomicrmw fadd ptr %ptr2, float %val2 acquire, !atomic.ignore.denormal.mode !0 ret void } +!0 = !{} + ; // ----- ; CHECK-LABEL: @atomic_cmpxchg diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir index f27c0a46780f2..e423724cce018 100644 --- a/mlir/test/Target/LLVMIR/llvmir.mlir +++ b/mlir/test/Target/LLVMIR/llvmir.mlir @@ -1663,6 +1663,8 @@ llvm.func @atomicrmw( // CHECK-SAME: syncscope("singlethread") // CHECK-SAME: align 8 %27 = llvm.atomicrmw volatile udec_wrap %i32_ptr, %i32 syncscope("singlethread") monotonic {alignment = 8 : i64} : !llvm.ptr, i32 + // CHECK: atomicrmw fadd ptr %{{.*}}, float %{{.*}} monotonic, align 4, !atomic.ignore.denormal.mode !{{[0-9]+}} + %28 = llvm.atomicrmw ignore_denormal_mode fadd %f32_ptr, %f32 monotonic : !llvm.ptr, f32 llvm.return } diff --git a/mlir/test/Target/LLVMIR/rocdl.mlir b/mlir/test/Target/LLVMIR/rocdl.mlir index c8d45570241f3..fd7a4fb75de12 100644 --- a/mlir/test/Target/LLVMIR/rocdl.mlir +++ b/mlir/test/Target/LLVMIR/rocdl.mlir @@ -1962,11 +1962,9 @@ llvm.func @rocdl_4_bit_floats( llvm.func @rocdl_atomic_attrs(%ptr: !llvm.ptr<1>, %data: f32) { // CHECK-LABEL: @rocdl_atomic_attrs // CHECK: atomicrmw - // CHECK-SAME: !atomic.ignore.denormal.mode // CHECK-SAME: !amdgpu.no.fine.grained.memory // CHECK-SAME: !amdgpu.no.remote.memory llvm.atomicrmw fadd %ptr, %data monotonic { - rocdl.ignore_denormal_mode, rocdl.no_fine_grained_memory, rocdl.no_remote_memory} : !llvm.ptr<1>, f32 llvm.return _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
