-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[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
base: main
Are you sure you want to change the base?
Changes from 10 commits
cce8aba
76ccc39
e62da97
cb0a195
98871cc
06eec6e
6df4291
e11c88d
23380a9
9e3aa8d
af2c25f
0531abf
0385088
f6862fa
552c871
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -201,4 +201,26 @@ 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this layout? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the tests, there is usage like There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 Could you add more description here? Or at least an example snippet. |
||
contiguously in row-major order within the region. | ||
}]; | ||
let parameters = (ins ArrayRefParameter<"int64_t">: $shape, | ||
"mlir::Type": $elementType, | ||
OptionalParameter<"mlir::Attribute">: $layout); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider using mem_layout instead of layout, to differentiate with XeGPU.layout which describes the mapping between sg/lane ids to the data. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
|
||
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, getLayout()); | ||
} | ||
}]; | ||
|
||
let hasCustomAssemblyFormat = true; | ||
} | ||
|
||
#endif // MLIR_DIALECT_XEGPU_IR_XEGPUTYPES_TD |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,8 @@ | |
//===----------------------------------------------------------------------===// | ||
|
||
#include "mlir/Dialect/Arith/Utils/Utils.h" | ||
#include "mlir/Dialect/GPU/IR/GPUDialect.h" | ||
#include "mlir/Dialect/LLVMIR/XeVMDialect.h" | ||
#include "mlir/Dialect/Utils/IndexingUtils.h" | ||
#include "mlir/Dialect/Utils/StaticValueUtils.h" | ||
#include "mlir/Dialect/XeGPU/IR/XeGPU.h" | ||
|
@@ -21,6 +23,17 @@ | |
namespace mlir { | ||
namespace xegpu { | ||
|
||
bool isSharedMemory(const MemRefType &memrefTy) { | ||
Attribute attr = memrefTy.getMemorySpace(); | ||
if (auto intAttr = llvm::dyn_cast<IntegerAttr>(attr)) | ||
return intAttr.getInt() == 3; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added support for this. |
||
if (auto memrefSpace = llvm::dyn_cast<MemorySpaceAttr>(attr)) | ||
return memrefSpace.getValue() == MemorySpace::SLM; | ||
if (auto xevmSpace = llvm::dyn_cast<xevm::AddrSpaceAttr>(attr)) | ||
return xevmSpace.getValue() == xevm::AddrSpace::SHARED; | ||
return gpu::GPUDialect::isWorkgroupMemoryAddressSpace(attr); | ||
} | ||
|
||
template <typename T> | ||
static std::string makeString(T array, bool breakline = false) { | ||
std::string buf; | ||
|
@@ -925,6 +938,82 @@ void ConvertLayoutOp::getCanonicalizationPatterns(RewritePatternSet &patterns, | |
patterns.add<FoldConvertLayoutOp>(context); | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// XeGPU_LoadMatrixOp | ||
//===----------------------------------------------------------------------===// | ||
void LoadMatrixOp::build(OpBuilder &builder, OperationState &state, Type res, | ||
TypedValue<MatrixDescType> matrixDesc, | ||
llvm::ArrayRef<OpFoldResult> offsets, | ||
LayoutTrait layout) { | ||
llvm::SmallVector<Value> dynamicOffsets; | ||
llvm::SmallVector<int64_t> staticOffsets; | ||
dispatchIndexOpFoldResults(offsets, dynamicOffsets, staticOffsets); | ||
auto staticOffsetsAttr = builder.getDenseI64ArrayAttr(staticOffsets); | ||
build(builder, state, res, matrixDesc, dynamicOffsets, staticOffsetsAttr, | ||
layout); | ||
} | ||
|
||
LogicalResult LoadMatrixOp::verify() { | ||
ArrayRef<int64_t> valueShape = getRes().getType().getShape(); | ||
ArrayRef<int64_t> mdescShape = getMatrixDesc().getType().getShape(); | ||
if (llvm::any_of(llvm::zip_equal(valueShape, mdescShape), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per latest definition, it can load or store a smaller shape of data from a bigger MatrixDesc. So AllShapesMatch doesn't fit here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, sorry, missed the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no worries |
||
[](auto p) { return std::get<0>(p) > std::get<1>(p); })) | ||
return emitOpError("result shape must not exceed matrix desc shape."); | ||
return success(); | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// XeGPU_StoreMatrixOp | ||
//===----------------------------------------------------------------------===// | ||
void StoreMatrixOp::build(OpBuilder &builder, OperationState &state, | ||
TypedValue<MatrixDescType> matrixDesc, | ||
llvm::ArrayRef<OpFoldResult> offsets, Value data, | ||
LayoutTrait layout) { | ||
llvm::SmallVector<Value> dynamicOffsets; | ||
llvm::SmallVector<int64_t> staticOffsets; | ||
dispatchIndexOpFoldResults(offsets, dynamicOffsets, staticOffsets); | ||
auto staticOffsetsAttr = builder.getDenseI64ArrayAttr(staticOffsets); | ||
build(builder, state, matrixDesc, dynamicOffsets, staticOffsetsAttr, data, | ||
layout); | ||
} | ||
|
||
LogicalResult StoreMatrixOp::verify() { | ||
ArrayRef<int64_t> dataShape = getData().getType().getShape(); | ||
ArrayRef<int64_t> mdescShape = getMatrixDesc().getType().getShape(); | ||
if (llvm::any_of(llvm::zip_equal(dataShape, mdescShape), | ||
[](auto p) { return std::get<0>(p) > std::get<1>(p); })) | ||
return emitOpError("data shape must not exceed matrix desc shape."); | ||
|
||
return success(); | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// XeGPU_MatrixDescSubviewOp | ||
//===----------------------------------------------------------------------===// | ||
|
||
void MatrixDescSubviewOp::build(OpBuilder &builder, OperationState &state, | ||
Type resTy, Value src, | ||
llvm::ArrayRef<OpFoldResult> offsets) { | ||
llvm::SmallVector<Value> dynamicOffsets; | ||
llvm::SmallVector<int64_t> staticOffsets; | ||
dispatchIndexOpFoldResults(offsets, dynamicOffsets, staticOffsets); | ||
auto staticOffsetsAttr = builder.getDenseI64ArrayAttr(staticOffsets); | ||
build(builder, state, resTy, src, dynamicOffsets, staticOffsetsAttr); | ||
} | ||
|
||
LogicalResult MatrixDescSubviewOp::verify() { | ||
ArrayRef<int64_t> srcShape = getSrc().getType().getShape(); | ||
ArrayRef<int64_t> resShape = getRes().getType().getShape(); | ||
if (llvm::any_of(llvm::zip_equal(resShape, srcShape), | ||
[](auto p) { return std::get<0>(p) > std::get<1>(p); })) | ||
return emitOpError("result shape must not exceed source shape."); | ||
|
||
if (getSrc().getType().getLayout() != getRes().getType().getLayout()) | ||
return emitOpError("result must inherit the source layout."); | ||
|
||
return success(); | ||
} | ||
|
||
} // namespace xegpu | ||
} // namespace mlir | ||
|
||
|
There was a problem hiding this comment.
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.