Skip to content

[mlir][xegpu] Add definitons of MatrixDescType and related ops. #153273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
31 changes: 31 additions & 0 deletions mlir/include/mlir/Dialect/XeGPU/IR/XeGPUAttrs.td
Original file line number Diff line number Diff line change
Expand Up @@ -527,4 +527,35 @@ def XeGPU_RangeAttr : XeGPUAttr<"Range", "range"> {
let genVerifyDecl = 1;
}

def XeGPU_MemLayoutAttr : XeGPUAttr<"MemLayout", "mem_layout"> {
let summary = [{Specifies memory layouts with named attributes.}];

let description = [{
This attribute stores a collection of named attributes that describe
memory layout properties such as stride, block, etc.
}];

let parameters = (ins "DictionaryAttr": $attrs);
let hasCustomAssemblyFormat = 1;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove extra line


let extraClassDeclaration = [{
/// Get a specific attribute by name
Attribute getAttr(StringRef name) const {
return getAttrs().get(name);
}

/// Check if a specific attribute exists
bool hasAttr(StringRef name) const {
return getAttrs().contains(name);
}

ArrayAttr getStrides() {
return getAttrs().getAs<ArrayAttr>("stride");
}

}];

}

#endif // MLIR_DIALECT_XEGPU_IR_XEGPUATTRS_TD
146 changes: 146 additions & 0 deletions mlir/include/mlir/Dialect/XeGPU/IR/XeGPUOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -1101,4 +1101,150 @@ def XeGPU_ConvertLayoutOp: XeGPU_Op<"convert_layout", [Pure, AllTypesMatch<["sou
let hasCanonicalizer = 1;
}

def isSharedPred : CPred<"isSharedMemory(llvm::cast<mlir::MemRefType>($_self))">;
class StaticShared1DMemRefOf<list<Type> allowedTypes> :
ConfinedType<MemRefRankOf<allowedTypes, [1]>, [HasStaticShapePred, isSharedPred],
"statically shaped " # MemRefOf<allowedTypes>.summary # " for shared memory",
"mlir::MemRefType">;

class SizeInBits<string name> :
StrFunc<"llvm::cast<mlir::ShapedType>($" # name # ".getType()).getNumElements()"
"*llvm::cast<mlir::ShapedType>($" # name # ".getType()).getElementTypeBitWidth()">;
class AllMemSizesMatch<list<string> names> :
AllMatchSameOperatorTrait<names, SizeInBits<"_self">.result,
"size in bits">;

def XeGPU_CreateMatrixDescOp: XeGPU_Op<"create_matrix_desc", [Pure,
AllMemSizesMatch<["source", "matrix_desc"]>]> {
let summary = "Create a matrix descriptor.";
let description = [{
Creates a matrix descriptor from a shared local memory (SLM) buffer.
The resulting matrix descriptor has to have the same size as the underlying
shared local memory.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shared local memory => memory. The memory descriptor itself doesn't have to associated with share local memory.


Arguments:
- `source` : a 1D statically shaped memref with element type i8, representing the raw SLM buffer.
Results:
- `matrix_desc` : the matrix descriptor.
}];
let arguments = (ins StaticShared1DMemRefOf<[I8]>:$source);
let results = (outs XeGPU_MatrixDesc:$matrix_desc);
let assemblyFormat = "$source prop-dict attr-dict `` `:` type($source) `->` qualified(type($matrix_desc))";
}

def XeGPU_LoadMatrixOp: XeGPU_Op<"load_matrix", [MemoryEffects<[MemRead]>,
AllElementTypesMatch<["matrix_desc", "res"]>,
AllRanksMatch<["matrix_desc", "res"]>]> {
let arguments = (ins XeGPU_MatrixDesc:$matrix_desc,
Variadic<Index>: $offsets,
DenseI64ArrayAttr: $const_offsets,
OptionalAttr<LayoutTrait>:$layout
);
let results = (outs XeGPU_ValueType:$res);
let assemblyFormat = [{
$matrix_desc `` custom<DynamicIndexList>($offsets, $const_offsets)
prop-dict attr-dict `` `:` type(operands) `->` type(results)
}];

let description = [{
This operation reads a block of data from shared local memory (SLM)
using the provided matrix descriptor.

Arguments:
- `matrix_desc`: the matrix descriptor identifying the SLM region.
- `offsets`: the coordinates within the matrix to read from.
- `layout`: [optional] An attribute for guiding distributions among
subgroups and/or work-items. It currently can accept either
LayoutAttr or SliceAttr.
Results:
- `res`: the matrix elements loaded from SLM.
}];

let builders = [
OpBuilder<(ins "Type":$res, "TypedValue<MatrixDescType>": $matrix_desc,
"llvm::ArrayRef<OpFoldResult>": $offsets, "LayoutTrait": $layout)>,
];
let extraClassDeclaration = [{
SmallVector<OpFoldResult> getMixedOffsets() {
return getMixedValues(getConstOffsets(), getOffsets(), getContext());
}
}];

let hasVerifier = 1;
}

def XeGPU_StoreMatrixOp: XeGPU_Op<"store_matrix", [MemoryEffects<[MemWrite]>,
AllElementTypesMatch<["matrix_desc", "data"]>,
AllRanksMatch<["matrix_desc", "data"]>]> {
let arguments = (ins
XeGPU_ValueType:$data,
XeGPU_MatrixDesc:$matrix_desc,
Variadic<Index>: $offsets,
DenseI64ArrayAttr: $const_offsets,
OptionalAttr<LayoutTrait>:$layout
);
let assemblyFormat = [{ $data `,` $matrix_desc `` custom<DynamicIndexList>($offsets, $const_offsets)
prop-dict attr-dict `` `:` type(operands)}];
let description = [{
This operation writes the `data` fragment into the shared local memory region
identified by `matrix_desc`.

Arguments:
- `matrix_desc`: the matrix descriptor specifying the SLM region.
- `offsets`: the coordinates within the matrix where the data will be written.
- `data`: the values to be stored in the matrix.
- `layout`: [optional] An attribute for guiding distributions among
subgroups and/or work-items. It currently can accept either
LayoutAttr or SliceAttr.
}];
let builders = [
OpBuilder<(ins "Value" : $data, "TypedValue<MatrixDescType>": $matrix_desc,
"llvm::ArrayRef<OpFoldResult>": $offsets, "LayoutTrait": $layout)>,
];
let extraClassDeclaration = [{
SmallVector<OpFoldResult> getMixedOffsets() {
return getMixedValues(getConstOffsets(), getOffsets(), getContext());
}
}];

let hasVerifier = 1;
}

def XeGPU_MatrixDescSubviewOp: XeGPU_Op<"matrix_desc_subview",
[Pure, ViewLikeOpInterface, AllElementTypesMatch<["src", "res"]>]> {
let description = [{
Creates a subview of a matrix descriptor. The resulting matrix descriptor can have
a lower rank than the source; in this case, the result dimensions correspond to the
higher-order dimensions of the source matrix descriptor.

Arguments:
- `src` : a matrix descriptor.
- `offsets` : the coordinates within the matrix the subview will be created from.

Results:
- `res` : a matrix descriptor with smaller size.

}];
let arguments = (ins XeGPU_MatrixDesc:$src,
Variadic<Index>:$offsets,
DenseI64ArrayAttr:$const_offsets);
let results = (outs XeGPU_MatrixDesc:$res);
let assemblyFormat = [{$src `` custom<DynamicIndexList>($offsets, $const_offsets) prop-dict
attr-dict `` `:` qualified(type($src)) `->` qualified(type($res))}];
let builders = [
OpBuilder<(ins "Type": $res, "Value":$src, "llvm::ArrayRef<OpFoldResult>": $offsets)>
];

let extraClassDeclaration = [{
mlir::Value getViewSource() { return getSrc(); }

SmallVector<OpFoldResult> getMixedOffsets() {
return getMixedValues(getConstOffsets(), getOffsets(), getContext());
}
}];

let hasVerifier = 1;
}


#endif // MLIR_DIALECT_XEGPU_IR_XEGPUOPS_TD
49 changes: 49 additions & 0 deletions mlir/include/mlir/Dialect/XeGPU/IR/XeGPUTypes.td
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,53 @@ def XeGPU_Nbarrier: XeGPUTypeDef<"Nbarrier", "nbarrier", [], "mlir::Type"> {
}];
}

