[Mlir-commits] [mlir] [amdgpu][mlir] implement amdgpu.cluster_load_async_to_lds (PR #195410)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sun May 3 00:33:46 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-amdgpu
@llvm/pr-subscribers-mlir
Author: Eric (efric)
<details>
<summary>Changes</summary>
Implement amdgpu.cluster_load_async_to_lds
Assisted by: Cursor
---
Patch is 22.06 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/195410.diff
6 Files Affected:
- (modified) mlir/include/mlir/Dialect/AMDGPU/IR/AMDGPUOps.td (+43-1)
- (modified) mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp (+73-7)
- (modified) mlir/lib/Dialect/AMDGPU/IR/AMDGPUOps.cpp (+52-16)
- (modified) mlir/test/Conversion/AMDGPUToROCDL/gfx1250.mlir (+64)
- (modified) mlir/test/Dialect/AMDGPU/invalid.mlir (+95)
- (modified) mlir/test/Dialect/AMDGPU/ops.mlir (+36)
``````````diff
diff --git a/mlir/include/mlir/Dialect/AMDGPU/IR/AMDGPUOps.td b/mlir/include/mlir/Dialect/AMDGPU/IR/AMDGPUOps.td
index 4112ea281bb96..8843e445fb3fa 100644
--- a/mlir/include/mlir/Dialect/AMDGPU/IR/AMDGPUOps.td
+++ b/mlir/include/mlir/Dialect/AMDGPU/IR/AMDGPUOps.td
@@ -1382,7 +1382,8 @@ def AMDGPU_GlobalLoadAsyncToLDSOp :
AMDGPU wrapper for `global.load.async.to.lds` instructions, which performs
asynchronous load of data from global memory into LDS while bypassing VGPRs.
- * `$src`: global memory memref to read from (global addrspace only, no fat buffer).
+ * `$src`: global memory memref to read from (global addrspace only, no
+ fat buffer).
* `$srcIndices`: indices into `$src` for this thread's global read location.
* `$dst`: LDS memref to write to (workgroup addrspace).
* `$dstIndices`: indices into `$dst` for this thread's LDS write location.
@@ -1415,6 +1416,47 @@ def AMDGPU_GlobalLoadAsyncToLDSOp :
let hasVerifier = 1;
}
+def AMDGPU_ClusterLoadAsyncToLDSOp :
+ AMDGPU_Op<"cluster_load_async_to_lds", [AttrSizedOperandSegments]>,
+ Arguments<(ins
+ Arg<AnyMemRef, "global memory to load from", [MemRead]>:$src,
+ Variadic<Index>:$srcIndices,
+ Arg<AnyMemRef, "LDS memory to write to", [MemWrite]>:$dst,
+ Variadic<Index>:$dstIndices,
+ I32:$clusterMask,
+ TypeAttr:$transferType
+ )>,
+ Results<(outs)> {
+ let summary = "MLIR wrapper for async cluster global load to LDS instructions";
+ let description = [{
+ AMDGPU wrapper for `cluster.load.async.to.lds` instructions, which broadcast
+ a global memory load to LDS from a single wave (subgroup) across a cluster of
+ workgroups while bypassing VGPRs.
+
+ * `$src`: global memory memref to read from (global addrspace only, no fat buffer).
+ * `$srcIndices`: indices into `$src` for this thread's global read location.
+ * `$dst`: LDS memref to write to (workgroup addrspace).
+ * `$dstIndices`: indices into `$dst` for this thread's LDS write location.
+ * `$clusterMask`: i32 mask selecting the workgroups which are part of the cluster.
+ * `$transferType`: type of data to be transferred. Must be an 8, 32, 64, or 128 bit
+ scalar or vector type.
+
+ Note: only supported on gfx1250 and later.
+
+ Example:
+ ```mlir
+ amdgpu.cluster_load_async_to_lds %src[%i, %j], %dst[%k, %l], %mask
+ : f32, memref<128x64xf32, #gpu.address_space<global>>,
+ memref<64x64xf32, #gpu.address_space<workgroup>>
+ ```
+ }];
+ let assemblyFormat = [{
+ $src `[` $srcIndices `]` `,` $dst `[` $dstIndices `]` `,` $clusterMask
+ attr-dict `:` $transferType `,` type($src) `,` type($dst)
+ }];
+ let hasVerifier = 1;
+}
+
def AMDGPU_TransposeLoadOp :
AMDGPU_Op<"transpose_load", [SameVariadicOperandSize]>,
Arguments<(ins Arg<AnyMemRef, "buffer to transpose load from", [MemRead]>:$src, Variadic<Index>:$srcIndices)>,
diff --git a/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp b/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp
index 8464d1e29f0aa..470ef56f377d0 100644
--- a/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp
+++ b/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp
@@ -2289,6 +2289,13 @@ struct GatherToLDSOpLowering : public ConvertOpToLLVMPattern<GatherToLDSOp> {
}
};
+static unsigned getTransferSizeInBits(Type transferType) {
+ if (VectorType transferVectorType = dyn_cast<VectorType>(transferType))
+ return transferVectorType.getNumElements() *
+ transferVectorType.getElementTypeBitWidth();
+ return transferType.getIntOrFloatBitWidth();
+}
+
struct GlobalLoadAsyncToLDSOpLowering
: public ConvertOpToLLVMPattern<GlobalLoadAsyncToLDSOp> {
GlobalLoadAsyncToLDSOpLowering(const LLVMTypeConverter &converter,
@@ -2311,11 +2318,7 @@ struct GlobalLoadAsyncToLDSOpLowering
auto dstMemRefType = cast<MemRefType>(op.getDst().getType());
Type transferType = op.getTransferType();
- int transferBits =
- isa<VectorType>(transferType)
- ? cast<VectorType>(transferType).getNumElements() *
- cast<VectorType>(transferType).getElementTypeBitWidth()
- : transferType.getIntOrFloatBitWidth();
+ unsigned transferBits = getTransferSizeInBits(transferType);
Value srcPtr =
getStridedElementPtr(rewriter, loc, srcMemRefType, adaptor.getSrc(),
@@ -2366,6 +2369,68 @@ struct GlobalLoadAsyncToLDSOpLowering
}
};
+struct ClusterLoadAsyncToLDSOpLowering
+ : public ConvertOpToLLVMPattern<ClusterLoadAsyncToLDSOp> {
+ ClusterLoadAsyncToLDSOpLowering(const LLVMTypeConverter &converter,
+ Chipset chipset)
+ : ConvertOpToLLVMPattern<ClusterLoadAsyncToLDSOp>(converter),
+ chipset(chipset) {}
+
+ Chipset chipset;
+
+ LogicalResult
+ matchAndRewrite(ClusterLoadAsyncToLDSOp op,
+ ClusterLoadAsyncToLDSOpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ if (chipset < kGfx1250)
+ return op.emitOpError(
+ "cluster_load_async_to_lds is only supported on gfx1250+");
+
+ Location loc = op.getLoc();
+ auto srcMemRefType = cast<MemRefType>(op.getSrc().getType());
+ auto dstMemRefType = cast<MemRefType>(op.getDst().getType());
+
+ Type transferType = op.getTransferType();
+ unsigned transferBits = getTransferSizeInBits(transferType);
+
+ Value srcPtr =
+ getStridedElementPtr(rewriter, loc, srcMemRefType, adaptor.getSrc(),
+ adaptor.getSrcIndices());
+ Value dstPtr =
+ getStridedElementPtr(rewriter, loc, dstMemRefType, adaptor.getDst(),
+ adaptor.getDstIndices());
+ IntegerAttr offset = rewriter.getI32IntegerAttr(0);
+ IntegerAttr cpol = rewriter.getI32IntegerAttr(0);
+ Value clusterMask = adaptor.getClusterMask();
+
+ switch (transferBits) {
+ case 8:
+ rewriter.replaceOpWithNewOp<ROCDL::ClusterLoadAsyncToLDSB8Op>(
+ op, srcPtr, dstPtr, offset, cpol, clusterMask, ArrayAttr{},
+ ArrayAttr{}, ArrayAttr{});
+ break;
+ case 32:
+ rewriter.replaceOpWithNewOp<ROCDL::ClusterLoadAsyncToLDSB32Op>(
+ op, srcPtr, dstPtr, offset, cpol, clusterMask, ArrayAttr{},
+ ArrayAttr{}, ArrayAttr{});
+ break;
+ case 64:
+ rewriter.replaceOpWithNewOp<ROCDL::ClusterLoadAsyncToLDSB64Op>(
+ op, srcPtr, dstPtr, offset, cpol, clusterMask, ArrayAttr{},
+ ArrayAttr{}, ArrayAttr{});
+ break;
+ case 128:
+ rewriter.replaceOpWithNewOp<ROCDL::ClusterLoadAsyncToLDSB128Op>(
+ op, srcPtr, dstPtr, offset, cpol, clusterMask, ArrayAttr{},
+ ArrayAttr{}, ArrayAttr{});
+ break;
+ default:
+ return op.emitOpError("unsupported transfer width");
+ }
+ return success();
+ }
+};
+
namespace {
struct ExtPackedFp8OpLowering final
: public ConvertOpToLLVMPattern<ExtPackedFp8Op> {
@@ -4407,8 +4472,9 @@ void mlir::populateAMDGPUToROCDLConversionPatterns(LLVMTypeConverter &converter,
ScaledExtPackedMatrixOpLowering, ScaledExtPackedOpLowering,
PackedScaledTruncOpLowering, PackedTrunc2xFp8OpLowering,
PackedStochRoundFp8OpLowering, GatherToLDSOpLowering,
- GlobalLoadAsyncToLDSOpLowering, TransposeLoadOpLowering,
- AMDGPUPermlaneLowering, AMDGPUMakeDmaBaseLowering<MakeDmaBaseOp>,
+ GlobalLoadAsyncToLDSOpLowering, ClusterLoadAsyncToLDSOpLowering,
+ TransposeLoadOpLowering, AMDGPUPermlaneLowering,
+ AMDGPUMakeDmaBaseLowering<MakeDmaBaseOp>,
AMDGPUMakeDmaBaseLowering<MakeGatherDmaBaseOp>,
AMDGPULowerDescriptor<MakeDmaDescriptorOp>,
AMDGPULowerDescriptor<MakeGatherDmaDescriptorOp>,
diff --git a/mlir/lib/Dialect/AMDGPU/IR/AMDGPUOps.cpp b/mlir/lib/Dialect/AMDGPU/IR/AMDGPUOps.cpp
index 2f6f59194fba3..17542f8c14322 100644
--- a/mlir/lib/Dialect/AMDGPU/IR/AMDGPUOps.cpp
+++ b/mlir/lib/Dialect/AMDGPU/IR/AMDGPUOps.cpp
@@ -1016,33 +1016,69 @@ void GatherToLDSOp::getCanonicalizationPatterns(RewritePatternSet &results,
// GlobalLoadAsyncToLDSOp
//===----------------------------------------------------------------------===//
-LogicalResult GlobalLoadAsyncToLDSOp::verify() {
- MemRefType srcType = cast<MemRefType>(getSrc().getType());
- MemRefType dstType = cast<MemRefType>(getDst().getType());
+static unsigned getTransferSizeInBits(Type transferType) {
+ if (VectorType transferVectorType = dyn_cast<VectorType>(transferType))
+ return transferVectorType.getNumElements() *
+ transferVectorType.getElementTypeBitWidth();
+ return transferType.getIntOrFloatBitWidth();
+}
+static LogicalResult
+verifyGlobalLoadAsyncToLDSLike(Operation *op, MemRefType srcType,
+ MemRefType dstType, OperandRange srcIndices,
+ OperandRange dstIndices, Type transferType) {
if (srcType.getElementType() != dstType.getElementType())
- return emitOpError("source and destination element types must match");
+ return op->emitOpError("source and destination element types must match");
- Type transferType = getTransferType();
- int transferSize;
- if (auto vectorTransfer = dyn_cast<VectorType>(transferType)) {
- transferSize = vectorTransfer.getNumElements() *
- vectorTransfer.getElementTypeBitWidth();
- } else {
- transferSize = transferType.getIntOrFloatBitWidth();
- }
- if (!llvm::is_contained({8, 32, 64, 128}, transferSize))
- return emitOpError("transfer type size must be 8, 32, 64, or 128 bits");
+ if (srcType.getRank() != static_cast<int64_t>(srcIndices.size()))
+ return op->emitOpError("source index count must match source memref rank");
+
+ if (dstType.getRank() != static_cast<int64_t>(dstIndices.size()))
+ return op->emitOpError(
+ "destination index count must match destination memref rank");
+
+ Type transferElementType = transferType;
+ if (auto vectorType = dyn_cast<VectorType>(transferType))
+ transferElementType = vectorType.getElementType();
+ if (!transferElementType.isIntOrFloat())
+ return op->emitOpError(
+ "transfer type must be an integer, float, or vector of integers or "
+ "floats");
+
+ unsigned transferSize = getTransferSizeInBits(transferType);
+ if (!llvm::is_contained({8u, 32u, 64u, 128u}, transferSize))
+ return op->emitOpError("transfer type size must be 8, 32, 64, or 128 bits");
if (!hasGlobalMemorySpace(srcType.getMemorySpace()))
- return emitOpError("source memory address space must be global");
+ return op->emitOpError("source memory address space must be global");
if (!hasWorkgroupMemorySpace(dstType.getMemorySpace()))
- return emitOpError("destination memory address space must be Workgroup");
+ return op->emitOpError(
+ "destination memory address space must be Workgroup");
return success();
}
+LogicalResult GlobalLoadAsyncToLDSOp::verify() {
+ auto srcType = cast<MemRefType>(getSrc().getType());
+ auto dstType = cast<MemRefType>(getDst().getType());
+ return verifyGlobalLoadAsyncToLDSLike(*this, srcType, dstType,
+ getSrcIndices(), getDstIndices(),
+ getTransferType());
+}
+
+//===----------------------------------------------------------------------===//
+// ClusterLoadAsyncToLDSOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult ClusterLoadAsyncToLDSOp::verify() {
+ auto srcType = cast<MemRefType>(getSrc().getType());
+ auto dstType = cast<MemRefType>(getDst().getType());
+ return verifyGlobalLoadAsyncToLDSLike(*this, srcType, dstType,
+ getSrcIndices(), getDstIndices(),
+ getTransferType());
+}
+
//===----------------------------------------------------------------------===//
// TransposeLoadOp
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Conversion/AMDGPUToROCDL/gfx1250.mlir b/mlir/test/Conversion/AMDGPUToROCDL/gfx1250.mlir
index e43ece8c74fdf..b6200657ef202 100644
--- a/mlir/test/Conversion/AMDGPUToROCDL/gfx1250.mlir
+++ b/mlir/test/Conversion/AMDGPUToROCDL/gfx1250.mlir
@@ -1031,3 +1031,67 @@ func.func @global_load_async_to_lds_b128_masked(
memref<64x64xf32, #gpu.address_space<workgroup>>
func.return
}
+
+// -----
+// cluster_load_async_to_lds_bN
+
+// CHECK-LABEL: func @cluster_load_async_to_lds_b32
+func.func @cluster_load_async_to_lds_b32(
+ %global : memref<128x72xf32, #gpu.address_space<global>>,
+ %mask : i32) {
+ %c0 = arith.constant 0 : index
+ %c12 = arith.constant 12 : index
+ %c32 = arith.constant 32 : index
+ %alloc = memref.alloc() : memref<64x64xf32, #gpu.address_space<workgroup>>
+ // CHECK: rocdl.cluster.load.async.to.lds.b32
+ amdgpu.cluster_load_async_to_lds %global[%c12, %c0],
+ %alloc[%c32, %c0], %mask
+ : f32, memref<128x72xf32, #gpu.address_space<global>>,
+ memref<64x64xf32, #gpu.address_space<workgroup>>
+ func.return
+}
+
+// -----
+
+// CHECK-LABEL: func @cluster_load_async_to_lds_b8
+func.func @cluster_load_async_to_lds_b8(
+ %global : memref<128x72xi8, #gpu.address_space<global>>, %mask : i32) {
+ %c0 = arith.constant 0 : index
+ %alloc = memref.alloc() : memref<64x64xi8, #gpu.address_space<workgroup>>
+ // CHECK: rocdl.cluster.load.async.to.lds.b8
+ amdgpu.cluster_load_async_to_lds %global[%c0, %c0], %alloc[%c0, %c0],
+ %mask
+ : i8, memref<128x72xi8, #gpu.address_space<global>>,
+ memref<64x64xi8, #gpu.address_space<workgroup>>
+ func.return
+}
+
+// -----
+
+// CHECK-LABEL: func @cluster_load_async_to_lds_b64
+func.func @cluster_load_async_to_lds_b64(
+ %global : memref<128x72xf32, #gpu.address_space<global>>,
+ %mask : i32) {
+ %c0 = arith.constant 0 : index
+ %alloc = memref.alloc() : memref<64x64xf32, #gpu.address_space<workgroup>>
+ // CHECK: rocdl.cluster.load.async.to.lds.b64 {{.*}}, {{.*}}, 0, 0, {{.*}}
+ amdgpu.cluster_load_async_to_lds %global[%c0, %c0], %alloc[%c0, %c0],
+ %mask
+ : vector<2xf32>, memref<128x72xf32, #gpu.address_space<global>>,
+ memref<64x64xf32, #gpu.address_space<workgroup>>
+ func.return
+}
+
+// -----
+
+// CHECK-LABEL: func @cluster_load_async_to_lds_b128_dynamic_indices
+func.func @cluster_load_async_to_lds_b128_dynamic_indices(
+ %global : memref<512xi32, #gpu.address_space<global>>,
+ %src_idx : index, %dst_idx : index, %mask : i32) {
+ %alloc = memref.alloc() : memref<256xi32, #gpu.address_space<workgroup>>
+ // CHECK: rocdl.cluster.load.async.to.lds.b128
+ amdgpu.cluster_load_async_to_lds %global[%src_idx], %alloc[%dst_idx], %mask
+ : vector<4xi32>, memref<512xi32, #gpu.address_space<global>>,
+ memref<256xi32, #gpu.address_space<workgroup>>
+ func.return
+}
diff --git a/mlir/test/Dialect/AMDGPU/invalid.mlir b/mlir/test/Dialect/AMDGPU/invalid.mlir
index 2958b0fe2bc51..e84f2bca2914a 100644
--- a/mlir/test/Dialect/AMDGPU/invalid.mlir
+++ b/mlir/test/Dialect/AMDGPU/invalid.mlir
@@ -356,6 +356,18 @@ func.func @global_load_async_to_lds_bad_size_16bit(%idx1 : index,
// -----
+func.func @global_load_async_to_lds_non_numeric_transfer_type(%idx1 : index,
+ %mem1 : memref<32xf32, #gpu.address_space<global>>,
+ %mem2 : memref<32xf32, #gpu.address_space<workgroup>>) {
+ // expected-error at +1 {{'amdgpu.global_load_async_to_lds' op transfer type must be an integer, float, or vector of integers or floats}}
+ amdgpu.global_load_async_to_lds %mem1[%idx1], %mem2[%idx1]
+ : index, memref<32xf32, #gpu.address_space<global>>,
+ memref<32xf32, #gpu.address_space<workgroup>>
+ func.return
+}
+
+// -----
+
func.func @global_load_async_to_lds_src_not_global(%idx1 : index,
%mem1 : memref<32xf32, #gpu.address_space<workgroup>>,
%mem2 : memref<32xf32, #gpu.address_space<workgroup>>) {
@@ -368,6 +380,89 @@ func.func @global_load_async_to_lds_src_not_global(%idx1 : index,
// -----
+func.func @global_load_async_to_lds_src_index_count(%idx1 : index,
+ %mem1 : memref<32x32xf32, #gpu.address_space<global>>,
+ %mem2 : memref<32xf32, #gpu.address_space<workgroup>>) {
+ // expected-error at +1 {{'amdgpu.global_load_async_to_lds' op source index count must match source memref rank}}
+ amdgpu.global_load_async_to_lds %mem1[%idx1], %mem2[%idx1]
+ : f32, memref<32x32xf32, #gpu.address_space<global>>,
+ memref<32xf32, #gpu.address_space<workgroup>>
+ func.return
+}
+
+// -----
+
+func.func @cluster_load_async_to_lds_non_lds(%idx1 : index, %mask : i32,
+ %mem1 : memref<32xf32, #gpu.address_space<global>>,
+ %mem2 : memref<32xf32>) {
+ // expected-error at +1 {{'amdgpu.cluster_load_async_to_lds' op destination memory address space must be Workgroup}}
+ amdgpu.cluster_load_async_to_lds %mem1[%idx1], %mem2[%idx1], %mask
+ : f32, memref<32xf32, #gpu.address_space<global>>, memref<32xf32>
+ func.return
+}
+
+// -----
+
+func.func @cluster_load_async_to_lds_bad_size_16bit(%idx1 : index, %mask : i32,
+ %mem1 : memref<32xf16, #gpu.address_space<global>>,
+ %mem2 : memref<32xf16, #gpu.address_space<workgroup>>) {
+ // expected-error at +1 {{'amdgpu.cluster_load_async_to_lds' op transfer type size must be 8, 32, 64, or 128 bits}}
+ amdgpu.cluster_load_async_to_lds %mem1[%idx1], %mem2[%idx1], %mask
+ : f16, memref<32xf16, #gpu.address_space<global>>,
+ memref<32xf16, #gpu.address_space<workgroup>>
+ func.return
+}
+
+// -----
+
+func.func @cluster_load_async_to_lds_non_numeric_transfer_type(%idx1 : index,
+ %mask : i32, %mem1 : memref<32xf32, #gpu.address_space<global>>,
+ %mem2 : memref<32xf32, #gpu.address_space<workgroup>>) {
+ // expected-error at +1 {{'amdgpu.cluster_load_async_to_lds' op transfer type must be an integer, float, or vector of integers or floats}}
+ amdgpu.cluster_load_async_to_lds %mem1[%idx1], %mem2[%idx1], %mask
+ : vector<2xindex>, memref<32xf32, #gpu.address_space<global>>,
+ memref<32xf32, #gpu.address_space<workgroup>>
+ func.return
+}
+
+// -----
+
+func.func @cluster_load_async_to_lds_src_not_global(%idx1 : index, %mask : i32,
+ %mem1 : memref<32xf32, #gpu.address_space<workgroup>>,
+ %mem2 : memref<32xf32, #gpu.address_space<workgroup>>) {
+ // expected-error at +1 {{'amdgpu.cluster_load_async_to_lds' op source memory address space must be global}}
+ amdgpu.cluster_load_async_to_lds %mem1[%idx1], %mem2[%idx1], %mask
+ : f32, memref<32xf32, #gpu.address_space<workgroup>>,
+ memref<32xf32, #gpu.address_space<workgroup>>
+ func.return
+}
+
+// -----
+
+func.func @cluster_load_async_to_lds_src_index_count(%idx1 : index,
+ %mask : i32, %mem1 : memref<32x32xf32, #gpu.address_space<global>>,
+ %mem2 : memref<32xf32, #gpu.address_space<workgroup>>) {
+ // expected-error at +1 {{'amdgpu.cluster_load_async_to_lds' op source index count must match source memref rank}}
+ amdgpu.cluster_load_async_to_lds %mem1[%idx1], %mem2[%idx1], %mask
+ : f32, memref<32x32xf32, #gpu.address_space<global>>,
+ memref<32xf32, #gpu.address_space<workgroup>>
+ func.return
+}
+
+// -----
+
+func.func @cluster_load_async_to_lds_dst_index_count(%idx1 : index,
+ %mask : i32, %mem1 : memref<32xf32, #gpu.address_space<global>>,
+ %mem2 : memref<32x32xf32, #gpu.address_space<workgroup>>) {
+ // expected-error at +1 {{'amdgpu.cluster_load_async_to_lds' op destination index count must match destination memref rank}}
+ amdgpu.cluster_load_async_to_lds %mem1[%idx1], %mem2[%idx1], %mask
+ : f32, memref<32xf32, #gpu.address_space<global>>,
+ memref<32x32xf32, #gpu.address_space<workgroup>>
+ func.return
+}
+
+// -----
+
func.func @scaled_mfma_invalid_m(%arg0 : vector<4xf8E8M0FNU>, %arg1 : vector<32xf4E2M1FN>, %arg2 : vector<16xf32>) -> vector<16xf32> {
// expected-error at +1 {{'amdgpu.scaled_mfma' op attribute 'm' failed to satisfy constraint: 32-bit signless integer attribute whose value is one of {16, 32}}}
%0 = amdgpu.scaled_mfma 8x32x64 (%arg0[0] * %arg1) * (%arg0[1] * %arg1) + %arg2 : vector<4xf8E8M0FNU>, vector<32xf4E2M1FN>, vector<4xf8E8M0FNU>, vector<32xf4E2M1FN>, vector<16xf32>
diff --git a/mlir/test/Dialect/AMDGPU/ops.mlir b/mlir/test/Dialect/AMDGPU/ops.mlir
index 606a7768974bf..918587214411f 100644
--- a/mlir...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/195410
More information about the Mlir-commits
mailing list