18#include "llvm/Support/Debug.h"
22#define DEBUG_TYPE "xegpu"
28static std::string
makeString(
const T &array,
bool breakline =
false) {
31 llvm::raw_string_ostream os(buf);
33 for (
size_t i = 1; i < array.size(); i++) {
34 os << array[i - 1] <<
", ";
38 os << array.back() <<
"]";
44 if (
auto ty = llvm::dyn_cast<ShapedType>(type))
54 auto kind = attr.getValue();
55 return kind == CachePolicy::CACHED || kind == CachePolicy::UNCACHED ||
56 kind == CachePolicy::STREAMING || kind == CachePolicy::READ_INVALIDATE;
62 auto kind = attr.getValue();
63 return kind == CachePolicy::CACHED || kind == CachePolicy::UNCACHED ||
64 kind == CachePolicy::WRITE_BACK || kind == CachePolicy::WRITE_THROUGH;
69 VectorType valueTy,
int64_t chunkSize,
72 auto maskVecTy = dyn_cast<VectorType>(maskTy);
73 auto offsetsVecTy = dyn_cast<VectorType>(offsetsTy);
76 return emitError() <<
"Expecting chunk size == 1 for scalar result";
77 if (maskVecTy || offsetsVecTy)
78 return emitError() <<
"Expecting scalar mask and offsets.";
79 else if (maskVecTy && offsetsVecTy)
80 return emitError() <<
"Expecting a vector type result.";
84 auto valueSize = valueTy.getNumElements();
86 if (!maskVecTy && !offsetsVecTy) {
87 if (valueSize != chunkSize)
88 return emitError() <<
"value elements must match chunk size "
96 return emitError() <<
"Expecting a vector type mask.";
97 int64_t maskSize = maskVecTy.getNumElements();
100 if ((valueTy.getRank() == 1) && (valueSize != chunkSize))
101 return emitError() <<
"value elements must match chunk size "
104 if (valueSize != maskSize)
106 <<
"Mask should match value except the chunk size dim.";
112 expectedMaskShape.pop_back();
113 if (expectedMaskShape != maskShape)
114 return emitError() <<
"Mask should match value except the chunk size dim.";
127 auto offsetsVecTy = dyn_cast<VectorType>(offsetsTy);
129 return emitError() <<
"contiguity requires vector offsets (one per lane).";
131 int64_t inner = offsetsVecTy.getShape().back();
133 return emitError() <<
"contiguity = " << size <<
" (must be >= 2)";
134 if (inner % size != 0)
135 return emitError() <<
"contiguity = " << size
136 <<
" (must divide the innermost offsets dim " << inner
143 UnitAttr subgroup_block_io, DistributeLayoutAttr layout,
147 if (subgroup_block_io)
148 return emitError() <<
"subgroup_block_io "
149 "are only allowed when result is a VectorType.";
158 ArrayAttr strideAttr = mdescTy.getStrideAttr();
160 for (
Attribute attr : strideAttr.getValue()) {
161 strides.push_back(cast<IntegerAttr>(attr).getInt());
163 if (subgroup_block_io && layout) {
164 auto laneData = layout.getEffectiveLaneDataAsInt();
165 auto laneLayout = layout.getEffectiveLaneLayoutAsInt();
166 if (!laneData.empty()) {
167 bool isLaneDataContiguous =
168 std::all_of(laneData.begin(), std::prev(laneData.end()),
169 [](
int x) { return x == 1; });
170 if (!isLaneDataContiguous)
171 return emitError() <<
"With subgroup_block_io, accessed data must be "
172 "contiguous and coalesced.";
173 for (
size_t i = 0; i < laneData.size(); ++i) {
174 if (laneLayout[i] != blockShape[i])
175 return emitError() <<
"With subgroup_block_io, the block shape must "
176 "match the lane layout.";
177 if (laneLayout[i] != 1 && strides[i] != 1)
178 return emitError() <<
"With subgroup_block_io, the distributed "
179 "dimensions must be contiguous.";
184 if (layout && !layout.isDistributable(
186 return emitError() <<
"Value shape is not distributable with the layout";
188 if (dataShape.size() == mdescShape.size()) {
189 if (llvm::any_of(llvm::zip_equal(dataShape, mdescShape),
190 [](
auto p) {
return std::get<0>(p) > std::get<1>(p); }))
191 return emitError() <<
"data shape must not exceed mem_desc shape.";
195 if (subgroup_block_io && !blockShape.size())
196 return emitError() <<
"mem_desc must have block attribute when "
197 "subgroup_block_io is set.";
204LogicalResult CreateMemDescOp::verify() {
205 auto srcTy = getSource().getType();
207 return emitOpError(
"source memref must be contiguous.");
217 build(builder, state, tdesc, source,
ValueRange({}) ,
228 assert((isa<IntegerType, MemRefType>(srcTy)) &&
229 "Source has to be either int or memref.");
243 if (
auto memrefTy = dyn_cast<MemRefType>(srcTy)) {
244 auto memrefShape = memrefTy.getShape();
245 auto [memrefStrides, _] = memrefTy.getStridesAndOffset();
250 if (staticShape == memrefShape && staticStrides == memrefStrides &&
251 dynamicShape.empty() && dynamicStrides.empty()) {
257 build(builder, state, tdesc, source, dynamicShape, dynamicStrides,
258 staticShapeAttr, staticStridesAttr);
261LogicalResult CreateNdDescOp::verify() {
262 auto srcMemrefTy = dyn_cast<MemRefType>(getSourceType());
263 size_t rank = srcMemrefTy ? srcMemrefTy.getRank() :
getMixedSizes().size();
264 bool invalidElemTy =
false;
270 auto srcMemorySpace = getSourceMemorySpace();
271 auto tdescMemorySpace =
static_cast<unsigned>(
getType().getMemorySpace());
272 if (srcMemorySpace != tdescMemorySpace)
273 return emitOpError(
"Memory space mismatch.")
274 <<
" Source: " << srcMemorySpace
275 <<
", TensorDesc: " << tdescMemorySpace;
279 if (
auto memrefTy = dyn_cast<MemRefType>(getSourceType()))
282 bool hasExplicitShapeStrides =
283 !
getShape().empty() || !getStrides().empty() ||
284 (getConstShapeAttr() && !getConstShapeAttr().empty()) ||
285 (getConstStridesAttr() && !getConstStridesAttr().empty());
287 if (llvm::isa<IntegerType>(getSourceType())) {
290 return emitOpError(
"expecting strides and shape to be present for "
293 return emitOpError(
"Expecting the rank of shape and strides to match.");
294 }
else if (srcMemrefTy && hasExplicitShapeStrides) {
295 return emitOpError(
"shape and strides should not be specified for a memref "
296 "source; they are inferred from the memref.");
301 return emitOpError(
"Expecting the TensorDesc rank is not greater than the "
302 "ranks of shape, strides or the memref source.");
305 return emitOpError(
"TensorDesc should have the same element "
306 "type with the source if it is a memref.\n");
317 xegpu::CachePolicyAttr l1_hint,
318 xegpu::CachePolicyAttr l2_hint,
319 xegpu::CachePolicyAttr l3_hint,
320 xegpu::DistributeLayoutAttr layout) {
327 build(builder, state, tensorDesc, dynamicOffsets, staticOffsetsAttr, l1_hint,
328 l2_hint, l3_hint, layout);
331LogicalResult PrefetchNdOp::verify() {
332 auto tdescTy = getTensorDescType();
335 return emitOpError(
"invalid l1_hint: ") << getL1HintAttr();
338 return emitOpError(
"invalid l2_hint: ") << getL2HintAttr();
341 return emitOpError(
"invalid l3_hint: ") << getL3HintAttr();
343 int64_t tDescRank = tdescTy.getRank();
344 int64_t offsetSize = getMixedOffsets().size();
345 if (offsetSize != tDescRank)
347 "Mismatched ranks between offsets and tensor descriptor");
349 if (
auto layout = getAnchorLayout()) {
350 if (!layout.isDistributable(
getShapeOf(tdescTy)))
352 "TensorDesc shape is not distributable with the layout");
365 xegpu::CachePolicyAttr l1_hint,
366 xegpu::CachePolicyAttr l2_hint,
367 xegpu::CachePolicyAttr l3_hint,
368 xegpu::DistributeLayoutAttr layout) {
375 build(builder, state, retType, tensorDesc, dynamicOffsets, staticOffsetsAttr,
376 packed, transpose, l1_hint, l2_hint, l3_hint,
380LogicalResult LoadNdOp::verify() {
381 auto tdescTy = getTensorDescType();
385 return emitOpError(
"Invalid result, it should be a VectorType.\n");
388 return emitOpError(
"invalid l1_hint: ") << getL1HintAttr();
391 return emitOpError(
"invalid l2_hint: ") << getL2HintAttr();
394 return emitOpError(
"invalid l3_hint: ") << getL3HintAttr();
396 int tdescElems = tdescTy.getNumElements() * tdescTy.getArrayLength();
397 int valueElems = valueTy.getNumElements();
402 if (valueElems < tdescElems && valueTy.getRank() == 1) {
404 if (tdescTy.getLayoutAttr())
406 <<
"TensorDesc doesn't need LayoutAttr for SIMT code";
411 if (tdescElems % valueElems)
414 <<
" is not a valid distribution for tensor descriptor "
424 if (getTranspose()) {
425 auto trans = getTranspose().value();
427 if (llvm::all_of(trans, [&](
size_t s) {
return s < tdescShape.size(); }))
434 if (tdescTy.getRank() == 2) {
436 auto vnni_factor = valueShape.back();
437 tdescShape[axis] /= vnni_factor;
438 tdescShape.push_back(vnni_factor);
441 <<
"Invalid Packed Attr. It is ignored (available for 2D "
451 auto array_len = tdescTy.getArrayLength();
454 if (array_len > 1 && !tdescShape.empty()) {
455 stacked2DShape[0] *= array_len;
456 threeDShape.insert(threeDShape.begin(), array_len);
459 if (valueShape != stacked2DShape && valueShape != threeDShape)
460 return emitOpError() <<
"Result shape " <<
makeString(valueShape)
461 <<
" is not consistent with tensor descriptor "
464 int64_t tDescRank = tdescTy.getRank();
465 int64_t offsetSize = getMixedOffsets().size();
466 if (offsetSize != tDescRank)
468 "Mismatched ranks between offsets and tensor descriptor");
470 if (
auto layout = getAnchorLayout()) {
471 if (!layout.isDistributable(
getShapeOf(tdescTy)))
473 "TensorDesc shape is not distributable with the layout");
485 xegpu::CachePolicyAttr l1_hint,
486 xegpu::CachePolicyAttr l2_hint,
487 xegpu::CachePolicyAttr l3_hint,
488 xegpu::DistributeLayoutAttr layout) {
495 build(builder, state, value, tensorDesc, dynamicOffsets, staticOffsetsAttr,
496 l1_hint, l2_hint, l3_hint, layout);
499LogicalResult StoreNdOp::verify() {
500 auto dstTy = getTensorDescType();
504 return emitOpError(
"Expecting a VectorType result.\n");
507 return emitOpError(
"invalid l1_hint: ") << getL1HintAttr();
510 return emitOpError(
"invalid l2_hint: ") << getL2HintAttr();
513 return emitOpError(
"invalid l3_hint: ") << getL3HintAttr();
515 auto array_len = dstTy.getArrayLength();
517 return emitOpError(
"array length is not supported by store_nd.\n");
519 auto tdescElems = dstTy.getNumElements();
520 auto valueElems = valTy.getNumElements();
525 if (valTy.getRank() == 1 && valueElems < tdescElems) {
527 if (dstTy.getLayoutAttr())
529 <<
"TensorDesc doesn't need LayoutAttr for SIMT code";
531 if (tdescElems % valueElems)
534 <<
" is not a valid distribution for tensor descriptor " << dstTy;
542 if (tdescShape != valueShape)
543 return emitOpError() <<
"Value shape " <<
makeString(valueShape)
544 <<
" is not consistent with tensor descriptor "
547 int64_t tDescRank = dstTy.getRank();
548 int64_t offsetSize = getMixedOffsets().size();
549 if (offsetSize != tDescRank)
551 "Mismatched ranks between offsets and tensor descriptor");
553 if (
auto layout = getAnchorLayout()) {
554 if (!layout.isDistributable(std::move(tdescShape)))
556 "TensorDesc shape is not distributable with the layout");
565LogicalResult PrefetchOp::verify() {
567 return emitOpError(
"invalid l1_hint: ") << getL1HintAttr();
570 return emitOpError(
"invalid l2_hint: ") << getL2HintAttr();
573 return emitOpError(
"invalid l3_hint: ") << getL3HintAttr();
575 auto srcTy = getSourceType();
576 if (srcTy.
isInteger() && !getOffsetAlignByteAttr())
577 return emitOpError(
"offset_align_byte is required with integer source.");
579 if (getOffsetAlignByteAttr() && !srcTy.
isInteger())
580 return emitOpError(
"offset_align_byte only allowed with integer source.");
582 if (
auto layout = getAnchorLayout()) {
584 auto offsetsTy = getOffsets().getType();
585 if (llvm::isa<VectorType>(offsetsTy) &&
586 !layout.isDistributable(
getShapeOf(offsetsTy)))
587 return emitOpError(
"offset shape is not distributable with the layout");
596LogicalResult LoadGatherOp::verify() {
597 auto maskTy = getMaskType();
601 return emitOpError(
"invalid l1_hint: ") << getL1HintAttr();
604 return emitOpError(
"invalid l2_hint: ") << getL2HintAttr();
607 return emitOpError(
"invalid l3_hint: ") << getL3HintAttr();
609 auto srcTy = getSourceType();
610 uint64_t chunkSize =
static_cast<int64_t>(getChunkSize().value_or(1));
611 auto memTy = dyn_cast<MemRefType>(srcTy);
614 return emitError() <<
"Value should have the same element type as MemRef.";
616 if (
auto layout = getAnchorLayout()) {
617 if (!layout.isDistributable(
getShapeOf(valueTy)))
618 return emitOpError(
"Value shape is not distributable with the layout");
621 auto offsetsTy = getOffsets().getType();
623 [&]() {
return emitOpError(); })))
626 [&]() {
return emitOpError(); });
632 IntegerAttr chunk_size, xegpu::CachePolicyAttr l1_hint,
633 xegpu::CachePolicyAttr l2_hint,
634 xegpu::CachePolicyAttr l3_hint) {
635 auto loc = source.
getLoc();
637 auto type = VectorType::get(size, builder.
getIndexType());
639 auto offset = vector::FromElementsOp::create(builder, loc, type, values);
641 build(builder, state, valueType, source, offset, mask, chunk_size, l1_hint,
642 l2_hint, l3_hint,
nullptr,
649 IntegerAttr chunk_size, xegpu::CachePolicyAttr l1_hint,
650 xegpu::CachePolicyAttr l2_hint,
651 xegpu::CachePolicyAttr l3_hint,
652 DistributeLayoutAttr layout) {
653 auto loc = source.
getLoc();
655 auto type = VectorType::get(size, builder.
getIndexType());
657 auto offset = vector::FromElementsOp::create(builder, loc, type, values);
659 build(builder, state, valueType, source, offset, mask, chunk_size, l1_hint,
660 l2_hint, l3_hint, layout,
nullptr);
666LogicalResult StoreScatterOp::verify() {
667 auto maskTy = getMaskType();
671 return emitOpError(
"invalid l1_hint: ") << getL1HintAttr();
674 return emitOpError(
"invalid l2_hint: ") << getL2HintAttr();
677 return emitOpError(
"invalid l3_hint: ") << getL3HintAttr();
679 auto destTy = getDestType();
680 uint64_t chunkSize =
static_cast<int64_t>(getChunkSize().value_or(1));
681 auto memTy = dyn_cast<MemRefType>(destTy);
684 return emitError() <<
"Value should have the same element type as MemRef.";
686 if (
auto layout = getAnchorLayout()) {
687 if (!layout.isDistributable(
getShapeOf(valueTy)))
688 return emitOpError(
"Value shape is not distributable with the layout");
691 auto offsetsTy = getOffsets().getType();
693 [&]() {
return emitOpError(); })))
696 [&]() {
return emitOpError(); });
702 IntegerAttr chunk_size,
703 xegpu::CachePolicyAttr l1_hint,
704 xegpu::CachePolicyAttr l2_hint,
705 xegpu::CachePolicyAttr l3_hint) {
708 auto type = VectorType::get(size, builder.
getIndexType());
710 auto offset = vector::FromElementsOp::create(builder, loc, type, values);
713 build(builder, state, value, dest, offset, mask, chunk_size, l1_hint, l2_hint,
714 l3_hint,
nullptr,
nullptr);
717void StoreScatterOp::build(
720 xegpu::CachePolicyAttr l1_hint, xegpu::CachePolicyAttr l2_hint,
721 xegpu::CachePolicyAttr l3_hint, DistributeLayoutAttr layout) {
724 auto type = VectorType::get(size, builder.
getIndexType());
726 auto offset = vector::FromElementsOp::create(builder, loc, type, values);
729 build(builder, state, value, dest, offset, mask, chunk_size, l1_hint, l2_hint,
730 l3_hint, layout,
nullptr);
740 std::optional<DistributeLayoutAttr> layout,
742 if (layout && !layout->isDistributable(
745 <<
" shape is not distributable with the layout";
755 auto aRank = aShape.size();
756 auto bRank = bShape.size();
757 auto resRank = resShape.size();
758 if (aRank == 1 && bRank == 1 && resRank == 1)
764 return op->
emitOpError(
"A operand must be at least a 2D vector.");
766 return op->
emitOpError(
"B operand must be at least a 2D vector.");
768 return op->
emitOpError(
"Result must be at least a 2D vector.");
775 if (bRank == aRank + 1)
781 if (aRank != bRank || aRank != resRank)
782 return op->
emitOpError(
"Rank mismatch among A, B, and result.");
787 for (
int64_t i = 0; i < batchRank; ++i) {
788 if (aShape[i] != resShape[i])
789 return op->
emitOpError(
"Batch dimension mismatch at dim ")
790 << i <<
": A has " << aShape[i] <<
" but result has "
791 << resShape[i] <<
".";
792 if (aShape[i] != bShape[i])
793 return op->
emitOpError(
"Batch dimension mismatch at dim ")
794 << i <<
": A has " << aShape[i] <<
" but B has " << bShape[i]
799 int64_t aM = aShape[batchRank];
800 int64_t aK = aShape[batchRank + 1];
801 int64_t bK = bShape[batchRank];
802 int64_t bN = bShape[batchRank + 1];
803 int64_t resM = resShape[batchRank];
804 int64_t resN = resShape[batchRank + 1];
808 return op->
emitOpError(
"K-dimension mismatch: A has K=")
809 << aK <<
" but B has K=" << bK <<
".";
813 return op->
emitOpError(
"M-dimension mismatch: A has M=")
814 << aM <<
" but result has M=" << resM <<
".";
818 return op->
emitOpError(
"N-dimension mismatch: B has N=")
819 << bN <<
" but result has N=" << resN <<
".";
827 if (accType != resultType)
828 return op->
emitOpError(
"Accumulator type must match result type.");
835LogicalResult DpasOp::verify() {
836 auto lhsShape = getLhsType().getShape();
837 auto rhsShape = getRhsType().getShape();
838 auto resShape = getResultType().getShape();
860LogicalResult ConvertLayoutOp::verify() {
861 auto resLayout = getTargetLayout();
863 return emitOpError(
"expected target layout.");
864 auto srcLayout = getEffectiveInputLayout();
868 if ((!srcLayout.isForWorkgroup() || !resLayout.isForWorkgroup()) &&
869 (!srcLayout.isForSubgroup() || !resLayout.isForSubgroup()))
870 return emitOpError(
"expected input layout and target layout be WgLayout or "
871 "SgLayout at the same time.");
873 Type srcType = getSource().getType();
874 if (llvm::isa<VectorType>(srcType)) {
876 if (!srcLayout.isDistributable(
shape))
878 "invalid input layout, data cannot be evenly distributed.");
880 if (!resLayout.isDistributable(std::move(
shape)))
882 "invalid target layout, data cannot be evenly distributed.");
884 return mlir::success();
893 DistributeLayoutAttr layout) {
900 build(builder, state, res, memDesc, dynamicOffsets, staticOffsetsAttr,
904LogicalResult LoadMatrixOp::verify() {
906 auto resTy = dyn_cast<VectorType>(getRes().
getType());
907 UnitAttr subgroup_block_io = getSubgroupBlockIoAttr();
908 MemDescType mdescTy = getMemDesc().getType();
911 getLayoutAttr(), [&]() {
return emitError(); });
920 DistributeLayoutAttr layout) {
925 build(builder, state, data, memDesc, dynamicOffsets, staticOffsetsAttr,
929LogicalResult StoreMatrixOp::verify() {
931 auto dataTy = dyn_cast<VectorType>(getData().
getType());
932 UnitAttr subgroup_block_io = getSubgroupBlockIoAttr();
933 MemDescType mdescTy = getMemDesc().getType();
935 getLayoutAttr(), [&]() {
return emitError(); });
942LogicalResult TruncfOp::verify() {
943 auto sourceVecType = dyn_cast<VectorType>(getSource().
getType());
944 auto resultVecType = dyn_cast<VectorType>(getResult().
getType());
946 if (sourceVecType.getElementTypeBitWidth() <=
947 resultVecType.getElementTypeBitWidth())
948 return emitOpError(
"input type must be wider than result type.");
957LogicalResult LaneShuffleOp::verify() {
961 return emitOpError(
"requires a source vector with at least 2 elements.");
969 auto producer = getSource().getDefiningOp<LaneShuffleOp>();
970 if (producer && producer.getMode() != getMode())
971 return producer.getSource();
980LogicalResult DpasMxOp::verify() {
981 auto aShape = getAType().getShape();
982 auto bShape = getBType().getShape();
983 auto resShape = getResultType().getShape();
1004 int64_t aBatchRank = aShape.size() - 2;
1008 auto scaleAVecType = dyn_cast<VectorType>(getScaleAType());
1010 if (scaleAVecType && scaleAVecType.getRank() > 1) {
1011 auto scaleAShape = scaleAVecType.getShape();
1013 if (scaleAVecType.getRank() < 2)
1014 return emitOpError(
"Scale A must be at least a 2D vector when not a "
1019 scaleAShape,
"ScaleA")))
1023 if (scaleAShape[scaleAShape.size() - 2] != aShape[aBatchRank])
1024 return emitOpError(
"Scale A M dimension [")
1025 << scaleAShape[scaleAShape.size() - 2]
1026 <<
"] must match A M dimension [" << aShape[aBatchRank] <<
"].";
1032 auto scaleBVecType = dyn_cast<VectorType>(getScaleBType());
1034 if (scaleBVecType && scaleBVecType.getRank() > 1) {
1035 auto scaleBShape = scaleBVecType.getShape();
1037 if (scaleBVecType.getRank() < 2)
1038 return emitOpError(
"Scale B must be at least a 2D vector when not a "
1043 scaleBShape,
"ScaleB")))
1048 if (scaleBShape.back() != bShape.back())
1049 return emitOpError(
"Scale B N dimension [")
1050 << scaleBShape.back() <<
"] must match B N dimension ["
1051 << bShape.back() <<
"].";
1057 if (getScaleA() && getScaleB()) {
1058 auto scaleAVecType = dyn_cast<VectorType>(getScaleAType());
1059 auto scaleBVecType = dyn_cast<VectorType>(getScaleBType());
1061 if (scaleAVecType && scaleBVecType && scaleAVecType.getRank() > 1 &&
1062 scaleBVecType.getRank() > 1) {
1063 auto scaleAShape = scaleAVecType.getShape();
1064 auto scaleBShape = scaleBVecType.getShape();
1068 if (scaleAShape.back() != scaleBShape[scaleBShape.size() - 2])
1069 return emitOpError(
"Scale K dimension mismatch: scale_a has K=")
1070 << scaleAShape.back()
1071 <<
" but scale_b has K=" << scaleBShape[scaleBShape.size() - 2]
1080#include <mlir/Dialect/XeGPU/IR/XeGPUAttrInterface.cpp.inc>
1082#include <mlir/Dialect/XeGPU/IR/XeGPUEnums.cpp.inc>
1083#define GET_OP_CLASSES
1084#include <mlir/Dialect/XeGPU/IR/XeGPU.cpp.inc>
static int64_t getNumElements(Type t)
Compute the total number of elements in the given type, also taking into account nested types.
static Type getValueType(Attribute attr)
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
static ArrayRef< int64_t > getShape(Type type)
Returns the shape of the given type.
static SmallVector< int64_t > getShapeOf(Type type)
static std::string makeString(const T &array, bool breakline=false)
static LogicalResult verifyDpasAccumulator(Operation *op, Type accType, Type resultType)
LogicalResult IsValidMatrixOpParams(VectorType dataTy, MemDescType mdescTy, UnitAttr subgroup_block_io, DistributeLayoutAttr layout, function_ref< InFlightDiagnostic()> emitError)
static bool isWriteHintOrNone(const CachePolicyAttr &attr)
static bool isReadHintOrNone(const CachePolicyAttr &attr)
static LogicalResult isValidGatherScatterBufferParams(Type offsetsTy, Type maskTy, VectorType valueTy, int64_t chunkSize, function_ref< InFlightDiagnostic()> emitError)
static LogicalResult isValidContiguity(std::optional< uint64_t > contiguity, Type offsetsTy, function_ref< InFlightDiagnostic()> emitError)
static LogicalResult verifyDpasDimensions(Operation *op, ArrayRef< int64_t > aShape, ArrayRef< int64_t > bShape, ArrayRef< int64_t > resShape)
static LogicalResult verifyLayoutDistributable(Operation *op, std::optional< DistributeLayoutAttr > layout, ArrayRef< int64_t > shape, StringRef operandName)
Attributes are known-constant values of operations.
DenseI64ArrayAttr getDenseI64ArrayAttr(ArrayRef< int64_t > values)
This class represents a diagnostic that is inflight and set to be reported.
This class helps build Operations.
This class represents a single result from folding an operation.
Operation is the basic unit of execution within MLIR.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
bool isInteger() const
Return true if this is an integer type (with the specified width).
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Location getLoc() const
Return the location of this value.
bool isStaticShapeAndContiguousRowMajor(MemRefType type)
Returns true, if the memref type has static shapes and represents a contiguous chunk of memory.
SmallVector< OpFoldResult > getMixedSizes(OpBuilder &builder, Location loc, Value value)
Return the dimensions of the given memref value.
Include the generated interface declarations.
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
detail::DenseArrayAttrImpl< int64_t > DenseI64ArrayAttr
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
SmallVector< T > applyPermutation(ArrayRef< T > input, ArrayRef< int64_t > permutation)
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
std::conditional_t< std::is_same_v< Ty, mlir::Type >, mlir::Value, detail::TypedValue< Ty > > TypedValue
If Ty is mlir::Type this will select Value instead of having a wrapper around it.
void dispatchIndexOpFoldResults(ArrayRef< OpFoldResult > ofrs, SmallVectorImpl< Value > &dynamicVec, SmallVectorImpl< int64_t > &staticVec)
Helper function to dispatch multiple OpFoldResults according to the behavior of dispatchIndexOpFoldRe...
Value getValueOrCreateConstantIndexOp(OpBuilder &b, Location loc, OpFoldResult ofr)
Converts an OpFoldResult to a Value.
llvm::function_ref< Fn > function_ref
This represents an operation in an abstracted form, suitable for use with the builder APIs.