def XeGPU_MatrixDesc: XeGPUTypeDef<"MatrixDesc", "matrix_desc", [ShapedTypeInterface], "mlir::Type"> {
let summary = "MatrixDesc describing the data in SLM";
let description = [{
MatrixDesc represents a block of data stored in shared local memory.
By default, unless a layout attribute is provided, the data is stored
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this layout?
I assume this is not distribution layout as you said it is not part of matrix desc type.

Copy link
Contributor

@silee2 silee2 Aug 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the tests, there is usage like
!xegpu.matrix_desc<16x64xf16, strided<[1, 16]>>
Is strided<[1,16]> the layout attribute?
Is that attribute type not some that can be represented by
MemRefLayoutAttrInterface used in MemRefType ?
https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/IR/BuiltinTypes.td#L796-#L801
Looks very similar to MemRefType. For example,
memref<12x4xf32, strided<[4, 1], offset: 5>>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please refer to intel/mlir-extensions#1092 for the motivation and explanation of the slm memory layout of matrix descriptor.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to the questions here. It just reads as a MemRef layout which is fine but could use explicit clarification as layout term becomes quite overloaded within the dialect now.

Could you add more description here? Or at least an example snippet.

contiguously in row-major order within the region.

Examples:
```mlir
// A matrix of data stored in column-major order.
!xegpu.matrix_desc<128x128xf16, #xegpu.mem_layout<stride = [1, 128]>>

// A matrix of data stored in a blocked layout. Elements within the same block
// are stored contiguously in memory. Blocks are stored in row-major order.
!xegpu.matrix_desc<128x128xf16, #xegpu.mem_layout<block = [8, 8]>>

// A matrix of data stored in column-major order with blocked layout.
!xegpu.matrix_desc<128x128xf16, #xegpu.mem_layout<stride = [1, 128], block = [8, 8]>>
```
}];
let parameters = (ins ArrayRefParameter<"int64_t">: $shape,
"mlir::Type": $elementType,
OptionalParameter<"MemLayoutAttr">: $mem_layout);

let extraClassDeclaration = [{
bool hasRank() const { return true; }

MatrixDescType cloneWith(std::optional<llvm::ArrayRef<int64_t>> shape, Type elementType) const {
return MatrixDescType::get(getContext(), shape.value_or(getShape()), elementType, getMemLayout());
}

ArrayAttr getStrides() {
auto layout = getMemLayout();
if (layout && layout.hasAttr("stride")) {
return layout.getStrides();
}

// derive and return default strides
SmallVector<int64_t> defaultStrides;
llvm::append_range(defaultStrides, getShape().drop_front());
llvm::append_values(defaultStrides, 1);
Builder builder(getContext());
return builder.getI64ArrayAttr(defaultStrides);
}
}];

let hasCustomAssemblyFormat = true;
}

#endif // MLIR_DIALECT_XEGPU_IR_XEGPUTYPES_TD
2 changes: 2 additions & 0 deletions mlir/lib/Dialect/XeGPU/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ add_mlir_dialect_library(MLIRXeGPUDialect
MLIRAffineUtils
MLIRArithUtils
MLIRDialectUtils
MLIRGPUDialect
MLIRXeVMDialect
MLIRIR
MLIRViewLikeInterface
MLIRVectorDialect
Expand Down
Loading