https://github.com/krzysz00 updated https://github.com/llvm/llvm-project/pull/222444
>From b9e4eca49fc073e69bd81f06e1bcedf3d35e1847 Mon Sep 17 00:00:00 2001 From: Krzysztof Drewniak <[email protected]> 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@below {{'rocdl.xnack' is only supported on modules}} +llvm.func private @xnack_on_func() attributes {rocdl.xnack = true} + +// ----- + +// expected-error@below {{'rocdl.sramecc' is only supported on modules}} +llvm.func private @sramecc_on_func() attributes {rocdl.sramecc = true} + +// ----- + +// expected-error@below {{'rocdl.xnack' must be a boolean}} +module attributes {rocdl.xnack = "on"} { +} + +// ----- + +// expected-error@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 0674ec93996393cb193961ace088661a280dca0d Mon Sep 17 00:00:00 2001 From: Krzysztof Drewniak <[email protected]> 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@below {{'rocdl.xnack' is only supported on modules}} +// expected-error@below {{"rocdl.xnack" is only supported on modules}} llvm.func private @xnack_on_func() attributes {rocdl.xnack = true} // ----- -// expected-error@below {{'rocdl.sramecc' is only supported on modules}} +// expected-error@below {{"rocdl.sramecc" is only supported on modules}} llvm.func private @sramecc_on_func() attributes {rocdl.sramecc = true} // ----- -// expected-error@below {{'rocdl.xnack' must be a boolean}} +// expected-error@below {{"rocdl.xnack" must be a boolean}} module attributes {rocdl.xnack = "on"} { } // ----- -// expected-error@below {{'rocdl.sramecc' must be a boolean}} +// expected-error@below {{"rocdl.sramecc" must be a boolean}} module attributes {rocdl.sramecc = 1 : i32} { } _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
