[Mlir-commits] [mlir] 2d1fb73 - [mlir][LLVM][ROCDL] Add buffer oob mode module flags, flag interfaces (#202729)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Fri Jun 12 09:19:44 PDT 2026
Author: Krzysztof Drewniak
Date: 2026-06-12T09:19:39-07:00
New Revision: 2d1fb738d6f9eb109a2f1e0405397565f25fece4
URL: https://github.com/llvm/llvm-project/commit/2d1fb738d6f9eb109a2f1e0405397565f25fece4
DIFF: https://github.com/llvm/llvm-project/commit/2d1fb738d6f9eb109a2f1e0405397565f25fece4.diff
LOG: [mlir][LLVM][ROCDL] Add buffer oob mode module flags, flag interfaces (#202729)
Now that the out-of-bounds mode for buffer accesses will be controlled
by a module flag and is no longer a function of the subtarget triple (as
of #160922) and since `ptr addrpace(7)` lowering will start respecting
this mode soon, add MLIR-level support for setting this flag.
After a few iterations, I think adding this module flag to
`llvm.module.flags` but adding interfaces for module flag attributes (so
that those wishing to set this flag don't need to know it has `max`
combining semantics or look up the enum values) is a
minimally-disruptive way to get a more ergonomic wrapper around this
functionality.
AI note: AI generated the code hehe, I reviewed it. The documentation
update to ModuleFlagsOp is mine.
(The LLVM PR that would want people to start explicitly setting
`relaxed` is #134329)
Co-authored-by: Codex <codex at openai.com>
Added:
mlir/test/Target/LLVMIR/rocdl-module-flags.mlir
Modified:
mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
mlir/include/mlir/Dialect/LLVMIR/ROCDLAttrs.td
mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.td
mlir/include/mlir/Dialect/LLVMIR/ROCDLEnums.td
mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp
mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
mlir/test/Dialect/GPU/module-to-binary-rocdl.mlir
mlir/test/Dialect/LLVMIR/invalid.mlir
mlir/test/Dialect/LLVMIR/module-roundtrip.mlir
mlir/test/Dialect/LLVMIR/rocdl.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 56f3afba6a030..9474afb897119 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1585,14 +1585,16 @@ def LLVM_DereferenceableAttr : LLVM_Attr<"Dereferenceable", "dereferenceable"> {
//===----------------------------------------------------------------------===//
def ModuleFlagAttr
- : LLVM_Attr<"ModuleFlag", "mlir.module_flag"> {
+ : LLVM_Attr<"ModuleFlag", "mlir.module_flag",
+ [DeclareAttrInterfaceMethods<LLVM_ModuleFlagAttrInterface>]> {
let summary = "LLVM module flag metadata";
let description = [{
Represents a single entry of llvm.module.flags metadata
(llvm::Module::ModuleFlagEntry in LLVM). The first element is a behavior
flag described by `ModFlagBehaviorAttr`, the second is a string ID
and third is the value of the flag. Supported keys and values include:
- - Arbitrary `key`s holding integer constants or strings.
+ - Arbitrary `key`s holding integer constants, integer-like dialect
+ attributes, strings, or non-empty string arrays.
- Domain specific keys (e.g "CG Profile"), holding lists of supported
module flag values (e.g. `llvm.cgprofile_entry`).
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
index e10d7f7df3450..19dced51e976f 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
@@ -100,6 +100,11 @@ bool isValidLoadStoreImpl(Type type, ptr::AtomicOrdering ordering,
std::optional<int64_t> alignment,
const ::mlir::DataLayout *dataLayout,
function_ref<InFlightDiagnostic()> emitError);
+
+/// Verifies that a module flag value can be exported to LLVM IR.
+LogicalResult
+verifyModuleFlagValue(StringAttr key, Attribute value,
+ function_ref<InFlightDiagnostic()> emitError);
} // namespace detail
} // namespace LLVM
} // namespace mlir
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
index 8c6d4fcefa903..c59b38c416956 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
@@ -582,6 +582,42 @@ def LLVM_IntrinsicIntegerAttrInterface :
];
}
+def LLVM_ModuleFlagAttrInterface :
+ AttrInterface<"ModuleFlagAttrInterface"> {
+ let description = [{
+ An interface for attributes that represent LLVM module flag metadata entries.
+
+ Implementing attributes provide the module flag merge behavior, metadata key,
+ and metadata value. This lets target dialects define richer, target-specific
+ module flag attributes while still sharing `llvm.module_flags` as the common
+ operation container. Values returned by this interface must use a shape that
+ can be exported to LLVM IR: integer attributes (exported as i32 constants),
+ string attributes, attributes implementing `IntrinsicIntegerAttrInterface`,
+ supported array values, or `ModuleFlagProfileSummaryAttr`.
+ }];
+ let cppNamespace = "::mlir::LLVM";
+ let methods = [
+ InterfaceMethod<
+ /*description=*/"Returns the module flag merge behavior.",
+ /*retTy=*/"::mlir::LLVM::ModFlagBehavior",
+ /*methodName=*/"getModuleFlagBehavior",
+ /*args=*/(ins)
+ >,
+ InterfaceMethod<
+ /*description=*/"Returns the module flag metadata key.",
+ /*retTy=*/"::mlir::StringAttr",
+ /*methodName=*/"getModuleFlagKey",
+ /*args=*/(ins)
+ >,
+ InterfaceMethod<
+ /*description=*/"Returns the module flag metadata value.",
+ /*retTy=*/"::mlir::Attribute",
+ /*methodName=*/"getModuleFlagValue",
+ /*args=*/(ins)
+ >
+ ];
+}
+
def LLVM_TargetAttrInterface
: AttrInterface<"TargetAttrInterface", [DLTIQueryInterface]> {
let description = [{
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 85b768f2f6755..9d112e5ea227e 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -2643,8 +2643,10 @@ def LLVM_ModuleFlagsOp
let summary = "Information about module properties";
let description = [{
Represents the equivalent in MLIR for LLVM's `llvm.module.flags` metadata,
- which requires a list of metadata triplets. Each triplet entry is described
- by a `ModuleFlagAttr`.
+ which requires a list of metadata triplets (combining kind, name, value),
+ either specified directly by a `ModuleFlagAttr` or defined by an attribute
+ implementing `ModuleFlagAttrInterface` (which is used to wrap the details
+ of metadata combining, provided other verifications, etc.)
Example:
```mlir
diff --git a/mlir/include/mlir/Dialect/LLVMIR/ROCDLAttrs.td b/mlir/include/mlir/Dialect/LLVMIR/ROCDLAttrs.td
index c3a66e2e92256..4f84513d23576 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/ROCDLAttrs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/ROCDLAttrs.td
@@ -11,6 +11,7 @@
include "mlir/Dialect/LLVMIR/ROCDLDialect.td"
include "mlir/Dialect/LLVMIR/ROCDLEnums.td"
+include "mlir/Dialect/LLVMIR/LLVMInterfaces.td"
include "mlir/IR/EnumAttr.td"
//===----------------------------------------------------------------------===//
@@ -26,6 +27,39 @@ class ROCDL_IntrinsicIntegerEnumAttr<EnumInfo enumInfo, string name>
: EnumAttr<ROCDL_Dialect, enumInfo, name,
[LLVM_IntrinsicIntegerAttrInterface]>;
+def ROCDL_BufferOOBModeAttr :
+ ROCDL_IntrinsicIntegerEnumAttr<ROCDL_BufferOOBMode, "buffer_oob_mode"> {
+ let summary = "ROCDL buffer out-of-bounds mode";
+ let description = [{
+ Specifies the AMDGPU buffer out-of-bounds mode encoded in
+ `amdgpu.buffer.oob.mode` or `amdgpu.tbuffer.oob.mode` LLVM module flags.
+ }];
+ let assemblyFormat = "`<` $value `>`";
+}
+
+class ROCDL_BufferOOBModeModuleFlagAttrBase<string attrName, string mnemonic>
+ : ROCDL_Attr<attrName, mnemonic,
+ [DeclareAttrInterfaceMethods<LLVM_ModuleFlagAttrInterface>]> {
+ let summary = "ROCDL buffer/tbuffer out-of-bounds mode LLVM module flag";
+ let description = [{
+ Specifies an AMDGPU buffer or tbuffer out-of-bounds mode LLVM module flag.
+ The attribute supplies the required `max` merge behavior and AMDGPU module
+ flag key. Prefer these typed attributes over hand-written generic
+ `#llvm.mlir.module_flag` triples for AMDGPU OOB mode keys when MLIR-side
+ behavior and enum validation are required.
+ }];
+ let parameters = (ins EnumParameter<ROCDL_BufferOOBMode>:$value);
+ let assemblyFormat = "`<` $value `>`";
+}
+
+def ROCDL_BufferOOBModeModuleFlagAttr :
+ ROCDL_BufferOOBModeModuleFlagAttrBase<"BufferOOBModeModuleFlag",
+ "buffer_oob_mode_flag">;
+
+def ROCDL_TBufferOOBModeModuleFlagAttr :
+ ROCDL_BufferOOBModeModuleFlagAttrBase<"TBufferOOBModeModuleFlag",
+ "tbuffer_oob_mode_flag">;
+
def ROCDL_MFMAPermBAttr
: ROCDL_IntrinsicIntegerEnumAttr<ROCDL_MFMAPermB, "mfma_perm_b">;
diff --git a/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.td b/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.td
index 6b3f073a4a994..0807cf8cf04a4 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.td
@@ -124,7 +124,16 @@ def ROCDL_Dialect : Dialect {
static constexpr ::llvm::StringLiteral getUniformWorkGroupSizeAttrName() {
return ::llvm::StringLiteral("rocdl.uniform_work_group_size");
}
-
+ /// Get the LLVM module flag key for the AMDGPU buffer OOB mode.
+ static constexpr ::llvm::StringLiteral
+ getModuleFlagKeyBufferOOBModeName() {
+ return ::llvm::StringLiteral("amdgpu.buffer.oob.mode");
+ }
+ /// Get the LLVM module flag key for the AMDGPU tbuffer OOB mode.
+ static constexpr ::llvm::StringLiteral
+ getModuleFlagKeyTBufferOOBModeName() {
+ return ::llvm::StringLiteral("amdgpu.tbuffer.oob.mode");
+ }
/// The address space value that represents global memory.
static constexpr unsigned kGlobalMemoryAddressSpace = 1;
/// The address space value that represents shared memory.
diff --git a/mlir/include/mlir/Dialect/LLVMIR/ROCDLEnums.td b/mlir/include/mlir/Dialect/LLVMIR/ROCDLEnums.td
index e0d1773b59b7b..fb704ecf4c0de 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/ROCDLEnums.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/ROCDLEnums.td
@@ -32,6 +32,21 @@ class ROCDL_I32BitEnum<string name, string summary,
let cppNamespace = "::mlir::ROCDL";
}
+//===----------------------------------------------------------------------===//
+// Buffer out-of-bounds mode enum.
+//===----------------------------------------------------------------------===//
+
+// Keep these values in sync with OOBFlagValue in AMDGPUTargetMachine.cpp and
+// the LLVM IR verifier's AMDGPU module flag checks.
+def ROCDL_BufferOOBModeAny : I32EnumCase<"Any", 0, "any">;
+def ROCDL_BufferOOBModeRelaxed : I32EnumCase<"Relaxed", 1, "relaxed">;
+def ROCDL_BufferOOBModeStrict : I32EnumCase<"Strict", 2, "strict">;
+
+def ROCDL_BufferOOBMode :
+ ROCDL_I32Enum<"BufferOOBMode", "ROCDL buffer out-of-bounds mode",
+ [ROCDL_BufferOOBModeAny, ROCDL_BufferOOBModeRelaxed,
+ ROCDL_BufferOOBModeStrict]>;
+
def ROCDL_MFMAPermB : ROCDL_I32Enum<"MFMAPermB",
"permutations of the lanes storing B in an MFMA",
[
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 2bd5b42720ee2..266faeca4553b 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -544,10 +544,9 @@ FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
// ModuleFlagAttr
//===----------------------------------------------------------------------===//
-LogicalResult
-ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
- LLVM::ModFlagBehavior flagBehavior, StringAttr key,
- Attribute value) {
+LogicalResult LLVM::detail::verifyModuleFlagValue(
+ StringAttr key, Attribute value,
+ function_ref<InFlightDiagnostic()> emitError) {
if (key == LLVMDialect::getModuleFlagKeyCGProfileName()) {
auto arrayAttr = dyn_cast<ArrayAttr>(value);
if ((!arrayAttr) || (!llvm::all_of(arrayAttr, [](Attribute attr) {
@@ -565,7 +564,7 @@ ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
return success();
}
- if (isa<IntegerAttr, StringAttr>(value))
+ if (isa<IntegerAttr, StringAttr, IntrinsicIntegerAttrInterface>(value))
return success();
// Allow non-empty ArrayAttr of StringAttrs to represent MDTuples of
@@ -578,7 +577,24 @@ ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
llvm::all_of(arrayAttr, [](Attribute a) { return isa<StringAttr>(a); }))
return success();
- return emitError() << "only integer, string, and string-array values are "
- "currently supported for unknown key '"
- << key << "'";
+ return emitError()
+ << "only integer, integer-like dialect attributes, string, "
+ "and string-array values are currently supported for "
+ "unknown key '"
+ << key << "'";
}
+
+LogicalResult
+ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
+ LLVM::ModFlagBehavior flagBehavior, StringAttr key,
+ Attribute value) {
+ return LLVM::detail::verifyModuleFlagValue(key, value, emitError);
+}
+
+ModFlagBehavior ModuleFlagAttr::getModuleFlagBehavior() const {
+ return getBehavior();
+}
+
+StringAttr ModuleFlagAttr::getModuleFlagKey() const { return getKey(); }
+
+Attribute ModuleFlagAttr::getModuleFlagValue() const { return getValue(); }
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index ac6cf03e057dc..3111d5bed3a64 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -25,6 +25,7 @@
#include "mlir/Transforms/InliningUtils.h"
#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Support/Error.h"
@@ -4171,9 +4172,23 @@ LogicalResult ModuleFlagsOp::verify() {
if (Operation *parentOp = (*this)->getParentOp();
parentOp && !satisfiesLLVMModule(parentOp))
return emitOpError("must appear at the module level");
- for (Attribute flag : getFlags())
- if (!isa<ModuleFlagAttr>(flag))
+
+ llvm::DenseSet<StringAttr> seenNonRequireKeys;
+ for (Attribute flag : getFlags()) {
+ auto moduleFlag = dyn_cast<ModuleFlagAttrInterface>(flag);
+ if (!moduleFlag)
return emitOpError("expected a module flag attribute");
+ if (failed(LLVM::detail::verifyModuleFlagValue(
+ moduleFlag.getModuleFlagKey(), moduleFlag.getModuleFlagValue(),
+ [&] { return emitOpError(); })))
+ return failure();
+ if (moduleFlag.getModuleFlagBehavior() == ModFlagBehavior::Require)
+ continue;
+ StringAttr key = moduleFlag.getModuleFlagKey();
+ if (!seenNonRequireKeys.insert(key).second)
+ return emitOpError("expected module flag key '")
+ << key.getValue() << "' to be unique for non-require flags";
+ }
return success();
}
diff --git a/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp
index 6e69a07856300..686b62f1dd80e 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp
@@ -25,6 +25,7 @@
#include "mlir/IR/Operation.h"
#include "mlir/Transforms/InliningUtils.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -66,6 +67,34 @@ void ROCDLDialect::initialize() {
declarePromisedInterface<gpu::TargetAttrInterface, ROCDLTargetAttr>();
}
+LLVM::ModFlagBehavior
+BufferOOBModeModuleFlagAttr::getModuleFlagBehavior() const {
+ return LLVM::ModFlagBehavior::Max;
+}
+
+StringAttr BufferOOBModeModuleFlagAttr::getModuleFlagKey() const {
+ return StringAttr::get(getContext(),
+ ROCDLDialect::getModuleFlagKeyBufferOOBModeName());
+}
+
+Attribute BufferOOBModeModuleFlagAttr::getModuleFlagValue() const {
+ return BufferOOBModeAttr::get(getContext(), getValue());
+}
+
+LLVM::ModFlagBehavior
+TBufferOOBModeModuleFlagAttr::getModuleFlagBehavior() const {
+ return LLVM::ModFlagBehavior::Max;
+}
+
+StringAttr TBufferOOBModeModuleFlagAttr::getModuleFlagKey() const {
+ return StringAttr::get(getContext(),
+ ROCDLDialect::getModuleFlagKeyTBufferOOBModeName());
+}
+
+Attribute TBufferOOBModeModuleFlagAttr::getModuleFlagValue() const {
+ return BufferOOBModeAttr::get(getContext(), getValue());
+}
+
LogicalResult ROCDLDialect::verifyOperationAttribute(Operation *op,
NamedAttribute attr) {
// Kernel function attribute should be attached to functions.
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 5474689c9b0b5..7cd8c3c77c15f 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -382,34 +382,40 @@ static llvm::Metadata *convertModuleFlagProfileSummaryAttr(
static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
LLVM::ModuleTranslation &moduleTranslation) {
llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
- for (auto flagAttr : flags.getAsRange<ModuleFlagAttr>()) {
+ auto convertIntegerAttr = [&](IntegerAttr intAttr) -> llvm::Metadata * {
+ return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+ llvm::Type::getInt32Ty(builder.getContext()), intAttr.getInt()));
+ };
+ for (auto flagAttr : flags.getAsRange<ModuleFlagAttrInterface>()) {
llvm::Metadata *valueMetadata =
- llvm::TypeSwitch<Attribute, llvm::Metadata *>(flagAttr.getValue())
+ llvm::TypeSwitch<Attribute, llvm::Metadata *>(
+ flagAttr.getModuleFlagValue())
.Case([&](StringAttr strAttr) {
return llvm::MDString::get(builder.getContext(),
strAttr.getValue());
})
.Case([&](IntegerAttr intAttr) {
- return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(builder.getContext()),
- intAttr.getInt()));
+ return convertIntegerAttr(intAttr);
+ })
+ .Case([&](IntrinsicIntegerAttrInterface intAttr) {
+ return convertIntegerAttr(intAttr.getIntegerAttr());
})
.Case([&](ArrayAttr arrayAttr) {
- return convertModuleFlagValue(flagAttr.getKey().getValue(),
- arrayAttr, builder,
- moduleTranslation);
+ return convertModuleFlagValue(
+ flagAttr.getModuleFlagKey().getValue(), arrayAttr, builder,
+ moduleTranslation);
})
.Case([&](ModuleFlagProfileSummaryAttr summaryAttr) {
return convertModuleFlagProfileSummaryAttr(
- flagAttr.getKey().getValue(), summaryAttr, builder,
+ flagAttr.getModuleFlagKey().getValue(), summaryAttr, builder,
moduleTranslation);
})
.Default([](auto) { return nullptr; });
assert(valueMetadata && "expected valid metadata");
llvmModule->addModuleFlag(
- convertModFlagBehaviorToLLVM(flagAttr.getBehavior()),
- flagAttr.getKey().getValue(), valueMetadata);
+ convertModFlagBehaviorToLLVM(flagAttr.getModuleFlagBehavior()),
+ flagAttr.getModuleFlagKey().getValue(), valueMetadata);
}
}
diff --git a/mlir/test/Dialect/GPU/module-to-binary-rocdl.mlir b/mlir/test/Dialect/GPU/module-to-binary-rocdl.mlir
index 939dbdd4382e7..7c3223d4b9970 100644
--- a/mlir/test/Dialect/GPU/module-to-binary-rocdl.mlir
+++ b/mlir/test/Dialect/GPU/module-to-binary-rocdl.mlir
@@ -4,8 +4,11 @@
module attributes {gpu.container_module} {
// CHECK-LABEL:gpu.binary @kernel_module1
- // CHECK:[#gpu.object<#rocdl.target<chip = "gfx90a">, offload = "{{.*}}">]
+ // CHECK:[#gpu.object<#rocdl.target<chip = "gfx90a">, offload = "{{.*}}amdgpu.buffer.oob.mode{{.*}}">]
gpu.module @kernel_module1 [#rocdl.target<chip = "gfx90a">] {
+ llvm.module_flags [
+ #rocdl.buffer_oob_mode_flag<relaxed>
+ ]
llvm.func @kernel(%arg0: i32, %arg1: !llvm.ptr,
%arg2: !llvm.ptr, %arg3: i64, %arg4: i64,
%arg5: i64) attributes {gpu.kernel} {
diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir
index e80094df1eed2..a0377cdfc14ff 100644
--- a/mlir/test/Dialect/LLVMIR/invalid.mlir
+++ b/mlir/test/Dialect/LLVMIR/invalid.mlir
@@ -1850,12 +1850,21 @@ llvm.mlir.alias external @y5 : i32 {
module {
llvm.func @foo()
- // expected-error at below {{only integer, string, and string-array values are currently supported for unknown key '"yolo"'}}
+ // expected-error at below {{only integer, integer-like dialect attributes, string, and string-array values are currently supported for unknown key '"yolo"'}}
llvm.module_flags [#llvm.mlir.module_flag<error, "yolo", @foo>]
}
// -----
+module {
+ // expected-error at below {{expected module flag key 'amdgpu.buffer.oob.mode' to be unique for non-require flags}}
+ llvm.module_flags [#rocdl.buffer_oob_mode_flag<any>,
+ #llvm.mlir.module_flag<max, "amdgpu.buffer.oob.mode",
+ #rocdl.buffer_oob_mode<strict>>]
+}
+
+// -----
+
module {
// expected-error at below {{'CG Profile' key expects an array of '#llvm.cgprofile_entry'}}
llvm.module_flags [#llvm.mlir.module_flag<append, "CG Profile", [
diff --git a/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir b/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir
index 85abd57df53c8..aa1f99a76ce5d 100644
--- a/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir
@@ -46,3 +46,14 @@ module {
// CHECK-SAME: <cut_off = 10000, min_count = 86427, num_counts = 1>,
// CHECK-SAME: <cut_off = 100000, min_count = 86427, num_counts = 1>
// CHECK-SAME: >>]
+
+// -----
+
+module {
+ llvm.module_flags [#llvm.mlir.module_flag<require, "shared-require", 0 : i32>,
+ #llvm.mlir.module_flag<require, "shared-require", 1 : i32>]
+}
+
+// CHECK: llvm.module_flags [
+// CHECK-SAME: #llvm.mlir.module_flag<require, "shared-require", 0 : i32>,
+// CHECK-SAME: #llvm.mlir.module_flag<require, "shared-require", 1 : i32>]
diff --git a/mlir/test/Dialect/LLVMIR/rocdl.mlir b/mlir/test/Dialect/LLVMIR/rocdl.mlir
index 603913750a32c..dd0b00faf7f1f 100644
--- a/mlir/test/Dialect/LLVMIR/rocdl.mlir
+++ b/mlir/test/Dialect/LLVMIR/rocdl.mlir
@@ -1,5 +1,30 @@
// RUN: mlir-opt %s -split-input-file -verify-diagnostics | FileCheck %s
+// CHECK-LABEL: module {
+// CHECK: llvm.module_flags [
+// CHECK-SAME: #rocdl.buffer_oob_mode_flag<any>,
+// CHECK-SAME: #rocdl.tbuffer_oob_mode_flag<strict>
+module {
+ llvm.module_flags [
+ #rocdl.buffer_oob_mode_flag<any>,
+ #rocdl.tbuffer_oob_mode_flag<strict>
+ ]
+}
+
+// -----
+
+// CHECK-LABEL: module {
+// CHECK: llvm.module_flags [
+// CHECK-SAME: #llvm.mlir.module_flag<max, "amdgpu.buffer.oob.mode", #rocdl.buffer_oob_mode<relaxed>>
+module {
+ llvm.module_flags [
+ #llvm.mlir.module_flag<max, "amdgpu.buffer.oob.mode",
+ #rocdl.buffer_oob_mode<relaxed>>
+ ]
+}
+
+// -----
+
func.func @rocdl_special_regs() -> i32 {
// CHECK-LABEL: rocdl_special_regs
// CHECK: rocdl.workitem.id.x : i32
@@ -1803,6 +1828,23 @@ func.func private @expected_llvm_func() attributes { rocdl.kernel }
// -----
+gpu.module @module_oob_modes {
+ llvm.module_flags [
+ #rocdl.buffer_oob_mode_flag<relaxed>,
+ #rocdl.tbuffer_oob_mode_flag<strict>
+ ]
+}
+
+// -----
+
+module {
+ // expected-error at +2 {{expected one of [any, relaxed, strict] for ROCDL buffer out-of-bounds mode}}
+ // expected-error at +1 {{failed to parse ROCDL_BufferOOBModeModuleFlagAttr parameter 'value'}}
+ llvm.module_flags [#rocdl.buffer_oob_mode_flag<invalid>]
+}
+
+// -----
+
// 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
new file mode 100644
index 0000000000000..8e1db326e7f28
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/rocdl-module-flags.mlir
@@ -0,0 +1,47 @@
+// RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s
+
+module {
+ llvm.module_flags [
+ #rocdl.buffer_oob_mode_flag<any>,
+ #rocdl.tbuffer_oob_mode_flag<relaxed>
+ ]
+ llvm.func @oob_any_relaxed() {
+ llvm.return
+ }
+}
+
+// CHECK-LABEL: define void @oob_any_relaxed()
+// CHECK: !llvm.module.flags = !{![[BUFFER_ANY:[0-9]+]], ![[TBUFFER_RELAXED:[0-9]+]]
+// CHECK-DAG: ![[BUFFER_ANY]] = !{i32 7, !"amdgpu.buffer.oob.mode", i32 0}
+// CHECK-DAG: ![[TBUFFER_RELAXED]] = !{i32 7, !"amdgpu.tbuffer.oob.mode", i32 1}
+
+// -----
+
+module {
+ llvm.module_flags [
+ #rocdl.buffer_oob_mode_flag<strict>
+ ]
+ llvm.func @oob_strict() {
+ llvm.return
+ }
+}
+
+// CHECK-LABEL: define void @oob_strict()
+// CHECK: !llvm.module.flags = !{![[BUFFER_STRICT:[0-9]+]]
+// CHECK-DAG: ![[BUFFER_STRICT]] = !{i32 7, !"amdgpu.buffer.oob.mode", i32 2}
+
+// -----
+
+module {
+ llvm.module_flags [
+ #llvm.mlir.module_flag<max, "amdgpu.buffer.oob.mode",
+ #rocdl.buffer_oob_mode<relaxed>>
+ ]
+ llvm.func @generic_oob_relaxed() {
+ llvm.return
+ }
+}
+
+// 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}
More information about the Mlir-commits
mailing list