23#include "llvm/ADT/ArrayRef.h"
31static FailureOr<Attribute>
35 if (
auto dstElementsAttr = dyn_cast<DenseElementsAttr>(value)) {
36 if (resType.isScalable() && !isa<SplatElementsAttr>(value))
37 return rewriter.notifyMatchFailure(
39 "Cannot linearize a constant scalable vector that's not a splat");
41 return dstElementsAttr.reshape(resType);
44 if (
auto poisonAttr = dyn_cast<ub::PoisonAttr>(value))
47 return rewriter.notifyMatchFailure(loc,
"unsupported attr type");
52struct LinearizeConstantLike final
53 : OpTraitConversionPattern<OpTrait::ConstantLike> {
56 LinearizeConstantLike(
const TypeConverter &typeConverter,
57 MLIRContext *context, PatternBenefit benefit = 1)
58 : OpTraitConversionPattern(typeConverter, context, benefit) {}
60 matchAndRewrite(Operation *op, ArrayRef<Value> operands,
61 ConversionPatternRewriter &rewriter)
const override {
62 Location loc = op->
getLoc();
64 return rewriter.notifyMatchFailure(loc,
"expected 1 result");
66 const TypeConverter &typeConverter = *getTypeConverter();
69 assert(resType &&
"expected 1-D vector type");
73 return rewriter.notifyMatchFailure(loc,
74 "could not fold constant-like op");
76 FailureOr<Attribute> newValue =
82 rewriter, *newValue, resType, loc);
84 return rewriter.notifyMatchFailure(
85 loc,
"could not materialize linearized constant");
87 rewriter.replaceOp(op, newOp);
92struct LinearizeVectorizable final
93 : OpTraitConversionPattern<OpTrait::Vectorizable> {
97 LinearizeVectorizable(
const TypeConverter &typeConverter,
98 MLIRContext *context, PatternBenefit benefit = 1)
99 : OpTraitConversionPattern(typeConverter, context, benefit) {}
101 matchAndRewrite(Operation *op, ArrayRef<Value> operands,
102 ConversionPatternRewriter &rewriter)
const override {
103 FailureOr<Operation *> newOp =
104 convertOpResultTypes(op, operands, *getTypeConverter(), rewriter);
108 rewriter.replaceOp(op, (*newOp)->getResults());
113template <
typename TOp>
114static bool stridesAllOne(TOp op) {
116 std::is_same_v<TOp, vector::ExtractStridedSliceOp> ||
117 std::is_same_v<TOp, vector::InsertStridedSliceOp>,
118 "expected vector.extract_strided_slice or vector.insert_strided_slice");
124static FailureOr<SmallVector<int64_t>> intsFromArrayAttr(
ArrayAttr attrs) {
128 ints.reserve(attrs.size());
129 for (
auto attr : attrs) {
130 if (
auto intAttr = dyn_cast<IntegerAttr>(attr)) {
131 ints.push_back(intAttr.getInt());
159 assert((large.size() >= small.size()) &&
160 "rank of 'large' cannot be lower than rank of 'small'");
161 assert((large.size() >= offsets.size()) &&
162 "rank of 'large' cannot be lower than the number of offsets");
163 unsigned delta = large.size() - small.size();
164 unsigned nOffsets = offsets.size();
166 return i >= delta ? small[i - delta] : 1;
169 return i < nOffsets ? offsets[i] : 0;
177 for (
int i = large.size() - 1; i >= 0; --i) {
179 int64_t smallSize = getSmall(i);
180 int64_t nextSize = currentSize * smallSize;
182 int64_t *base = nextIndices.begin();
183 int64_t offset = getOffset(i) * stride;
184 for (
int j = 0;
j < smallSize; ++
j) {
185 for (
int k = 0; k < currentSize; ++k) {
192 indices = std::move(nextIndices);
216struct LinearizeVectorExtractStridedSlice final
217 :
public mlir::OpConversionPattern<mlir::vector::ExtractStridedSliceOp> {
219 LinearizeVectorExtractStridedSlice(
const TypeConverter &typeConverter,
220 MLIRContext *context,
221 PatternBenefit benefit = 1)
222 : OpConversionPattern(typeConverter, context, benefit) {}
225 matchAndRewrite(vector::ExtractStridedSliceOp extractStridedSliceOp,
227 ConversionPatternRewriter &rewriter)
const override {
229 VectorType flatOutputType = getTypeConverter()->convertType<VectorType>(
230 extractStridedSliceOp.getType());
231 assert(flatOutputType &&
"vector type expected");
235 if (!stridesAllOne(extractStridedSliceOp)) {
236 return rewriter.notifyMatchFailure(
237 extractStridedSliceOp,
238 "extract_strided_slice with strides != 1 not supported");
241 FailureOr<SmallVector<int64_t>> offsets =
242 intsFromArrayAttr(extractStridedSliceOp.getOffsets());
244 return rewriter.notifyMatchFailure(extractStridedSliceOp,
245 "failed to get integer offsets");
248 ArrayRef<int64_t> inputShape =
249 extractStridedSliceOp.getSourceVectorType().getShape();
251 ArrayRef<int64_t> outputShape = extractStridedSliceOp.getType().getShape();
253 SmallVector<int64_t>
indices = getStridedSliceInsertionIndices(
254 outputShape, inputShape, offsets.value());
256 Value srcVector = adaptor.getSource();
257 rewriter.replaceOpWithNewOp<vector::ShuffleOp>(
258 extractStridedSliceOp, flatOutputType, srcVector, srcVector,
indices);
287struct LinearizeVectorInsertStridedSlice final
288 :
public mlir::OpConversionPattern<mlir::vector::InsertStridedSliceOp> {
290 LinearizeVectorInsertStridedSlice(
const TypeConverter &typeConverter,
291 MLIRContext *context,
292 PatternBenefit benefit = 1)
293 : OpConversionPattern(typeConverter, context, benefit) {}
296 matchAndRewrite(vector::InsertStridedSliceOp insertStridedSliceOp,
298 ConversionPatternRewriter &rewriter)
const override {
302 if (!stridesAllOne(insertStridedSliceOp)) {
303 return rewriter.notifyMatchFailure(
304 insertStridedSliceOp,
305 "insert_strided_slice with strides != 1 not supported");
308 VectorType inputType = insertStridedSliceOp.getValueToStore().getType();
309 ArrayRef<int64_t> inputShape = inputType.getShape();
311 VectorType outputType = insertStridedSliceOp.getType();
312 ArrayRef<int64_t> outputShape = outputType.getShape();
313 int64_t nOutputElements = outputType.getNumElements();
315 FailureOr<SmallVector<int64_t>> offsets =
316 intsFromArrayAttr(insertStridedSliceOp.getOffsets());
318 return rewriter.notifyMatchFailure(insertStridedSliceOp,
319 "failed to get integer offsets");
321 SmallVector<int64_t> sliceIndices = getStridedSliceInsertionIndices(
322 inputShape, outputShape, offsets.value());
324 SmallVector<int64_t>
indices(nOutputElements);
326 for (
auto [index, sliceIndex] : llvm::enumerate(sliceIndices)) {
327 indices[sliceIndex] = index + nOutputElements;
330 Value flatToStore = adaptor.getValueToStore();
331 Value flatDest = adaptor.getDest();
332 rewriter.replaceOpWithNewOp<vector::ShuffleOp>(insertStridedSliceOp,
350struct LinearizeVectorShuffle final
351 :
public OpConversionPattern<vector::ShuffleOp> {
353 LinearizeVectorShuffle(
const TypeConverter &typeConverter,
354 MLIRContext *context, PatternBenefit benefit = 1)
355 : OpConversionPattern(typeConverter, context, benefit) {}
358 matchAndRewrite(vector::ShuffleOp shuffleOp, OpAdaptor adaptor,
359 ConversionPatternRewriter &rewriter)
const override {
361 getTypeConverter()->convertType<VectorType>(shuffleOp.getType());
362 assert(dstType &&
"vector type destination expected.");
364 Value vec1 = adaptor.getV1();
365 Value vec2 = adaptor.getV2();
366 int shuffleSliceLen = 1;
367 int rank = shuffleOp.getV1().getType().getRank();
374 llvm::ArrayRef<int64_t> shape = shuffleOp.getV1().getType().getShape();
375 for (
unsigned i = 1; i < shape.size(); ++i) {
376 shuffleSliceLen *= shape[i];
384 ArrayRef<int64_t> mask = shuffleOp.getMask();
385 int64_t totalSizeOfShuffledElmnts = mask.size() * shuffleSliceLen;
386 llvm::SmallVector<int64_t, 2>
indices(totalSizeOfShuffledElmnts);
387 for (
auto [i, value] : llvm::enumerate(mask)) {
388 std::iota(
indices.begin() + shuffleSliceLen * i,
389 indices.begin() + shuffleSliceLen * (i + 1),
390 shuffleSliceLen * value);
393 rewriter.replaceOpWithNewOp<vector::ShuffleOp>(shuffleOp, dstType, vec1,
425struct LinearizeVectorExtract final
426 :
public OpConversionPattern<vector::ExtractOp> {
428 LinearizeVectorExtract(
const TypeConverter &typeConverter,
429 MLIRContext *context, PatternBenefit benefit = 1)
430 : OpConversionPattern(typeConverter, context, benefit) {}
432 matchAndRewrite(vector::ExtractOp extractOp, OpAdaptor adaptor,
433 ConversionPatternRewriter &rewriter)
const override {
434 Type dstTy = getTypeConverter()->convertType(extractOp.getType());
435 assert(dstTy &&
"expected 1-D vector type");
438 if (extractOp.hasDynamicPosition())
439 return rewriter.notifyMatchFailure(extractOp,
440 "dynamic position is not supported.");
442 llvm::ArrayRef<int64_t> shape = extractOp.getSource().getType().getShape();
443 int64_t size = extractOp.getSource().getType().getNumElements();
446 int64_t linearizedOffset = 0;
447 llvm::ArrayRef<int64_t> offsets = extractOp.getStaticPosition();
448 for (
auto [i, off] : llvm::enumerate(offsets)) {
450 linearizedOffset += offsets[i] * size;
453 Value srcVector = adaptor.getSource();
454 if (!isa<VectorType>(extractOp.getType())) {
456 Value
result = rewriter.createOrFold<vector::ExtractOp>(
457 extractOp.getLoc(), srcVector, linearizedOffset);
458 rewriter.replaceOp(extractOp,
result);
464 llvm::SmallVector<int64_t, 2>
indices(size);
466 rewriter.replaceOpWithNewOp<vector::ShuffleOp>(extractOp, dstTy, srcVector,
503struct LinearizeVectorInsert final
504 :
public OpConversionPattern<vector::InsertOp> {
506 LinearizeVectorInsert(
const TypeConverter &typeConverter,
507 MLIRContext *context, PatternBenefit benefit = 1)
508 : OpConversionPattern(typeConverter, context, benefit) {}
510 matchAndRewrite(vector::InsertOp insertOp, OpAdaptor adaptor,
511 ConversionPatternRewriter &rewriter)
const override {
512 VectorType dstTy = getTypeConverter()->convertType<VectorType>(
513 insertOp.getDestVectorType());
514 assert(dstTy &&
"vector type destination expected.");
517 if (insertOp.hasDynamicPosition())
518 return rewriter.notifyMatchFailure(insertOp,
519 "dynamic position is not supported.");
520 auto srcTy = insertOp.getValueToStoreType();
521 auto srcAsVec = dyn_cast<VectorType>(srcTy);
522 uint64_t srcSize = srcAsVec ? srcAsVec.getNumElements() : 1;
524 auto dstShape = insertOp.getDestVectorType().getShape();
525 const auto dstSize = insertOp.getDestVectorType().getNumElements();
526 auto dstSizeForOffsets = dstSize;
529 int64_t linearizedOffset = 0;
530 auto offsetsNd = insertOp.getStaticPosition();
531 for (
auto [dim, offset] : llvm::enumerate(offsetsNd)) {
532 dstSizeForOffsets /= dstShape[dim];
533 linearizedOffset += offset * dstSizeForOffsets;
536 Location loc = insertOp.getLoc();
537 Value valueToStore = adaptor.getValueToStore();
539 if (!isa<VectorType>(valueToStore.
getType())) {
541 Value
result = rewriter.createOrFold<vector::InsertOp>(
542 loc, valueToStore, adaptor.getDest(), linearizedOffset);
543 rewriter.replaceOp(insertOp,
result);
548 llvm::SmallVector<int64_t, 2>
indices(dstSize);
549 auto *origValsUntil =
indices.begin();
550 std::advance(origValsUntil, linearizedOffset);
553 std::iota(
indices.begin(), origValsUntil, 0);
554 auto *newValsUntil = origValsUntil;
555 std::advance(newValsUntil, srcSize);
557 std::iota(origValsUntil, newValsUntil, dstSize);
559 std::iota(newValsUntil,
indices.end(), linearizedOffset + srcSize);
561 Value
result = rewriter.createOrFold<vector::ShuffleOp>(
562 loc, dstTy, adaptor.getDest(), valueToStore,
indices);
564 rewriter.replaceOp(insertOp,
result);
577struct LinearizeVectorBitCast final
578 :
public OpConversionPattern<vector::BitCastOp> {
580 LinearizeVectorBitCast(
const TypeConverter &typeConverter,
581 MLIRContext *context, PatternBenefit benefit = 1)
582 : OpConversionPattern(typeConverter, context, benefit) {}
584 matchAndRewrite(vector::BitCastOp castOp, OpAdaptor adaptor,
585 ConversionPatternRewriter &rewriter)
const override {
586 auto resType = getTypeConverter()->convertType(castOp.getType());
587 assert(resType &&
"expected 1-D vector type");
588 rewriter.replaceOpWithNewOp<vector::BitCastOp>(castOp, resType,
589 adaptor.getSource());
590 return mlir::success();
605struct LinearizeVectorCreateMask final
606 : OpConversionPattern<vector::CreateMaskOp> {
609 LinearizeVectorCreateMask(
const TypeConverter &typeConverter,
610 MLIRContext *context, PatternBenefit benefit = 1)
611 : OpConversionPattern(typeConverter, context, benefit) {}
614 matchAndRewrite(vector::CreateMaskOp createMaskOp, OpAdaptor adaptor,
615 ConversionPatternRewriter &rewriter)
const override {
616 Location loc = createMaskOp.getLoc();
617 VectorType srcTy = createMaskOp.getType();
618 auto srcShape = srcTy.getShape();
619 if (srcShape.size() != 2)
620 return rewriter.notifyMatchFailure(createMaskOp,
621 "only 2D mask is supported.");
623 if (srcShape[0] != 1)
624 return rewriter.notifyMatchFailure(
625 createMaskOp,
"only unit outer dimension is supported.");
627 auto dstTy = getTypeConverter()->convertType(srcTy);
629 return rewriter.notifyMatchFailure(createMaskOp,
"cannot convert type.");
635 auto firstOperand = adaptor.getOperands().front();
637 auto isNonZero = rewriter.createOrFold<mlir::arith::CmpIOp>(
638 loc, mlir::arith::CmpIPredicate::sgt, firstOperand, zero);
639 auto isNonZeroIndex = rewriter.createOrFold<mlir::arith::IndexCastOp>(
640 loc, rewriter.getIndexType(), isNonZero);
641 auto secondOperand = adaptor.getOperands().back();
642 auto maskSize = rewriter.createOrFold<mlir::arith::AndIOp>(
643 loc, rewriter.getIndexType(), isNonZeroIndex, secondOperand);
646 mlir::vector::CreateMaskOp::create(rewriter, loc, dstTy, maskSize);
647 rewriter.replaceOp(createMaskOp, newMask);
661struct LinearizeVectorLoad final :
public OpConversionPattern<vector::LoadOp> {
663 LinearizeVectorLoad(
const TypeConverter &typeConverter, MLIRContext *context,
664 PatternBenefit benefit = 1)
665 : OpConversionPattern(typeConverter, context, benefit) {}
668 matchAndRewrite(vector::LoadOp loadOp, OpAdaptor adaptor,
669 ConversionPatternRewriter &rewriter)
const override {
670 VectorType vecTy = loadOp.getType();
672 return rewriter.notifyMatchFailure(loadOp,
"expected vector type");
674 auto shape = vecTy.getShape();
675 auto scalableDims = vecTy.getScalableDims();
678 if (!llvm::all_of(shape.drop_back(1), [](
auto d) { return d == 1; }))
679 return rewriter.notifyMatchFailure(loadOp,
680 "only vector<1x1x...xN> supported");
682 if (llvm::any_of(scalableDims.drop_back(1), [](
bool s) { return s; }))
683 return rewriter.notifyMatchFailure(loadOp,
684 "only innermost dim may be scalable");
686 auto linearTy = typeConverter->convertType<VectorType>(vecTy);
689 vector::LoadOp::create(rewriter, loadOp.getLoc(), linearTy,
690 adaptor.getBase(), adaptor.getIndices());
691 rewriter.replaceOp(loadOp, newLoad.getResult());
707struct LinearizeVectorStore final
708 :
public OpConversionPattern<vector::StoreOp> {
710 LinearizeVectorStore(
const TypeConverter &typeConverter, MLIRContext *context,
711 PatternBenefit benefit = 1)
712 : OpConversionPattern(typeConverter, context, benefit) {}
715 matchAndRewrite(vector::StoreOp storeOp, OpAdaptor adaptor,
716 ConversionPatternRewriter &rewriter)
const override {
717 VectorType vecTy = storeOp.getValueToStore().getType();
719 return rewriter.notifyMatchFailure(storeOp,
"expected vector type");
721 auto shape = vecTy.getShape();
722 auto scalableDims = vecTy.getScalableDims();
725 if (!llvm::all_of(shape.drop_back(1), [](
auto d) { return d == 1; }))
726 return rewriter.notifyMatchFailure(storeOp,
727 "only vector<1x1x...xN> supported");
729 if (llvm::any_of(scalableDims.drop_back(1), [](
bool s) { return s; }))
730 return rewriter.notifyMatchFailure(storeOp,
731 "only innermost dim may be scalable");
733 rewriter.replaceOpWithNewOp<vector::StoreOp>(
734 storeOp, adaptor.getValueToStore(), adaptor.getBase(),
735 adaptor.getIndices());
754struct LinearizeVectorFromElements final
755 :
public OpConversionPattern<vector::FromElementsOp> {
757 LinearizeVectorFromElements(
const TypeConverter &typeConverter,
758 MLIRContext *context, PatternBenefit benefit = 1)
759 : OpConversionPattern(typeConverter, context, benefit) {}
761 matchAndRewrite(vector::FromElementsOp fromElementsOp, OpAdaptor adaptor,
762 ConversionPatternRewriter &rewriter)
const override {
764 getTypeConverter()->convertType<VectorType>(fromElementsOp.getType());
765 assert(dstTy &&
"vector type destination expected.");
767 OperandRange elements = fromElementsOp.getElements();
768 assert(elements.size() ==
static_cast<size_t>(dstTy.getNumElements()) &&
769 "expected same number of elements");
770 rewriter.replaceOpWithNewOp<vector::FromElementsOp>(fromElementsOp, dstTy,
790struct LinearizeVectorToElements final
791 :
public OpConversionPattern<vector::ToElementsOp> {
794 LinearizeVectorToElements(
const TypeConverter &typeConverter,
795 MLIRContext *context, PatternBenefit benefit = 1)
796 : OpConversionPattern(typeConverter, context, benefit) {}
799 matchAndRewrite(vector::ToElementsOp toElementsOp, OpAdaptor adaptor,
800 ConversionPatternRewriter &rewriter)
const override {
802 VectorType vecType = toElementsOp.getSource().getType();
803 if (vecType.getRank() <= 1)
804 return rewriter.notifyMatchFailure(
805 toElementsOp,
"the rank is already less than or equal to 1");
807 assert(vecType.getNumScalableDims() == 0 &&
808 "to_elements does not support scalable vectors");
810 VectorType::get({vecType.getNumElements()}, vecType.getElementType());
811 Value shapeCast = vector::ShapeCastOp::create(
812 rewriter, toElementsOp.getLoc(), vec1DType, toElementsOp.getSource());
813 auto newToElementsOp =
814 vector::ToElementsOp::create(rewriter, toElementsOp.getLoc(),
815 toElementsOp.getResultTypes(), shapeCast);
816 rewriter.replaceOp(toElementsOp, newToElementsOp);
834struct LinearizeVectorBroadcast final
835 :
public OpConversionPattern<vector::BroadcastOp> {
838 LinearizeVectorBroadcast(
const TypeConverter &typeConverter,
839 MLIRContext *context, PatternBenefit benefit = 1)
840 : OpConversionPattern(typeConverter, context, benefit) {}
843 matchAndRewrite(vector::BroadcastOp broadcastOp, OpAdaptor adaptor,
844 ConversionPatternRewriter &rewriter)
const override {
847 Type sourceType = broadcastOp.getSourceType();
848 if (
auto vecType = dyn_cast<VectorType>(sourceType)) {
849 numElements = vecType.getNumElements();
852 if (numElements != 1) {
853 return rewriter.notifyMatchFailure(
854 broadcastOp,
"only broadcasts of single elements can be linearized.");
857 auto dstTy = getTypeConverter()->convertType(broadcastOp.getType());
858 rewriter.replaceOpWithNewOp<vector::BroadcastOp>(broadcastOp, dstTy,
859 adaptor.getSource());
874struct LinearizeVectorInterleave final
875 :
public OpConversionPattern<vector::InterleaveOp> {
877 LinearizeVectorInterleave(
const TypeConverter &typeConverter,
878 MLIRContext *context, PatternBenefit benefit = 1)
879 : OpConversionPattern(typeConverter, context, benefit) {}
882 matchAndRewrite(vector::InterleaveOp op, OpAdaptor adaptor,
883 ConversionPatternRewriter &rewriter)
const override {
884 VectorType flatResultTy =
885 getTypeConverter()->convertType<VectorType>(op.getResultVectorType());
887 return rewriter.notifyMatchFailure(op,
"failed to linearize result type");
888 rewriter.replaceOpWithNewOp<vector::InterleaveOp>(
889 op, flatResultTy, adaptor.getLhs(), adaptor.getRhs());
908struct LinearizeVectorDeinterleave final
909 :
public OpConversionPattern<vector::DeinterleaveOp> {
911 LinearizeVectorDeinterleave(
const TypeConverter &typeConverter,
912 MLIRContext *context, PatternBenefit benefit = 1)
913 : OpConversionPattern(typeConverter, context, benefit) {}
916 matchAndRewrite(vector::DeinterleaveOp op, OpAdaptor adaptor,
917 ConversionPatternRewriter &rewriter)
const override {
918 if (op.getSource().getType().getShape().back() % 2)
920 auto newOp = vector::DeinterleaveOp::create(rewriter, op.getLoc(),
921 adaptor.getSource());
922 rewriter.replaceOp(op, newOp.getResults());
935 StringLiteral vectorDialect = vector::VectorDialect::getDialectNamespace();
937 bool supported = (opDialect == vectorDialect) ||
947 .Case([&](vector::ShapeCastOp) {
return false; })
957 .Case([&](vector::ExtractStridedSliceOp extractOp) {
958 return !extractOp.getType().isScalable();
960 .Case([&](vector::InsertStridedSliceOp insertOp) {
961 return !insertOp.getType().isScalable();
963 .Case([&](vector::InsertOp insertOp) {
964 return !insertOp.getType().isScalable();
966 .Case([&](vector::ExtractOp extractOp) {
967 return !extractOp.getSourceVectorType().isScalable();
969 .Default([&](
auto) {
return true; });
972void mlir::vector::populateForVectorLinearize(
TypeConverter &typeConverter,
975 auto convertType = [](
Type type) -> std::optional<Type> {
976 VectorType vectorType = dyn_cast<VectorType>(type);
980 VectorType linearizedType =
981 VectorType::get(vectorType.getNumElements(),
982 vectorType.getElementType(), vectorType.isScalable());
983 return linearizedType;
985 typeConverter.addConversion(convertType);
989 if (inputs.size() != 1)
992 Value value = inputs.front();
993 if (!isa<VectorType>(type) || !isa<VectorType>(value.
getType()))
996 return vector::ShapeCastOp::create(builder, loc, type, value);
998 typeConverter.addSourceMaterialization(materializeCast);
999 typeConverter.addTargetMaterialization(materializeCast);
1001 target.markUnknownOpDynamicallyLegal(
1002 [=](
Operation *op) -> std::optional<bool> {
1007 return typeConverter.isLegal(op);
1016 if (
auto insertOp = dyn_cast<vector::InsertOp>(op)) {
1017 unsigned w = targetBitWidth < std::numeric_limits<unsigned>::max()
1018 ? targetBitWidth + 1
1020 return {{insertOp.getValueToStoreType(), w}};
1025 resultsWithBitWidth.reserve(resultTypes.size());
1026 for (
Type type : resultTypes) {
1027 resultsWithBitWidth.push_back({type, targetBitWidth});
1029 return resultsWithBitWidth;
1041 return llvm::any_of(toCheck, [&](std::pair<Type, unsigned> typeWidth) {
1042 VectorType vecType = dyn_cast<VectorType>(typeWidth.first);
1045 if (!vecType || vecType.getRank() == 0)
1050 if (vecType.getElementType().isIndex())
1053 unsigned finalDimSize = vecType.getShape().back();
1054 unsigned nbBitsPerElm = vecType.getElementTypeBitWidth();
1055 unsigned trailingVecDimBitWidth = finalDimSize * nbBitsPerElm;
1056 return trailingVecDimBitWidth >= typeWidth.second;
1060void mlir::vector::populateVectorLinearizeBitWidthTargetRules(
1062 target.markUnknownOpDynamicallyLegal(
1063 [=](
Operation *op) -> std::optional<bool> {
1066 return std::nullopt;
1070void mlir::vector::populateVectorLinearizeBasePatterns(
1074 .
add<LinearizeConstantLike, LinearizeVectorizable, LinearizeVectorBitCast,
1075 LinearizeVectorCreateMask, LinearizeVectorLoad, LinearizeVectorStore,
1076 LinearizeVectorBroadcast, LinearizeVectorFromElements,
1077 LinearizeVectorToElements, LinearizeVectorInterleave,
1078 LinearizeVectorDeinterleave>(typeConverter, patterns.
getContext());
1081void mlir::vector::populateVectorLinearizeShuffleLikeOpsPatterns(
1084 patterns.
add<LinearizeVectorShuffle, LinearizeVectorExtract,
1085 LinearizeVectorInsert, LinearizeVectorExtractStridedSlice,
1086 LinearizeVectorInsertStridedSlice>(typeConverter,
static SmallVector< std::pair< Type, unsigned > > getTypeBitWidthBoundPairs(Operation *op, unsigned targetBitWidth)
Get the set of operand/result types to check for sufficiently small inner-most dimension size.
static FailureOr< Attribute > linearizeConstAttr(Location loc, ConversionPatternRewriter &rewriter, VectorType resType, Attribute value)
static bool hasWideInnerDim(Operation *op, unsigned targetBitWidth)
Returns true if any checked vector type of op's inner-most dimension size is equal to or exceeds targ...
static bool isLinearizable(Operation *op)
This method defines the set of operations that are linearizable, and hence that are considered illega...
Attributes are known-constant values of operations.
StringRef getNamespace() const
virtual Operation * materializeConstant(OpBuilder &builder, Attribute value, Type type, Location loc)
Registered hook to materialize a single constant operation from a given attribute value with the desi...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
This class helps build Operations.
This class provides the API for a sub-set of ops that are known to be constant-like.
Operation is the basic unit of execution within MLIR.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Location getLoc()
The source location the operation was defined or derived from.
DictionaryAttr getDiscardableAttrDictionary()
Return all of the discardable attributes on this operation as a DictionaryAttr.
result_type_range getResultTypes()
void setDiscardableAttrs(DictionaryAttr newAttrs)
Set the discardable attribute dictionary on this operation.
unsigned getNumResults()
Return the number of results held by this operation.
MLIRContext * getContext() const
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides an abstraction over the different types of ranges over Values.
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.
static ConstantIndexOp create(OpBuilder &builder, Location location, int64_t value)
bool isLinearizableVector(VectorType type)
Returns true if the input Vector type can be linearized.
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
llvm::TypeSwitch< T, ResultT > TypeSwitch
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
bool isOneInteger(OpFoldResult v)
Return true if v is an IntegerAttr with value 1.
This trait tags Elementwise operatons that can be systematically vectorized.
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.