https://github.com/chsigg created https://github.com/llvm/llvm-project/pull/217588
None >From c9c604a9e5a7bf4e2e2e021b73a6519b878194d8 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/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 15 ++++++----- 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 ++ 7 files changed, 55 insertions(+), 12 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 86b9e6f58ea31..888083a4ef882 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -2369,12 +2369,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) }]; @@ -2385,6 +2387,7 @@ def LLVM_AtomicRMWOp : LLVM_MemAccessOpBase<"atomicrmw", [ convertAtomicOrderingToLLVM($ordering)); $res = inst; }] # setVolatileCode + # setIgnoreDenormalModeCode # setSyncScopeCode # setAlignmentCode # setAccessGroupsMetadataCode @@ -2395,16 +2398,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/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/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir index 9fc3f769d1020..f2287fb1e0cd9 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 f4805c5541f91..e44da44b9e599 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 } _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
