[llvm-branch-commits] [mlir] [mlir][LLVM] Add ignore_denormal_mode UnitAttr to LLVM::AtomicRMWOp (PR #217588)
Christian Sigg via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Aug 24 03:18:55 PDT 2026
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 <csigg at google.com>
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 at +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 at +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
More information about the llvm-branch-commits
mailing list