18#include "llvm/ADT/MapVector.h"
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/Support/DebugLog.h"
21#include "llvm/Support/InterleavedRange.h"
24#define DEBUG_TYPE "vector-unroll"
34 if (
auto constExpr = dyn_cast<AffineConstantExpr>(expr))
35 return constExpr.getValue() == 0;
40 for (
const auto &dim : llvm::enumerate(permutationMap.
getResults())) {
41 int64_t elementOffset = elementOffsets[dim.index()];
42 if (isBroadcast(dim.value()) || elementOffset == 0)
44 unsigned pos = cast<AffineDimExpr>(dim.value()).getPosition();
49 affine::AffineApplyOp::create(builder, loc, map,
indices[pos]);
61 assert(offsets.size() <= originalIndices.size() &&
62 "Offsets should not exceed the number of original indices");
65 auto start =
indices.size() - offsets.size();
66 for (
auto [i, offset] : llvm::enumerate(offsets)) {
68 indices[start + i] = arith::AddIOp::create(
69 rewriter, loc, originalIndices[start + i],
85 return builder.
create(state);
90static std::optional<SmallVector<int64_t>>
93 if (
options.filterConstraint && failed(
options.filterConstraint(op))) {
94 LDBG() <<
"--no filter constraint -> BAIL";
99 auto maskableOp = dyn_cast<vector::MaskableOpInterface>(op);
100 if (maskableOp && maskableOp.isMasked()) {
101 LDBG() <<
"--op is masked -> BAIL";
105 "vector unrolling expects the native shape or native"
106 "shape call back function to be set");
107 auto unrollableVectorOp = dyn_cast<VectorUnrollOpInterface>(op);
108 if (!unrollableVectorOp) {
109 LDBG() <<
"--not an unrollable op -> BAIL";
112 auto maybeUnrollShape = unrollableVectorOp.getIterationShapeToUnroll();
113 if (!maybeUnrollShape) {
114 LDBG() <<
"--could not get shape of op " << *op <<
" -> BAIL";
117 LDBG() <<
"--vector op shape: " << llvm::interleaved(*maybeUnrollShape);
119 std::optional<SmallVector<int64_t>> targetShape =
options.nativeShape(op);
121 LDBG() <<
"--no unrolling target shape defined " << *op <<
"-> SKIP";
124 LDBG() <<
"--target shape: " << llvm::interleaved(*targetShape);
127 if (!maybeShapeRatio) {
128 LDBG() <<
"--could not compute integral shape ratio -> BAIL";
131 if (llvm::all_of(*maybeShapeRatio, [](
int64_t v) {
return v == 1; })) {
132 LDBG() <<
"--no unrolling needed -> SKIP";
135 LDBG() <<
"--found an integral shape ratio to unroll to -> SUCCESS";
143 llvm::to_vector(llvm::seq<int64_t>(0,
static_cast<int64_t>(numLoops)));
144 if (
options.traversalOrderCallback !=
nullptr) {
145 std::optional<SmallVector<int64_t>> order =
146 options.traversalOrderCallback(op);
148 loopOrder = std::move(*order);
156struct UnrollTransferReadPattern
158 UnrollTransferReadPattern(MLIRContext *context,
159 const vector::UnrollVectorOptions &options,
160 PatternBenefit benefit = 1)
161 : OpRewritePattern<vector::TransferReadOp>(context, benefit),
164 LogicalResult matchAndRewrite(vector::TransferReadOp readOp,
165 PatternRewriter &rewriter)
const override {
167 if (readOp.getTransferRank() == 0)
169 if (readOp.getMask())
174 auto sourceVectorType = readOp.getVectorType();
175 SmallVector<int64_t> strides(targetShape->size(), 1);
176 Location loc = readOp.getLoc();
177 ArrayRef<int64_t> originalSize = sourceVectorType.getShape();
181 arith::ConstantOp::create(rewriter, loc, sourceVectorType,
184 VectorType::get(*targetShape, sourceVectorType.getElementType());
185 SmallVector<Value> originalIndices(readOp.getIndices().begin(),
186 readOp.getIndices().end());
187 SmallVector<int64_t> loopOrder =
189 for (SmallVector<int64_t> elementOffsets :
190 StaticTileOffsetRange(originalSize, *targetShape, loopOrder)) {
192 sliceTransferIndices(elementOffsets, originalIndices,
193 readOp.getPermutationMap(), loc, rewriter);
194 auto slicedRead = vector::TransferReadOp::create(
195 rewriter, loc, targetType, readOp.getBase(),
indices,
196 readOp.getPermutationMapAttr(), readOp.getPadding(), readOp.getMask(),
197 readOp.getInBoundsAttr());
200 loc, slicedRead,
result, elementOffsets, strides);
207 vector::UnrollVectorOptions options;
210struct UnrollTransferWritePattern
212 UnrollTransferWritePattern(MLIRContext *context,
213 const vector::UnrollVectorOptions &options,
214 PatternBenefit benefit = 1)
215 : OpRewritePattern<vector::TransferWriteOp>(context, benefit),
218 LogicalResult matchAndRewrite(vector::TransferWriteOp writeOp,
219 PatternRewriter &rewriter)
const override {
221 if (writeOp.getTransferRank() == 0)
224 if (writeOp.getMask())
229 auto sourceVectorType = writeOp.getVectorType();
230 SmallVector<int64_t> strides(targetShape->size(), 1);
231 Location loc = writeOp.getLoc();
232 ArrayRef<int64_t> originalSize = sourceVectorType.getShape();
236 if (originalSize.size() != targetShape->size())
239 "expected source input vector rank to match target shape rank");
241 SmallVector<Value> originalIndices(writeOp.getIndices().begin(),
242 writeOp.getIndices().end());
243 SmallVector<int64_t> loopOrder =
246 for (SmallVector<int64_t> elementOffsets :
247 StaticTileOffsetRange(originalSize, *targetShape, loopOrder)) {
248 Value slicedVector = rewriter.
createOrFold<vector::ExtractStridedSliceOp>(
249 loc, writeOp.getVector(), elementOffsets, *targetShape, strides);
251 sliceTransferIndices(elementOffsets, originalIndices,
252 writeOp.getPermutationMap(), loc, rewriter);
253 Operation *slicedWrite = vector::TransferWriteOp::create(
254 rewriter, loc, slicedVector,
255 resultTensor ? resultTensor : writeOp.getBase(),
indices,
256 writeOp.getPermutationMapAttr(), writeOp.getInBoundsAttr());
259 resultTensor = slicedWrite->
getResult(0);
262 rewriter.
replaceOp(writeOp, resultTensor);
269 vector::UnrollVectorOptions options;
272struct OffsetMapInfo {
273 static unsigned getHashValue(
const SmallVector<int64_t> &v) {
274 return static_cast<unsigned>(llvm::hash_combine_range(v));
277 static bool isEqual(
const SmallVector<int64_t> &
lhs,
278 const SmallVector<int64_t> &
rhs) {
283struct UnrollContractionPattern
285 UnrollContractionPattern(MLIRContext *context,
286 const vector::UnrollVectorOptions &options,
287 PatternBenefit benefit = 1)
288 : OpRewritePattern<vector::ContractionOp>(context, benefit),
291 LogicalResult matchAndRewrite(vector::ContractionOp contractOp,
292 PatternRewriter &rewriter)
const override {
296 auto dstVecType = cast<VectorType>(contractOp.getResultType());
297 SmallVector<int64_t> originalSize = *contractOp.getIterationShapeToUnroll();
299 Location loc = contractOp.getLoc();
300 unsigned accIndex = vector::ContractionOp::getAccOperandIndex();
301 AffineMap dstAffineMap = contractOp.getIndexingMapsArray()[accIndex];
303 SmallVector<int64_t>, Value,
304 llvm::DenseMap<SmallVector<int64_t>, unsigned, OffsetMapInfo>>
308 contractOp.getIteratorTypes().size(), contractOp, options);
310 for (SmallVector<int64_t> offsets :
311 StaticTileOffsetRange(originalSize, *targetShape, loopOrder)) {
312 SmallVector<Value> slicesOperands(contractOp.getNumOperands());
315 auto extractOperand = [&](
unsigned index, Value operand,
316 AffineMap permutationMap,
317 ArrayRef<int64_t> operandOffets) {
319 permutationMap, ArrayRef<int64_t>(*targetShape));
320 SmallVector<int64_t> operandStrides(operandOffets.size(), 1);
321 slicesOperands[index] =
323 loc, operand, operandOffets, operandShape, operandStrides);
327 AffineMap lhsPermutationMap = contractOp.getIndexingMapsArray()[0];
328 SmallVector<int64_t> lhsOffets =
330 extractOperand(0, contractOp.getLhs(), lhsPermutationMap, lhsOffets);
333 AffineMap rhsPermutationMap = contractOp.getIndexingMapsArray()[1];
334 SmallVector<int64_t> rhsOffets =
336 extractOperand(1, contractOp.getRhs(), rhsPermutationMap, rhsOffets);
338 AffineMap accPermutationMap = contractOp.getIndexingMapsArray()[2];
339 SmallVector<int64_t> accOffets =
343 auto *accIt = accCache.find(accOffets);
344 if (accIt != accCache.end())
345 slicesOperands[2] = accIt->second;
347 extractOperand(2, contractOp.getAcc(), accPermutationMap, accOffets);
349 SmallVector<int64_t> dstShape =
351 auto targetType = VectorType::get(dstShape, dstVecType.getElementType());
353 rewriter, loc, contractOp, slicesOperands, targetType);
355 SmallVector<int64_t> dstOffets =
359 accCache[dstOffets] = newOp->
getResult(0);
362 Value
result = arith::ConstantOp::create(rewriter, loc, dstVecType,
364 for (
const auto &it : accCache) {
365 SmallVector<int64_t> dstStrides(it.first.size(), 1);
367 loc, it.second,
result, it.first, dstStrides);
374 vector::UnrollVectorOptions options;
377struct UnrollMultiReductionPattern
379 UnrollMultiReductionPattern(MLIRContext *context,
380 const vector::UnrollVectorOptions &options,
381 PatternBenefit benefit = 1)
382 : OpRewritePattern<vector::MultiDimReductionOp>(context, benefit),
385 LogicalResult matchAndRewrite(vector::MultiDimReductionOp reductionOp,
386 PatternRewriter &rewriter)
const override {
387 std::optional<SmallVector<int64_t>> targetShape =
391 SmallVector<int64_t> originalSize =
392 *reductionOp.getIterationShapeToUnroll();
393 Location loc = reductionOp.getLoc();
394 auto resultType = reductionOp->getResult(0).getType();
399 SmallVector<int64_t> adjustedTargetShape(originalSize.size(), 1);
400 llvm::copy(*targetShape, adjustedTargetShape.end() - targetShape->size());
405 if (resultType.isIntOrFloat()) {
406 Value accumulator = reductionOp.getAcc();
407 for (SmallVector<int64_t> offsets :
408 StaticTileOffsetRange(originalSize, adjustedTargetShape)) {
409 SmallVector<int64_t> operandStrides(offsets.size(), 1);
410 Value slicedOperand =
412 loc, reductionOp.getSource(), offsets, adjustedTargetShape,
415 rewriter, loc, reductionOp, {slicedOperand, accumulator},
419 rewriter.
replaceOp(reductionOp, accumulator);
425 SmallVector<int64_t>, Value,
426 llvm::DenseMap<SmallVector<int64_t>, unsigned, OffsetMapInfo>>
431 for (SmallVector<int64_t> offsets :
432 StaticTileOffsetRange(originalSize, adjustedTargetShape)) {
433 SmallVector<Value> operands;
434 SmallVector<int64_t> operandStrides(offsets.size(), 1);
435 Value slicedOperand =
437 loc, reductionOp.getSource(), offsets, adjustedTargetShape,
439 operands.push_back(slicedOperand);
440 SmallVector<int64_t> dstShape;
441 SmallVector<int64_t> destOffset;
442 for (
size_t i : llvm::seq(
size_t(0), adjustedTargetShape.size())) {
443 if (!reductionOp.isReducedDim(i)) {
444 destOffset.push_back(offsets[i]);
445 dstShape.push_back(adjustedTargetShape[i]);
449 SmallVector<int64_t> accStrides(destOffset.size(), 1);
452 auto *accIt = accCache.find(destOffset);
453 if (accIt != accCache.end())
456 acc = rewriter.
createOrFold<vector::ExtractStridedSliceOp>(
457 loc, reductionOp.getAcc(), destOffset, dstShape, accStrides);
458 operands.push_back(acc);
459 auto targetType = VectorType::get(
460 dstShape, reductionOp.getSourceVectorType().getElementType());
462 operands, targetType);
464 accCache[destOffset] =
result;
467 Value
result = arith::ConstantOp::create(
468 rewriter, loc, reductionOp.getDestType(),
470 for (
const auto &it : accCache) {
471 SmallVector<int64_t> dstStrides(it.first.size(), 1);
473 loc, it.second,
result, it.first, dstStrides);
480 vector::UnrollVectorOptions options;
484 UnrollElementwisePattern(MLIRContext *context,
485 const vector::UnrollVectorOptions &options,
486 PatternBenefit benefit = 1)
487 : RewritePattern(MatchAnyOpTypeTag(), benefit, context),
490 LogicalResult matchAndRewrite(Operation *op,
491 PatternRewriter &rewriter)
const override {
497 int64_t targetShapeRank = targetShape->size();
499 SmallVector<int64_t> originalSize =
500 *cast<VectorUnrollOpInterface>(op).getIterationShapeToUnroll();
501 int64_t originalShapeRank = originalSize.size();
503 Location loc = op->
getLoc();
506 SmallVector<int64_t> adjustedTargetShape(originalShapeRank);
507 int64_t rankDiff = originalShapeRank - targetShapeRank;
508 std::fill(adjustedTargetShape.begin(),
509 adjustedTargetShape.begin() + rankDiff, 1);
510 std::copy(targetShape->begin(), targetShape->end(),
511 adjustedTargetShape.begin() + rankDiff);
513 int64_t adjustedTargetShapeRank = adjustedTargetShape.size();
515 Value
result = arith::ConstantOp::create(rewriter, loc, dstVecType,
517 SmallVector<int64_t> strides(adjustedTargetShapeRank, 1);
518 VectorType unrolledVecType =
519 VectorType::get(*targetShape, dstVecType.getElementType());
522 for (SmallVector<int64_t> offsets :
523 StaticTileOffsetRange(originalSize, adjustedTargetShape)) {
524 SmallVector<Value> extractOperands;
526 auto vecType = dyn_cast<VectorType>(operand.get().getType());
528 extractOperands.push_back(operand.get());
531 Value extracted = rewriter.
createOrFold<vector::ExtractStridedSliceOp>(
532 loc, operand.get(), offsets, adjustedTargetShape, strides);
535 if (adjustedTargetShapeRank > targetShapeRank) {
537 loc, VectorType::get(*targetShape, vecType.getElementType()),
540 extractOperands.push_back(extracted);
544 rewriter, loc, op, extractOperands, unrolledVecType);
546 Value computeResult = newOp->
getResult(0);
549 SmallVector<int64_t> insertStrides =
550 (adjustedTargetShapeRank > targetShapeRank)
551 ? SmallVector<int64_t>(targetShapeRank, 1)
555 loc, computeResult,
result, offsets, insertStrides);
562 vector::UnrollVectorOptions options;
565struct UnrollReductionPattern :
public OpRewritePattern<vector::ReductionOp> {
566 UnrollReductionPattern(MLIRContext *context,
567 const vector::UnrollVectorOptions &options,
568 PatternBenefit benefit = 1)
569 : OpRewritePattern<vector::ReductionOp>(context, benefit),
572 LogicalResult matchAndRewrite(vector::ReductionOp reductionOp,
573 PatternRewriter &rewriter)
const override {
574 std::optional<SmallVector<int64_t>> targetShape =
578 SmallVector<int64_t> originalSize =
579 *reductionOp.getIterationShapeToUnroll();
582 Location loc = reductionOp.getLoc();
583 Value accumulator =
nullptr;
584 for (SmallVector<int64_t> offsets :
585 StaticTileOffsetRange(originalSize, *targetShape)) {
586 SmallVector<int64_t> strides(offsets.size(), 1);
587 Value slicedOperand =
589 loc, reductionOp.getVector(), offsets, *targetShape, strides);
591 rewriter, loc, reductionOp, slicedOperand, reductionOp.getType());
604 rewriter.
replaceOp(reductionOp, accumulator);
609 const vector::UnrollVectorOptions options;
612struct UnrollTransposePattern :
public OpRewritePattern<vector::TransposeOp> {
613 UnrollTransposePattern(MLIRContext *context,
614 const vector::UnrollVectorOptions &options,
615 PatternBenefit benefit = 1)
616 : OpRewritePattern<vector::TransposeOp>(context, benefit),
619 LogicalResult matchAndRewrite(vector::TransposeOp transposeOp,
620 PatternRewriter &rewriter)
const override {
621 if (transposeOp.getResultVectorType().getRank() == 0)
626 auto originalVectorType = transposeOp.getResultVectorType();
627 SmallVector<int64_t> strides(targetShape->size(), 1);
628 Location loc = transposeOp.getLoc();
629 ArrayRef<int64_t> originalSize = originalVectorType.getShape();
633 arith::ConstantOp::create(rewriter, loc, originalVectorType,
635 ArrayRef<int64_t> permutation = transposeOp.getPermutation();
638 for (SmallVector<int64_t> elementOffsets :
639 StaticTileOffsetRange(originalSize, *targetShape)) {
640 SmallVector<int64_t> permutedOffsets(elementOffsets.size());
641 SmallVector<int64_t> permutedShape(elementOffsets.size());
643 for (
auto indices : llvm::enumerate(permutation)) {
644 permutedOffsets[
indices.value()] = elementOffsets[
indices.index()];
647 Value slicedOperand =
649 loc, transposeOp.getVector(), permutedOffsets, permutedShape,
651 Value transposedSlice = rewriter.
createOrFold<vector::TransposeOp>(
652 loc, slicedOperand, permutation);
654 loc, transposedSlice,
result, elementOffsets, strides);
661 vector::UnrollVectorOptions options;
665 UnrollGatherPattern(MLIRContext *context,
666 const vector::UnrollVectorOptions &options,
667 PatternBenefit benefit = 1)
668 : OpRewritePattern<vector::GatherOp>(context, benefit), options(options) {
671 LogicalResult matchAndRewrite(vector::GatherOp gatherOp,
672 PatternRewriter &rewriter)
const override {
673 VectorType sourceVectorType = gatherOp.getVectorType();
674 if (sourceVectorType.getRank() == 0)
679 SmallVector<int64_t> strides(targetShape->size(), 1);
680 Location loc = gatherOp.getLoc();
681 ArrayRef<int64_t> originalSize = gatherOp.getVectorType().getShape();
685 arith::ConstantOp::create(rewriter, loc, sourceVectorType,
688 VectorType::get(*targetShape, sourceVectorType.getElementType());
690 SmallVector<int64_t> loopOrder =
692 for (SmallVector<int64_t> elementOffsets :
693 StaticTileOffsetRange(originalSize, *targetShape, loopOrder)) {
697 Value indexSubVec = rewriter.
createOrFold<vector::ExtractStridedSliceOp>(
698 loc, gatherOp.getIndices(), elementOffsets, *targetShape, strides);
699 Value maskSubVec = rewriter.
createOrFold<vector::ExtractStridedSliceOp>(
700 loc, gatherOp.getMask(), elementOffsets, *targetShape, strides);
701 Value passThruSubVec =
703 loc, gatherOp.getPassThru(), elementOffsets, *targetShape,
705 auto slicedGather = vector::GatherOp::create(
706 rewriter, loc, targetType, gatherOp.getBase(), gatherOp.getOffsets(),
707 indexSubVec, maskSubVec, passThruSubVec);
710 loc, slicedGather,
result, elementOffsets, strides);
717 vector::UnrollVectorOptions options;
721 UnrollLoadPattern(MLIRContext *context,
722 const vector::UnrollVectorOptions &options,
723 PatternBenefit benefit = 1)
724 : OpRewritePattern<vector::LoadOp>(context, benefit), options(options) {}
726 LogicalResult matchAndRewrite(vector::LoadOp loadOp,
727 PatternRewriter &rewriter)
const override {
728 VectorType vecType = loadOp.getVectorType();
734 Location loc = loadOp.getLoc();
735 ArrayRef<int64_t> originalShape = vecType.getShape();
736 SmallVector<int64_t> strides(targetShape->size(), 1);
738 Value
result = arith::ConstantOp::create(rewriter, loc, vecType,
741 SmallVector<int64_t> loopOrder =
745 VectorType::get(*targetShape, vecType.getElementType());
747 for (SmallVector<int64_t> offsets :
748 StaticTileOffsetRange(originalShape, *targetShape, loopOrder)) {
751 Value slicedLoad = vector::LoadOp::create(rewriter, loc, targetVecType,
754 loc, slicedLoad,
result, offsets, strides);
761 vector::UnrollVectorOptions options;
765 UnrollStorePattern(MLIRContext *context,
766 const vector::UnrollVectorOptions &options,
767 PatternBenefit benefit = 1)
768 : OpRewritePattern<vector::StoreOp>(context, benefit), options(options) {}
770 LogicalResult matchAndRewrite(vector::StoreOp storeOp,
771 PatternRewriter &rewriter)
const override {
772 VectorType vecType = storeOp.getVectorType();
778 Location loc = storeOp.getLoc();
779 ArrayRef<int64_t> originalShape = vecType.getShape();
780 SmallVector<int64_t> strides(targetShape->size(), 1);
782 Value base = storeOp.getBase();
783 Value vector = storeOp.getValueToStore();
785 SmallVector<int64_t> loopOrder =
788 for (SmallVector<int64_t> offsets :
789 StaticTileOffsetRange(originalShape, *targetShape, loopOrder)) {
793 loc, vector, offsets, *targetShape, strides);
794 vector::StoreOp::create(rewriter, loc,
slice, base,
indices);
801 vector::UnrollVectorOptions options;
804struct UnrollBroadcastPattern :
public OpRewritePattern<vector::BroadcastOp> {
805 UnrollBroadcastPattern(MLIRContext *context,
806 const vector::UnrollVectorOptions &options,
807 PatternBenefit benefit = 1)
808 : OpRewritePattern<vector::BroadcastOp>(context, benefit),
811 LogicalResult matchAndRewrite(vector::BroadcastOp broadcastOp,
812 PatternRewriter &rewriter)
const override {
817 Location loc = broadcastOp.getLoc();
818 VectorType srcType = dyn_cast<VectorType>(broadcastOp.getSourceType());
819 VectorType resType = broadcastOp.getResultVectorType();
821 SmallVector<int64_t> originalShape =
822 *broadcastOp.getIterationShapeToUnroll();
825 SmallVector<int64_t> adjustedTargetShape(originalShape.size(), 1);
826 llvm::copy(*targetShape, adjustedTargetShape.end() - targetShape->size());
828 VectorType targetType =
829 resType.cloneWith(adjustedTargetShape, resType.getElementType());
830 Value
result = arith::ConstantOp::create(rewriter, loc, resType,
833 SmallVector<int64_t> strides(originalShape.size(), 1);
835 for (SmallVector<int64_t> offsets :
836 StaticTileOffsetRange(originalShape, adjustedTargetShape)) {
840 newSrc = broadcastOp.getSource();
843 int64_t rank = srcType.getRank();
844 SmallVector<int64_t> srcOffsets(offsets.end() - rank, offsets.end());
845 SmallVector<int64_t> srcShape(adjustedTargetShape.end() - rank,
846 adjustedTargetShape.end());
847 SmallVector<int64_t> srcStrides(strides.end() - rank, strides.end());
849 for (int64_t i = 0; i < rank; ++i) {
850 if (srcType.getDimSize(i) == 1) {
855 newSrc = rewriter.
createOrFold<vector::ExtractStridedSliceOp>(
856 loc, broadcastOp.getSource(), srcOffsets, srcShape, srcStrides);
871 vector::UnrollVectorOptions options;
891struct UnrollToElements final :
public OpRewritePattern<vector::ToElementsOp> {
892 UnrollToElements(MLIRContext *context,
893 const vector::UnrollVectorOptions &options,
894 PatternBenefit benefit = 1)
895 : OpRewritePattern<vector::ToElementsOp>(context, benefit),
898 LogicalResult matchAndRewrite(vector::ToElementsOp op,
899 PatternRewriter &rewriter)
const override {
902 FailureOr<SmallVector<Value>>
result =
907 SmallVector<Value> vectors = *
result;
909 SmallVector<Value> results;
910 for (Value vector : vectors) {
912 vector::ToElementsOp::create(rewriter, op.getLoc(), vector);
913 llvm::append_range(results, subElements.getResults());
920 vector::UnrollVectorOptions options;
950 UnrollStepPattern(MLIRContext *context,
951 const vector::UnrollVectorOptions &options,
952 PatternBenefit benefit = 1)
953 : OpRewritePattern<vector::StepOp>(context, benefit), options(options) {}
955 LogicalResult matchAndRewrite(vector::StepOp stepOp,
956 PatternRewriter &rewriter)
const override {
957 std::optional<SmallVector<int64_t>> targetShape =
962 VectorType vecType = stepOp.getType();
963 if (vecType.isScalable()) {
967 int64_t originalSize = vecType.getShape()[0];
968 Location loc = stepOp.getLoc();
969 SmallVector<int64_t> strides(1, 1);
971 Value
result = arith::ConstantOp::create(rewriter, loc, vecType,
975 VectorType::get(*targetShape, vecType.getElementType());
976 Value baseStep = vector::StepOp::create(rewriter, loc, targetVecType);
977 for (
const SmallVector<int64_t> &offsets :
978 StaticTileOffsetRange({originalSize}, *targetShape)) {
979 Value bcastOffset = arith::ConstantOp::create(
980 rewriter, loc, targetVecType,
983 IntegerAttr::get(targetVecType.getElementType(), offsets[0])));
985 arith::AddIOp::create(rewriter, loc, baseStep, bcastOffset);
988 loc, tileStep,
result, offsets, strides);
995 vector::UnrollVectorOptions options;
1016 UnrollFromElements(MLIRContext *context,
1017 const vector::UnrollVectorOptions &options,
1018 PatternBenefit benefit = 1)
1019 : OpRewritePattern<vector::FromElementsOp>(context, benefit),
1022 LogicalResult matchAndRewrite(vector::FromElementsOp op,
1023 PatternRewriter &rewriter)
const override {
1026 auto unrollFromElementsFn = [&](PatternRewriter &rewriter, Location loc,
1027 VectorType subTy, int64_t index) {
1028 size_t subTyNumElements = subTy.getNumElements();
1029 assert((index + 1) * subTyNumElements <= allElements.size() &&
1032 allElements.slice(index * subTyNumElements, subTyNumElements);
1033 return vector::FromElementsOp::create(rewriter, loc, subTy, subElements);
1040 vector::UnrollVectorOptions options;
1076struct UnrollCreateMaskPattern :
public OpRewritePattern<vector::CreateMaskOp> {
1077 UnrollCreateMaskPattern(MLIRContext *context,
1078 const vector::UnrollVectorOptions &options,
1079 PatternBenefit benefit = 1)
1080 : OpRewritePattern<vector::CreateMaskOp>(context, benefit),
1083 LogicalResult matchAndRewrite(vector::CreateMaskOp createMaskOp,
1084 PatternRewriter &rewriter)
const override {
1089 VectorType resultType = createMaskOp.getVectorType();
1090 SmallVector<int64_t> originalSize =
1091 *createMaskOp.getIterationShapeToUnroll();
1092 Location loc = createMaskOp.getLoc();
1096 SmallVector<int64_t> adjustedTargetShape(originalSize.size(), 1);
1097 llvm::copy(*targetShape, adjustedTargetShape.end() - targetShape->size());
1099 Value
result = arith::ConstantOp::create(rewriter, loc, resultType,
1101 VectorType targetVectorType =
1102 VectorType::get(adjustedTargetShape, rewriter.
getI1Type());
1103 SmallVector<int64_t> strides(adjustedTargetShape.size(), 1);
1107 for (SmallVector<int64_t> offsets :
1108 StaticTileOffsetRange(originalSize, adjustedTargetShape)) {
1109 SmallVector<Value> unrolledOperands;
1111 for (
auto [i, originalMaskOperand] :
1112 llvm::enumerate(createMaskOp.getOperands())) {
1115 Value adjustedMaskSize = rewriter.
createOrFold<arith::SubIOp>(
1116 loc, originalMaskOperand, offsetVal);
1119 rewriter, loc, adjustedTargetShape[i]);
1121 rewriter.
createOrFold<arith::MaxSIOp>(loc, adjustedMaskSize, zero);
1122 Value unrolledOperand = rewriter.
createOrFold<arith::MinSIOp>(
1123 loc, nonNegative, unrolledDimSize);
1124 unrolledOperands.push_back(unrolledOperand);
1127 auto unrolledMask = rewriter.
createOrFold<vector::CreateMaskOp>(
1128 loc, targetVectorType, unrolledOperands);
1130 loc, unrolledMask,
result, offsets, strides);
1137 vector::UnrollVectorOptions options;
1172struct UnrollConstantMaskPattern
1174 UnrollConstantMaskPattern(MLIRContext *context,
1175 const vector::UnrollVectorOptions &options,
1176 PatternBenefit benefit = 1)
1177 : OpRewritePattern<vector::ConstantMaskOp>(context, benefit),
1180 LogicalResult matchAndRewrite(vector::ConstantMaskOp constantMaskOp,
1181 PatternRewriter &rewriter)
const override {
1182 std::optional<SmallVector<int64_t>> targetShape =
1187 VectorType resultType = constantMaskOp.getVectorType();
1188 SmallVector<int64_t> originalSize =
1189 *constantMaskOp.getIterationShapeToUnroll();
1190 Location loc = constantMaskOp.getLoc();
1194 SmallVector<int64_t> adjustedTargetShape(originalSize.size(), 1);
1195 llvm::copy(*targetShape, adjustedTargetShape.end() - targetShape->size());
1197 Value
result = arith::ConstantOp::create(rewriter, loc, resultType,
1199 VectorType targetVectorType =
1200 VectorType::get(adjustedTargetShape, rewriter.
getI1Type());
1201 SmallVector<int64_t> strides(adjustedTargetShape.size(), 1);
1205 for (
const SmallVector<int64_t> &offsets :
1206 StaticTileOffsetRange(originalSize, adjustedTargetShape)) {
1207 SmallVector<int64_t> unrolledMaskDims;
1209 for (
auto [i, originalMaskDim] :
1210 llvm::enumerate(constantMaskOp.getMaskDimSizes())) {
1213 int64_t adjustedMaskSize =
1214 std::max(originalMaskDim - offsets[i],
static_cast<int64_t
>(0));
1215 int64_t unrolledMaskDim =
1216 std::min(adjustedMaskSize, adjustedTargetShape[i]);
1217 unrolledMaskDims.push_back(unrolledMaskDim);
1223 if (llvm::is_contained(unrolledMaskDims, 0))
1224 unrolledMaskDims.assign(unrolledMaskDims.size(), 0);
1226 auto unrolledMask = rewriter.
createOrFold<vector::ConstantMaskOp>(
1227 loc, targetVectorType, unrolledMaskDims);
1229 loc, unrolledMask,
result, offsets, strides);
1236 vector::UnrollVectorOptions options;
1254 if (extractShape.empty() ||
shape.empty() ||
1255 extractShape.size() >
shape.size())
1258 while (extractShape.size() > 1 && extractShape.front() == 1)
1259 extractShape = extractShape.drop_front();
1261 while (
shape.size() > 1 &&
shape.front() == 1) {
1265 size_t rankDiff =
shape.size() - extractShape.size();
1266 if (!llvm::equal(extractShape.drop_front(),
shape.drop_front(rankDiff + 1)))
1269 int64_t extractElements = ShapedType::getNumElements(extractShape);
1270 int64_t shapeElements = ShapedType::getNumElements(
shape);
1271 return shapeElements % extractElements == 0;
1293static std::optional<SmallVector<int64_t>>
1297 int64_t remainingElements = targetElements;
1300 for (
int i = sourceShape.size() - 1; i >= 0 && remainingElements > 1; --i) {
1301 int64_t takeFromDim = std::min(remainingElements, sourceShape[i]);
1302 extractShape.insert(extractShape.begin(), takeFromDim);
1304 if (remainingElements % takeFromDim != 0)
1305 return std::nullopt;
1306 remainingElements /= takeFromDim;
1310 while (extractShape.size() < sourceShape.size())
1311 extractShape.insert(extractShape.begin(), 1);
1313 if (ShapedType::getNumElements(extractShape) != targetElements)
1314 return std::nullopt;
1316 return extractShape;
1332struct ShapeCastReassociationGroup {
1333 int64_t srcBegin, srcEnd;
1334 int64_t resBegin, resEnd;
1340static std::optional<SmallVector<ShapeCastReassociationGroup>>
1345 int64_t srcRank = sourceShape.size(), resRank = resultShape.size();
1346 while (si < srcRank && ri < resRank) {
1347 int64_t srcBegin = si, resBegin = ri;
1348 int64_t srcProd = sourceShape[si++];
1349 int64_t resProd = resultShape[ri++];
1351 while (srcProd != resProd) {
1352 if (srcProd < resProd) {
1354 return std::nullopt;
1355 srcProd *= sourceShape[si++];
1358 return std::nullopt;
1359 resProd *= resultShape[ri++];
1363 while (si < srcRank && sourceShape[si] == 1)
1365 while (ri < resRank && resultShape[ri] == 1)
1367 groups.push_back({srcBegin, si, resBegin, ri});
1369 if (si != srcRank || ri != resRank)
1370 return std::nullopt;
1421struct UnrollShapeCastPattern :
public OpRewritePattern<vector::ShapeCastOp> {
1422 UnrollShapeCastPattern(MLIRContext *context,
1423 const vector::UnrollVectorOptions &options,
1424 PatternBenefit benefit = 1)
1425 : OpRewritePattern<vector::ShapeCastOp>(context, benefit),
1428 LogicalResult matchAndRewrite(vector::ShapeCastOp shapeCastOp,
1429 PatternRewriter &rewriter)
const override {
1430 std::optional<SmallVector<int64_t>> targetShape =
1435 VectorType sourceType = shapeCastOp.getSourceVectorType();
1436 VectorType resultType = shapeCastOp.getResultVectorType();
1437 ArrayRef<int64_t> sourceShape = sourceType.getShape();
1438 ArrayRef<int64_t> resultShape = resultType.getShape();
1442 std::optional<SmallVector<ShapeCastReassociationGroup>> groups =
1443 computeShapeCastGroups(sourceShape, resultShape);
1446 shapeCastOp,
"cannot align source and result reassociation groups");
1450 SmallVector<int64_t> paddedTarget(resultShape.size(), 1);
1451 llvm::copy(*targetShape,
1452 paddedTarget.end() -
static_cast<int64_t
>(targetShape->size()));
1455 SmallVector<int64_t> extractShapeStorage;
1456 for (
const ShapeCastReassociationGroup &g : *groups) {
1457 ArrayRef<int64_t> resSub =
1458 resultShape.slice(g.resBegin, g.resEnd - g.resBegin);
1459 ArrayRef<int64_t> tgtSub = ArrayRef<int64_t>(paddedTarget)
1460 .slice(g.resBegin, g.resEnd - g.resBegin);
1461 if (!isContiguous(tgtSub, resSub))
1463 shapeCastOp,
"target shape is not contiguous within a "
1464 "reassociation group of the result vector shape");
1466 ArrayRef<int64_t> srcSub =
1467 sourceShape.slice(g.srcBegin, g.srcEnd - g.srcBegin);
1468 int64_t groupTargetElements = ShapedType::getNumElements(tgtSub);
1469 std::optional<SmallVector<int64_t>> groupExtract =
1470 calculateSourceExtractShape(srcSub, groupTargetElements);
1473 shapeCastOp,
"cannot extract the target number of elements "
1474 "contiguously from a source reassociation group");
1475 extractShapeStorage.append(groupExtract->begin(), groupExtract->end());
1477 ArrayRef<int64_t> extractShape = extractShapeStorage;
1479 Location loc = shapeCastOp.getLoc();
1482 Value
result = arith::ConstantOp::create(rewriter, loc, resultType,
1485 VectorType targetType =
1486 VectorType::get(*targetShape, sourceType.getElementType());
1489 SmallVector<int64_t> insertStrides(targetShape->size(), 1);
1491 for (SmallVector<int64_t> resultOffsets :
1492 StaticTileOffsetRange(resultShape, *targetShape)) {
1493 SmallVector<int64_t> sourceOffsets =
1494 calculateSourceOffsets(resultOffsets, sourceShape, resultShape);
1495 Value sourceChunk = rewriter.
createOrFold<vector::ExtractStridedSliceOp>(
1496 loc, shapeCastOp.getSource(), sourceOffsets, extractShape,
1498 Value targetChunk = rewriter.
createOrFold<vector::ShapeCastOp>(
1499 loc, targetType, sourceChunk);
1501 loc, targetChunk,
result, resultOffsets, insertStrides);
1509 vector::UnrollVectorOptions options;
1527 UnrollBitCastPattern(MLIRContext *context,
1528 const vector::UnrollVectorOptions &options,
1529 PatternBenefit benefit = 1)
1530 : OpRewritePattern<vector::BitCastOp>(context, benefit),
1533 LogicalResult matchAndRewrite(vector::BitCastOp bitCastOp,
1534 PatternRewriter &rewriter)
const override {
1538 "failed to get target shape");
1540 VectorType sourceType = bitCastOp.getSourceVectorType();
1541 VectorType resultType = bitCastOp.getResultVectorType();
1542 ArrayRef<int64_t> resultShape = resultType.getShape();
1543 Location loc = bitCastOp.getLoc();
1545 if (targetShape->size() != resultShape.size())
1547 bitCastOp,
"target shape rank must match result rank");
1549 unsigned sourceElementBits = sourceType.getElementTypeBitWidth();
1550 unsigned resultElementBits = resultType.getElementTypeBitWidth();
1552 SmallVector<int64_t> sourceSliceShape(targetShape->begin(),
1553 targetShape->end());
1554 int64_t lastDim = sourceSliceShape.size() - 1;
1556 sourceSliceShape[lastDim] =
1557 ((*targetShape)[lastDim] * resultElementBits) / sourceElementBits;
1559 Value
result = arith::ConstantOp::create(rewriter, loc, resultType,
1561 SmallVector<int64_t> resultStrides(targetShape->size(), 1);
1562 SmallVector<int64_t> sourceStrides(sourceSliceShape.size(), 1);
1564 VectorType targetType =
1565 VectorType::get(*targetShape, resultType.getElementType());
1567 for (SmallVector<int64_t> resultOffsets :
1568 StaticTileOffsetRange(resultShape, *targetShape)) {
1569 SmallVector<int64_t> sourceOffsets = resultOffsets;
1570 sourceOffsets[lastDim] =
1571 (resultOffsets[lastDim] * resultElementBits) / sourceElementBits;
1573 Value sourceSlice = rewriter.
createOrFold<vector::ExtractStridedSliceOp>(
1574 loc, bitCastOp.getSource(), sourceOffsets, sourceSliceShape,
1576 Value bitcastSlice = rewriter.
createOrFold<vector::BitCastOp>(
1577 loc, targetType, sourceSlice);
1579 loc, bitcastSlice,
result, resultOffsets, resultStrides);
1587 vector::UnrollVectorOptions options;
1607struct UnrollInterleavePattern :
public OpRewritePattern<vector::InterleaveOp> {
1608 UnrollInterleavePattern(MLIRContext *context,
1609 const vector::UnrollVectorOptions &options,
1610 PatternBenefit benefit = 1)
1611 : OpRewritePattern<vector::InterleaveOp>(context, benefit),
1614 LogicalResult matchAndRewrite(vector::InterleaveOp interleaveOp,
1615 PatternRewriter &rewriter)
const override {
1619 "failed to get target shape");
1621 VectorType resultType = interleaveOp.getResultVectorType();
1622 ArrayRef<int64_t> resultShape = resultType.getShape();
1623 Location loc = interleaveOp.getLoc();
1625 if (targetShape->size() != resultShape.size())
1627 interleaveOp,
"target shape rank must match result rank");
1629 SmallVector<int64_t> sourceSliceShape(targetShape->begin(),
1630 targetShape->end());
1631 int64_t lastDim = sourceSliceShape.size() - 1;
1632 sourceSliceShape[lastDim] = (*targetShape)[lastDim] / 2;
1634 Value
result = arith::ConstantOp::create(rewriter, loc, resultType,
1636 SmallVector<int64_t> resultStrides(targetShape->size(), 1);
1637 SmallVector<int64_t> sourceStrides(sourceSliceShape.size(), 1);
1639 VectorType targetType =
1640 VectorType::get(*targetShape, resultType.getElementType());
1642 for (SmallVector<int64_t> resultOffsets :
1643 StaticTileOffsetRange(resultShape, *targetShape)) {
1644 SmallVector<int64_t> sourceOffsets = resultOffsets;
1645 sourceOffsets[lastDim] = resultOffsets[lastDim] / 2;
1647 Value lhsSlice = rewriter.
createOrFold<vector::ExtractStridedSliceOp>(
1648 loc, interleaveOp.getLhs(), sourceOffsets, sourceSliceShape,
1650 Value rhsSlice = rewriter.
createOrFold<vector::ExtractStridedSliceOp>(
1651 loc, interleaveOp.getRhs(), sourceOffsets, sourceSliceShape,
1653 Value interleaveSlice = rewriter.
createOrFold<vector::InterleaveOp>(
1654 loc, targetType, lhsSlice, rhsSlice);
1656 loc, interleaveSlice,
result, resultOffsets, resultStrides);
1664 vector::UnrollVectorOptions options;
1685struct UnrollDeinterleavePattern
1687 UnrollDeinterleavePattern(MLIRContext *context,
1688 const vector::UnrollVectorOptions &options,
1689 PatternBenefit benefit = 1)
1690 : OpRewritePattern<vector::DeinterleaveOp>(context, benefit),
1693 LogicalResult matchAndRewrite(vector::DeinterleaveOp deinterleaveOp,
1694 PatternRewriter &rewriter)
const override {
1698 "failed to get target shape");
1700 VectorType resultType = deinterleaveOp.getResultVectorType();
1701 ArrayRef<int64_t> resultShape = resultType.getShape();
1702 Location loc = deinterleaveOp.getLoc();
1704 if (targetShape->size() != resultShape.size())
1706 deinterleaveOp,
"target shape rank must match result rank");
1708 SmallVector<int64_t> sourceSliceShape(targetShape->begin(),
1709 targetShape->end());
1710 int64_t lastDim = sourceSliceShape.size() - 1;
1711 sourceSliceShape[lastDim] = (*targetShape)[lastDim] * 2;
1713 Value resultOdd = arith::ConstantOp::create(
1714 rewriter, loc, resultType, rewriter.
getZeroAttr(resultType));
1715 Value resultEven = arith::ConstantOp::create(
1716 rewriter, loc, resultType, rewriter.
getZeroAttr(resultType));
1717 SmallVector<int64_t> resultStrides(targetShape->size(), 1);
1718 SmallVector<int64_t> sourceStrides(sourceSliceShape.size(), 1);
1720 for (SmallVector<int64_t> resultOffsets :
1721 StaticTileOffsetRange(resultShape, *targetShape)) {
1722 SmallVector<int64_t> sourceOffsets = resultOffsets;
1723 sourceOffsets[lastDim] = resultOffsets[lastDim] * 2;
1725 Value sourceSlice = rewriter.
createOrFold<vector::ExtractStridedSliceOp>(
1726 loc, deinterleaveOp.getSource(), sourceOffsets, sourceSliceShape,
1729 auto deinterleaveSlice =
1730 vector::DeinterleaveOp::create(rewriter, loc, sourceSlice);
1732 resultOdd = rewriter.
createOrFold<vector::InsertStridedSliceOp>(
1733 loc, deinterleaveSlice.getResultEven(), resultOdd, resultOffsets,
1735 resultEven = rewriter.
createOrFold<vector::InsertStridedSliceOp>(
1736 loc, deinterleaveSlice.getResultOdd(), resultEven, resultOffsets,
1745 vector::UnrollVectorOptions options;
1750void mlir::vector::populateVectorUnrollPatterns(
1753 patterns.
add<UnrollTransferReadPattern, UnrollTransferWritePattern,
1754 UnrollContractionPattern, UnrollElementwisePattern,
1755 UnrollReductionPattern, UnrollMultiReductionPattern,
1756 UnrollTransposePattern, UnrollGatherPattern, UnrollLoadPattern,
1757 UnrollStorePattern, UnrollBroadcastPattern, UnrollFromElements,
1758 UnrollToElements, UnrollStepPattern, UnrollShapeCastPattern,
1759 UnrollCreateMaskPattern, UnrollConstantMaskPattern,
1760 UnrollBitCastPattern, UnrollInterleavePattern,
1765void mlir::vector::populateVectorContractUnrollPatterns(
1772void mlir::vector::populateVectorToElementsUnrollPatterns(
1778void mlir::vector::populateVectorFromElementsUnrollPatterns(
static LogicalResult extractStrides(AffineExpr e, AffineExpr multiplicativeFactor, MutableArrayRef< AffineExpr > strides, AffineExpr &offset)
Takes a single AffineExpr e and populates the strides array with the strides expressions for each dim...
static llvm::ManagedStatic< PassManagerOptions > options
static SmallVector< Value > slice(OpBuilder &b, Location loc, Value value, VectorType nativeType)
static SmallVector< Value > sliceLoadStoreIndices(PatternRewriter &rewriter, Location loc, OperandRange originalIndices, ArrayRef< int64_t > offsets)
static std::optional< SmallVector< int64_t > > getTargetShape(const vector::UnrollVectorOptions &options, Operation *op)
Return the target shape for unrolling for the given op.
static SmallVector< int64_t > getUnrollOrder(unsigned numLoops, Operation *op, const vector::UnrollVectorOptions &options)
static Operation * cloneOpWithOperandsAndTypes(OpBuilder &builder, Location loc, Operation *op, ArrayRef< Value > operands, ArrayRef< Type > resultTypes)
Base type for affine expression.
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
static AffineMap get(MLIRContext *context)
Returns a zero result affine map with no dimensions or symbols: () -> ().
ArrayRef< AffineExpr > getResults() const
TypedAttr getZeroAttr(Type type)
MLIRContext * getContext() const
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
This class helps build Operations.
void createOrFold(SmallVectorImpl< Value > &results, Location location, Args &&...args)
Create an operation of specific op type at the current insertion point, and immediately try to fold i...
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
This class implements the operand iterators for the Operation class.
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
Operation is the basic unit of execution within MLIR.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Location getLoc()
The source location the operation was defined or derived from.
MutableArrayRef< OpOperand > getOpOperands()
Attribute getPropertiesAsAttribute()
Return the properties converted to an attribute.
OperationName getName()
The name of an operation is the key identifier for it.
DictionaryAttr getDiscardableAttrDictionary()
Return all of the discardable attributes on this operation as a DictionaryAttr.
result_range getResults()
unsigned getNumResults()
Return the number of results held by this operation.
This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
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.
RewritePattern is the common base class for all DAG to DAG replacements.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)
Used to notify the listener that the IR failed to be rewritten because of a match failure,...
Type getType() const
Return the type of this value.
static ConstantIndexOp create(OpBuilder &builder, Location location, int64_t value)
bool hasElementwiseMappableTraits(Operation *op)
Together, Elementwise, Scalarizable, Vectorizable, and Tensorizable provide an easy way for scalar op...
Value makeArithReduction(OpBuilder &b, Location loc, CombiningKind kind, Value v1, Value acc, arith::FastMathFlagsAttr fastmath=nullptr, Value mask=nullptr)
Returns the result value of reducing two scalar/vector values with the corresponding arith operation.
FailureOr< SmallVector< Value > > unrollVectorValue(TypedValue< VectorType >, RewriterBase &)
Generic utility for unrolling values of type vector<NxAxBx...> to N values of type vector<AxBx....
LogicalResult unrollVectorOp(Operation *op, PatternRewriter &rewriter, UnrollVectorOpFn unrollFn)
Include the generated interface declarations.
SmallVector< int64_t > computeStrides(ArrayRef< int64_t > sizes)
SmallVector< int64_t > delinearize(int64_t linearIndex, ArrayRef< int64_t > strides)
Given the strides together with a linear index in the dimension space, return the vector-space offset...
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.
AffineExpr getAffineConstantExpr(int64_t constant, MLIRContext *context)
SmallVector< T > applyPermutationMap(AffineMap map, llvm::ArrayRef< T > source)
Apply a permutation from map to source and return the result.
int64_t linearize(ArrayRef< int64_t > offsets, ArrayRef< int64_t > basis)
Return the linearized index of 'offsets' w.r.t.
std::optional< SmallVector< int64_t > > computeShapeRatio(ArrayRef< int64_t > shape, ArrayRef< int64_t > subShape)
Return the multi-dimensional integral ratio of subShape to the trailing dimensions of shape.
AffineExpr getAffineDimExpr(unsigned position, MLIRContext *context)
These free functions allow clients of the API to not use classes in detail.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
This represents an operation in an abstracted form, suitable for use with the builder APIs.
Attribute propertiesAttr
This Attribute is used to opaquely construct the properties of the operation.
Options that control the vector unrolling.