[llvm-branch-commits] [mlir] [mlir][ROCDL] Add `rocdl.xnack` and `rocdl.sramecc` module attributes (PR #222444)

Krzysztof Drewniak via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Sep 10 15:53:29 PDT 2026


https://github.com/krzysz00 updated https://github.com/llvm/llvm-project/pull/222444

>From 6307fed07a17da05e5571c2851d61832da7ec4d7 Mon Sep 17 00:00:00 2001
From: Krzysztof Drewniak <Krzysztof.Drewniak at amd.com>
Date: Tue, 8 Sep 2026 17:17:38 +0000
Subject: [PATCH 1/2] [mlir][ROCDL] Add `rocdl.xnack` and `rocdl.sramecc`
 module attributes

Since 27eeb7370281, the AMDGPU backend takes the xnack
and sramecc target-ID settings from the `amdgpu.xnack` and
`amdgpu.sramecc` module flags instead subtarget features, making the
old usage a hard error.

This commit adds `rocdl.xnack` and `rocdl.sramecc` module attributes
to the discardable attribute list the ROCDL dialect defines in order
to represent these flags and adds translations for them.

Omitting them means to leave these modifiers at
their default "either" state, which isn't the same as setting them to
false.

AI disclosure: Claude wrote this code and I reviewed it and tried to
reword the comments to something better.
---
 .../mlir/Dialect/LLVMIR/ROCDLDialect.td       | 13 +++++++
 mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp   | 10 +++++
 .../ROCDL/ROCDLToLLVMIRTranslation.cpp        | 18 +++++++++
 mlir/test/Dialect/LLVMIR/rocdl.mlir           | 38 +++++++++++++++++++
 .../Target/LLVMIR/rocdl-module-flags.mlir     | 29 ++++++++++++++
 5 files changed, 108 insertions(+)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.td b/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.td
index c92cdd49e8200..a05913bb2c15f 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.td
@@ -125,6 +125,14 @@ def ROCDL_Dialect : Dialect {
     static constexpr ::llvm::StringLiteral getUniformWorkGroupSizeAttrName() {
       return ::llvm::StringLiteral("rocdl.uniform_work_group_size");
     }
+    /// Get the LLVM module flag key `rocdl.xnack` translates to.
+    static constexpr ::llvm::StringLiteral getModuleFlagKeyXnackName() {
+      return ::llvm::StringLiteral("amdgpu.xnack");
+    }
+    /// Get the LLVM module flag key `rocdl.sramecc` translates to.
+    static constexpr ::llvm::StringLiteral getModuleFlagKeySramEccName() {
+      return ::llvm::StringLiteral("amdgpu.sramecc");
+    }
     /// Get the LLVM module flag key for the AMDGPU buffer OOB mode.
     static constexpr ::llvm::StringLiteral
     getModuleFlagKeyBufferOOBModeName() {
@@ -154,6 +162,11 @@ def ROCDL_Dialect : Dialect {
      "::mlir::IntegerAttr":$max_flat_work_group_size,
      "::mlir::IntegerAttr":$waves_per_eu,
      "::mlir::BoolAttr":$unsafe_fp_atomics,
+     // Boolean attributes for explicitly enabling/disabling xnack or sramecc.
+     // Not setting these is a third "default"/"any" state, and not the same as
+     // false.
+     "::mlir::BoolAttr":$xnack,
+     "::mlir::BoolAttr":$sramecc,
      // Correspond to LLVM metadata of the same name
      "::mlir::UnitAttr":$last_use,
      "::mlir::UnitAttr":$no_remote_memory,
diff --git a/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp
index e5d2bed07d05c..b508475626a88 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp
@@ -103,6 +103,16 @@ LogicalResult ROCDLDialect::verifyOperationAttribute(Operation *op,
                              << "' attribute attached to unexpected op";
     }
   }
+  // xnack/sramecc describe the whole code object.
+  if (attr.getName() == xnackAttrName.getName() ||
+      attr.getName() == srameccAttrName.getName()) {
+    if (!LLVM::satisfiesLLVMModule(op))
+      return op->emitError() << "'" << attr.getName().getValue()
+                             << "' is only supported on modules";
+    if (!isa<BoolAttr>(attr.getValue()))
+      return op->emitError()
+             << "'" << attr.getName().getValue() << "' must be a boolean";
+  }
   return success();
 }
 
diff --git a/mlir/lib/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.cpp
index 18eb07a9e17df..00e4164a9f4aa 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.cpp
@@ -149,6 +149,24 @@ class ROCDLDialectLLVMIRTranslationInterface
       else
         llvmFunc->removeFnAttr("uniform-work-group-size");
     }
+
+    bool isXnack =
+        dialect->getXnackAttrHelper().getName() == attribute.getName();
+    bool isSramecc =
+        dialect->getSrameccAttrHelper().getName() == attribute.getName();
+    if (isXnack || isSramecc) {
+      auto value = dyn_cast<BoolAttr>(attribute.getValue());
+      if (!value)
+        return op->emitOpError(Twine(attribute.getName()) +
+                               " must be a boolean");
+      StringRef key = isXnack
+                          ? ROCDL::ROCDLDialect::getModuleFlagKeyXnackName()
+                          : ROCDL::ROCDLDialect::getModuleFlagKeySramEccName();
+      moduleTranslation.getLLVMModule()->addModuleFlag(
+          llvm::Module::Error, key,
+          llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvmContext),
+                                 value.getValue()));
+    }
     if (dialect->getUnsafeFpAtomicsAttrHelper().getName() ==
         attribute.getName()) {
       auto func = dyn_cast<LLVM::LLVMFuncOp>(op);
diff --git a/mlir/test/Dialect/LLVMIR/rocdl.mlir b/mlir/test/Dialect/LLVMIR/rocdl.mlir
index 6a6f99ac7d2e7..58e337ae771df 100644
--- a/mlir/test/Dialect/LLVMIR/rocdl.mlir
+++ b/mlir/test/Dialect/LLVMIR/rocdl.mlir
@@ -1856,6 +1856,44 @@ module {
 
 // -----
 
+// CHECK-LABEL: module @module_target_id_settings
+// CHECK-SAME: attributes {rocdl.sramecc = false, rocdl.xnack = true}
+module @module_target_id_settings attributes {
+    rocdl.xnack = true, rocdl.sramecc = false} {
+}
+
+// -----
+
+// CHECK-LABEL: gpu.module @gpu_module_target_id_settings
+// CHECK-SAME: attributes {rocdl.sramecc = true, rocdl.xnack = false}
+gpu.module @gpu_module_target_id_settings attributes {
+    rocdl.xnack = false, rocdl.sramecc = true} {
+}
+
+// -----
+
+// expected-error at below {{'rocdl.xnack' is only supported on modules}}
+llvm.func private @xnack_on_func() attributes {rocdl.xnack = true}
+
+// -----
+
+// expected-error at below {{'rocdl.sramecc' is only supported on modules}}
+llvm.func private @sramecc_on_func() attributes {rocdl.sramecc = true}
+
+// -----
+
+// expected-error at below {{'rocdl.xnack' must be a boolean}}
+module attributes {rocdl.xnack = "on"} {
+}
+
+// -----
+
+// expected-error at below {{'rocdl.sramecc' must be a boolean}}
+module attributes {rocdl.sramecc = 1 : i32} {
+}
+
+// -----
+
 // Just check these don't emit errors.
 gpu.module @module_1 [#rocdl.target<O = 1, chip = "gfx900", abi = "500", link = ["my_device_lib.bc"], flags = {fast, daz, unsafe_math}>] {
 }
diff --git a/mlir/test/Target/LLVMIR/rocdl-module-flags.mlir b/mlir/test/Target/LLVMIR/rocdl-module-flags.mlir
index 8e1db326e7f28..2f67770190b13 100644
--- a/mlir/test/Target/LLVMIR/rocdl-module-flags.mlir
+++ b/mlir/test/Target/LLVMIR/rocdl-module-flags.mlir
@@ -45,3 +45,32 @@ module {
 // CHECK-LABEL: define void @generic_oob_relaxed()
 // CHECK: !llvm.module.flags = !{![[GENERIC_BUFFER_RELAXED:[0-9]+]]
 // CHECK-DAG: ![[GENERIC_BUFFER_RELAXED]] = !{i32 7, !"amdgpu.buffer.oob.mode", i32 1}
+
+// -----
+
+module attributes {rocdl.xnack = true, rocdl.sramecc = false} {
+  llvm.func @xnack_on_sramecc_off() {
+    llvm.return
+  }
+}
+
+// CHECK-LABEL: define void @xnack_on_sramecc_off()
+// CHECK: !llvm.module.flags = !{![[SRAMECC_OFF:[0-9]+]], ![[XNACK_ON:[0-9]+]]
+// CHECK-DAG: ![[SRAMECC_OFF]] = !{i32 1, !"amdgpu.sramecc", i32 0}
+// CHECK-DAG: ![[XNACK_ON]] = !{i32 1, !"amdgpu.xnack", i32 1}
+
+// -----
+
+// An unmentioned setting stays unmentioned: the backend reads that as "either",
+// which is not the same as the feature being disabled.
+
+module attributes {rocdl.xnack = false} {
+  llvm.func @xnack_off_sramecc_any() {
+    llvm.return
+  }
+}
+
+// CHECK-LABEL: define void @xnack_off_sramecc_any()
+// CHECK: !llvm.module.flags = !{![[XNACK_OFF:[0-9]+]]
+// CHECK-DAG: ![[XNACK_OFF]] = !{i32 1, !"amdgpu.xnack", i32 0}
+// CHECK-NOT: amdgpu.sramecc

>From 80d13251e3e5781b3a35daee70136a6e3d1d5a3e Mon Sep 17 00:00:00 2001
From: Krzysztof Drewniak <Krzysztof.Drewniak at amd.com>
Date: Thu, 10 Sep 2026 19:51:50 +0000
Subject: [PATCH 2/2] Fix names up a bit

---
 mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp | 7 +++----
 mlir/test/Dialect/LLVMIR/rocdl.mlir         | 8 ++++----
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp
index b508475626a88..c0b30863134ef 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp
@@ -107,11 +107,10 @@ LogicalResult ROCDLDialect::verifyOperationAttribute(Operation *op,
   if (attr.getName() == xnackAttrName.getName() ||
       attr.getName() == srameccAttrName.getName()) {
     if (!LLVM::satisfiesLLVMModule(op))
-      return op->emitError() << "'" << attr.getName().getValue()
-                             << "' is only supported on modules";
-    if (!isa<BoolAttr>(attr.getValue()))
       return op->emitError()
-             << "'" << attr.getName().getValue() << "' must be a boolean";
+             << attr.getName() << " is only supported on modules";
+    if (!isa<BoolAttr>(attr.getValue()))
+      return op->emitError() << attr.getName() << " must be a boolean";
   }
   return success();
 }
diff --git a/mlir/test/Dialect/LLVMIR/rocdl.mlir b/mlir/test/Dialect/LLVMIR/rocdl.mlir
index 58e337ae771df..1b5b641936881 100644
--- a/mlir/test/Dialect/LLVMIR/rocdl.mlir
+++ b/mlir/test/Dialect/LLVMIR/rocdl.mlir
@@ -1872,23 +1872,23 @@ gpu.module @gpu_module_target_id_settings attributes {
 
 // -----
 
-// expected-error at below {{'rocdl.xnack' is only supported on modules}}
+// expected-error at below {{"rocdl.xnack" is only supported on modules}}
 llvm.func private @xnack_on_func() attributes {rocdl.xnack = true}
 
 // -----
 
-// expected-error at below {{'rocdl.sramecc' is only supported on modules}}
+// expected-error at below {{"rocdl.sramecc" is only supported on modules}}
 llvm.func private @sramecc_on_func() attributes {rocdl.sramecc = true}
 
 // -----
 
-// expected-error at below {{'rocdl.xnack' must be a boolean}}
+// expected-error at below {{"rocdl.xnack" must be a boolean}}
 module attributes {rocdl.xnack = "on"} {
 }
 
 // -----
 
-// expected-error at below {{'rocdl.sramecc' must be a boolean}}
+// expected-error at below {{"rocdl.sramecc" must be a boolean}}
 module attributes {rocdl.sramecc = 1 : i32} {
 }
 



More information about the llvm-branch-commits mailing list