303 assert(scope &&
"Expected op to be inside automatic allocation scope");
308template <
typename OpTy>
309static BufferAllocs allocBuffers(
OpBuilder &
b, OpTy xferOp) {
312 Operation *scope = getAutomaticAllocationScope(xferOp);
314 "AutomaticAllocationScope with >1 regions");
318 auto bufferType = MemRefType::get({}, xferOp.getVectorType());
319 result.dataBuffer = memref::AllocaOp::create(
b, loc, bufferType);
321 if (xferOp.getMask()) {
322 auto maskType = MemRefType::get({}, xferOp.getMask().
getType());
323 auto maskBuffer = memref::AllocaOp::create(
b, loc, maskType);
324 b.setInsertionPoint(xferOp);
325 memref::StoreOp::create(
b, loc, xferOp.getMask(), maskBuffer);
327 memref::LoadOp::create(
b, loc, maskBuffer,
ValueRange());
337static FailureOr<MemRefType> unpackOneDim(MemRefType type) {
338 auto vectorType = dyn_cast<VectorType>(type.getElementType());
341 if (vectorType.getScalableDims().front())
343 auto memrefShape = type.getShape();
345 newMemrefShape.append(memrefShape.begin(), memrefShape.end());
346 newMemrefShape.push_back(vectorType.getDimSize(0));
347 return MemRefType::get(newMemrefShape,
353template <
typename OpTy>
354static Value getMaskBuffer(OpTy xferOp) {
355 assert(xferOp.getMask() &&
"Expected that transfer op has mask");
356 auto loadOp = xferOp.getMask().template getDefiningOp<memref::LoadOp>();
357 assert(loadOp &&
"Expected transfer op mask produced by LoadOp");
358 return loadOp.getMemRef();
362template <
typename OpTy>
367struct Strategy<TransferReadOp> {
370 static memref::StoreOp getStoreOp(TransferReadOp xferOp) {
371 assert(xferOp->hasOneUse() &&
"Expected exactly one use of TransferReadOp");
372 auto storeOp = dyn_cast<memref::StoreOp>((*xferOp->use_begin()).getOwner());
373 assert(storeOp &&
"Expected TransferReadOp result used by StoreOp");
384 static Value getBuffer(TransferReadOp xferOp) {
385 return getStoreOp(xferOp).getMemRef();
389 static void getBufferIndices(TransferReadOp xferOp,
391 auto storeOp = getStoreOp(xferOp);
392 auto prevIndices = memref::StoreOpAdaptor(storeOp).getIndices();
393 indices.append(prevIndices.begin(), prevIndices.end());
425 TransferReadOp xferOp,
Value buffer,
Value iv,
428 getBufferIndices(xferOp, storeIndices);
429 storeIndices.push_back(iv);
435 auto bufferType = dyn_cast<ShapedType>(buffer.
getType());
436 auto vecType = dyn_cast<VectorType>(bufferType.getElementType());
437 auto inBoundsAttr = dropFirstElem(
b, xferOp.getInBoundsAttr());
438 auto newXferOp = vector::TransferReadOp::create(
439 b, loc, vecType, xferOp.getBase(), xferIndices,
440 AffineMapAttr::get(unpackedPermutationMap(
b, xferOp)),
441 xferOp.getPadding(),
Value(), inBoundsAttr);
443 maybeApplyPassLabel(
b, newXferOp,
options.targetRank);
445 memref::StoreOp::create(
b, loc, newXferOp.getVector(), buffer,
456 getBufferIndices(xferOp, storeIndices);
457 storeIndices.push_back(iv);
460 auto bufferType = dyn_cast<ShapedType>(buffer.
getType());
461 auto vecType = dyn_cast<VectorType>(bufferType.getElementType());
463 vector::BroadcastOp::create(
b, loc, vecType, xferOp.getPadding());
464 memref::StoreOp::create(
b, loc, vec, buffer, storeIndices);
472 rewriter.
eraseOp(getStoreOp(xferOp));
477 static Value initialLoopState(TransferReadOp xferOp) {
return Value(); }
482struct Strategy<TransferWriteOp> {
490 static Value getBuffer(TransferWriteOp xferOp) {
491 auto loadOp = xferOp.getVector().
getDefiningOp<memref::LoadOp>();
492 assert(loadOp &&
"Expected transfer op vector produced by LoadOp");
493 return loadOp.getMemRef();
497 static void getBufferIndices(TransferWriteOp xferOp,
499 auto loadOp = xferOp.getVector().getDefiningOp<memref::LoadOp>();
500 auto prevIndices = memref::LoadOpAdaptor(loadOp).getIndices();
501 indices.append(prevIndices.begin(), prevIndices.end());
513 static TransferWriteOp rewriteOp(
OpBuilder &
b,
515 TransferWriteOp xferOp,
Value buffer,
518 getBufferIndices(xferOp, loadIndices);
519 loadIndices.push_back(iv);
525 auto vec = memref::LoadOp::create(
b, loc, buffer, loadIndices);
526 auto inBoundsAttr = dropFirstElem(
b, xferOp.getInBoundsAttr());
527 auto source = loopState.empty() ? xferOp.getBase() : loopState[0];
528 Type type = isTensorOp(xferOp) ? xferOp.getShapedType() :
Type();
529 auto newXferOp = vector::TransferWriteOp::create(
530 b, loc, type, vec, source, xferIndices,
531 AffineMapAttr::get(unpackedPermutationMap(
b, xferOp)),
Value(),
534 maybeApplyPassLabel(
b, newXferOp,
options.targetRank);
540 static Value handleOutOfBoundsDim(
OpBuilder &
b, TransferWriteOp xferOp,
543 return isTensorOp(xferOp) ? loopState[0] :
Value();
549 if (isTensorOp(xferOp)) {
550 assert(forOp->getNumResults() == 1 &&
"Expected one for loop result");
551 rewriter.
replaceOp(xferOp, forOp->getResult(0));
558 static Value initialLoopState(TransferWriteOp xferOp) {
559 return isTensorOp(xferOp) ? xferOp.getBase() :
Value();
563template <
typename OpTy>
564static LogicalResult checkPrepareXferOp(OpTy xferOp,
PatternRewriter &rewriter,
566 if (xferOp->hasDiscardableAttr(kPassLabel))
568 xferOp,
"kPassLabel is present (vector-to-scf lowering in progress)");
569 if (failed(checkNotMasked(xferOp, rewriter)))
571 if (xferOp.getVectorType().getRank() <=
options.targetRank)
573 xferOp,
"xferOp vector rank <= transformation target rank");
574 if (xferOp.getVectorType().getScalableDims().front())
576 xferOp,
"Unpacking of the leading dimension into the memref is not yet "
577 "supported for scalable dims");
578 if (isTensorOp(xferOp) && !
options.lowerTensors)
580 xferOp,
"Unpacking for tensors has been disabled.");
581 if (xferOp.getVectorType().getElementType() !=
582 xferOp.getShapedType().getElementType())
584 xferOp,
"Mismatching source and destination element types.");
588 xferOp,
"xferOp is not inside an automatic allocation scope");
616struct PrepareTransferReadConversion
617 :
public VectorToSCFPattern<TransferReadOp> {
618 using VectorToSCFPattern<TransferReadOp>::VectorToSCFPattern;
620 LogicalResult matchAndRewrite(TransferReadOp xferOp,
622 if (checkPrepareXferOp(xferOp, rewriter,
options).failed())
624 xferOp,
"checkPrepareXferOp conditions not met!");
626 auto buffers = allocBuffers(rewriter, xferOp);
627 auto *newXfer = rewriter.
clone(*xferOp.getOperation());
629 if (xferOp.getMask()) {
630 dyn_cast<TransferReadOp>(newXfer).getMaskMutable().assign(
635 memref::StoreOp::create(rewriter, loc, newXfer->getResult(0),
667struct PrepareTransferWriteConversion
668 :
public VectorToSCFPattern<TransferWriteOp> {
669 using VectorToSCFPattern<TransferWriteOp>::VectorToSCFPattern;
671 LogicalResult matchAndRewrite(TransferWriteOp xferOp,
673 if (checkPrepareXferOp(xferOp, rewriter,
options).failed())
675 xferOp,
"checkPrepareXferOp conditions not met!");
678 auto buffers = allocBuffers(rewriter, xferOp);
679 memref::StoreOp::create(rewriter, loc, xferOp.getVector(),
682 memref::LoadOp::create(rewriter, loc, buffers.dataBuffer,
ValueRange{});
684 xferOp.getValueToStoreMutable().assign(loadedVec);
685 xferOp->setDiscardableAttr(kPassLabel, rewriter.
getUnitAttr());
688 if (xferOp.getMask()) {
690 xferOp.getMaskMutable().assign(buffers.maskBuffer);
725struct DecomposePrintOpConversion :
public VectorToSCFPattern<vector::PrintOp> {
726 using VectorToSCFPattern<vector::PrintOp>::VectorToSCFPattern;
727 LogicalResult matchAndRewrite(vector::PrintOp
printOp,
732 VectorType vectorType = dyn_cast<VectorType>(
printOp.getPrintType());
742 if (vectorType.getRank() > 1 && vectorType.isScalable())
746 auto value =
printOp.getSource();
748 if (
auto intTy = dyn_cast<IntegerType>(vectorType.getElementType())) {
752 auto width = intTy.getWidth();
753 auto legalWidth = llvm::NextPowerOf2(std::max(8u, width) - 1);
754 auto legalIntTy = IntegerType::get(rewriter.
getContext(), legalWidth,
755 intTy.getSignedness());
757 auto signlessSourceVectorType =
758 vectorType.cloneWith({}, getIntTypeWithSignlessSemantics(intTy));
759 auto signlessTargetVectorType =
760 vectorType.cloneWith({}, getIntTypeWithSignlessSemantics(legalIntTy));
761 auto targetVectorType = vectorType.cloneWith({}, legalIntTy);
762 value = vector::BitCastOp::create(rewriter, loc, signlessSourceVectorType,
764 if (value.
getType() != signlessTargetVectorType) {
765 if (width == 1 || intTy.isUnsigned())
766 value = arith::ExtUIOp::create(rewriter, loc,
767 signlessTargetVectorType, value);
769 value = arith::ExtSIOp::create(rewriter, loc,
770 signlessTargetVectorType, value);
772 value = vector::BitCastOp::create(rewriter, loc, targetVectorType, value);
773 vectorType = targetVectorType;
776 auto scalableDimensions = vectorType.getScalableDims();
777 auto shape = vectorType.getShape();
778 constexpr int64_t singletonShape[] = {1};
779 if (vectorType.getRank() == 0)
780 shape = singletonShape;
782 if (vectorType.getRank() != 1) {
786 auto flatVectorType =
787 VectorType::get({flatLength}, vectorType.getElementType());
788 value = vector::ShapeCastOp::create(rewriter, loc, flatVectorType, value);
791 vector::PrintOp firstClose;
793 for (
unsigned d = 0; d <
shape.size(); d++) {
799 if (!scalableDimensions.empty() && scalableDimensions[d]) {
800 auto vscale = vector::VectorScaleOp::create(rewriter, loc,
802 upperBound = arith::MulIOp::create(rewriter, loc, upperBound, vscale);
804 auto lastIndex = arith::SubIOp::create(rewriter, loc, upperBound, step);
807 vector::PrintOp::create(rewriter, loc, vector::PrintPunctuation::Open);
809 scf::ForOp::create(rewriter, loc, lowerBound, upperBound, step);
811 rewriter, loc, vector::PrintPunctuation::Close);
815 auto loopIdx = loop.getInductionVar();
816 loopIndices.push_back(loopIdx);
820 auto notLastIndex = arith::CmpIOp::create(
821 rewriter, loc, arith::CmpIPredicate::ult, loopIdx, lastIndex);
822 scf::IfOp::create(rewriter, loc, notLastIndex,
824 vector::PrintOp::create(
825 builder, loc, vector::PrintPunctuation::Comma);
826 scf::YieldOp::create(builder, loc);
835 auto currentStride = 1;
836 for (
int d =
shape.size() - 1; d >= 0; d--) {
839 auto index = arith::MulIOp::create(rewriter, loc, stride, loopIndices[d]);
841 flatIndex = arith::AddIOp::create(rewriter, loc, flatIndex,
index);
844 currentStride *=
shape[d];
848 auto element = vector::ExtractOp::create(rewriter, loc, value, flatIndex);
849 vector::PrintOp::create(rewriter, loc, element,
850 vector::PrintPunctuation::NoPunctuation);
853 vector::PrintOp::create(rewriter, loc,
printOp.getPunctuation());
858 static IntegerType getIntTypeWithSignlessSemantics(IntegerType intTy) {
859 return IntegerType::get(intTy.getContext(), intTy.getWidth(),
860 IntegerType::Signless);
893template <
typename OpTy>
894struct TransferOpConversion :
public VectorToSCFPattern<OpTy> {
895 using VectorToSCFPattern<OpTy>::VectorToSCFPattern;
900 this->setHasBoundedRewriteRecursion();
903 static void getMaskBufferLoadIndices(OpTy xferOp,
Value castedMaskBuffer,
906 assert(xferOp.getMask() &&
"Expected transfer op to have mask");
912 Value maskBuffer = getMaskBuffer(xferOp);
915 if (
auto loadOp = dyn_cast<memref::LoadOp>(user)) {
917 loadIndices.append(prevIndices.begin(), prevIndices.end());
924 if (!xferOp.isBroadcastDim(0))
925 loadIndices.push_back(iv);
928 LogicalResult matchAndRewrite(OpTy xferOp,
930 if (!xferOp->hasDiscardableAttr(kPassLabel))
932 xferOp,
"kPassLabel is present (progressing lowering in progress)");
936 Value dataBuffer = Strategy<OpTy>::getBuffer(xferOp);
937 auto dataBufferType = dyn_cast<MemRefType>(dataBuffer.
getType());
938 FailureOr<MemRefType> castedDataType = unpackOneDim(dataBufferType);
939 if (failed(castedDataType))
941 "Failed to unpack one vector dim.");
943 auto castedDataBuffer =
944 vector::TypeCastOp::create(locB, *castedDataType, dataBuffer);
947 Value castedMaskBuffer;
948 if (xferOp.getMask()) {
949 Value maskBuffer = getMaskBuffer(xferOp);
950 if (xferOp.isBroadcastDim(0) || xferOp.getMaskType().getRank() == 1) {
956 castedMaskBuffer = maskBuffer;
960 auto maskBufferType = cast<MemRefType>(maskBuffer.
getType());
961 MemRefType castedMaskType = *unpackOneDim(maskBufferType);
963 vector::TypeCastOp::create(locB, castedMaskType, maskBuffer);
970 locB, castedDataType->getDimSize(castedDataType->getRank() - 1));
974 auto loopState = Strategy<OpTy>::initialLoopState(xferOp);
977 auto result = scf::ForOp::create(
982 auto result = generateInBoundsCheck(
983 b, xferOp, iv, unpackedDim(xferOp),
988 OpTy newXfer = Strategy<OpTy>::rewriteOp(
989 b, this->options, xferOp, castedDataBuffer, iv, loopState);
995 if (xferOp.getMask() && (xferOp.isBroadcastDim(0) ||
996 xferOp.getMaskType().getRank() > 1)) {
998 b.setInsertionPoint(newXfer);
1001 getMaskBufferLoadIndices(xferOp, castedMaskBuffer,
1003 auto mask = memref::LoadOp::create(
b, loc, castedMaskBuffer,
1006 newXfer.getMaskMutable().assign(mask);
1010 return loopState.empty() ?
Value() : newXfer->getResult(0);
1014 return Strategy<OpTy>::handleOutOfBoundsDim(
1015 b, xferOp, castedDataBuffer, iv, loopState);
1018 maybeYieldValue(
b, loc, !loopState.empty(),
result);
1021 Strategy<OpTy>::cleanup(rewriter, xferOp,
result);
1028template <
typename VscaleConstantBuilder>
1029static FailureOr<SmallVector<OpFoldResult>>
1030getMaskDimSizes(
Value mask, VscaleConstantBuilder &createVscaleMultiple) {
1033 if (
auto createMaskOp = mask.getDefiningOp<vector::CreateMaskOp>()) {
1034 return llvm::map_to_vector(createMaskOp.getOperands(), [](
Value dimSize) {
1035 return OpFoldResult(dimSize);
1038 if (
auto constantMask = mask.getDefiningOp<vector::ConstantMaskOp>()) {
1040 VectorType maskType = constantMask.getVectorType();
1041 auto indexType = IndexType::get(mask.getContext());
1042 return llvm::map_to_vector(
1043 constantMask.getMaskDimSizes(), [&](
int64_t dimSize) {
1045 if (maskType.getScalableDims()[dimIdx++])
1046 return OpFoldResult(createVscaleMultiple(dimSize));
1047 return OpFoldResult(IntegerAttr::get(indexType, dimSize));
1090struct ScalableTransposeTransferWriteConversion
1091 : VectorToSCFPattern<vector::TransferWriteOp> {
1092 using VectorToSCFPattern::VectorToSCFPattern;
1094 LogicalResult matchAndRewrite(TransferWriteOp writeOp,
1096 if (failed(checkLowerTensors(writeOp, rewriter)))
1098 if (failed(checkNotMasked(writeOp, rewriter)))
1101 VectorType vectorType = writeOp.getVectorType();
1108 writeOp,
"expected vector of the form vector<[N]xMxty>");
1111 auto permutationMap = writeOp.getPermutationMap();
1112 if (!permutationMap.isIdentity()) {
1114 writeOp,
"non-identity permutations are unsupported (lower first)");
1120 if (!writeOp.isDimInBounds(0)) {
1122 writeOp,
"out-of-bounds dims are unsupported (use masking)");
1126 auto transposeOp =
vector.getDefiningOp<vector::TransposeOp>();
1132 auto loc = writeOp.getLoc();
1133 auto createVscaleMultiple =
1136 auto maskDims = getMaskDimSizes(writeOp.getMask(), createVscaleMultiple);
1137 if (failed(maskDims)) {
1139 "failed to resolve mask dims");
1142 int64_t fixedDimSize = vectorType.getDimSize(1);
1143 auto fixedDimOffsets = llvm::seq(fixedDimSize);
1146 auto transposeSource = transposeOp.getVector();
1148 llvm::map_to_vector(fixedDimOffsets, [&](
int64_t idx) ->
Value {
1149 return vector::ExtractOp::create(rewriter, loc, transposeSource, idx);
1156 ?
Value(createVscaleMultiple(vectorType.getDimSize(0)))
1162 Value sliceMask =
nullptr;
1163 if (!maskDims->empty()) {
1164 sliceMask = vector::CreateMaskOp::create(
1165 rewriter, loc, sliceType.clone(rewriter.
getI1Type()),
1169 Value initDest = isTensorOp(writeOp) ? writeOp.getBase() :
Value{};
1171 auto result = scf::ForOp::create(
1172 rewriter, loc, lb,
ub, step, initLoopArgs,
1180 llvm::map_to_vector(fixedDimOffsets, [&](
int64_t idx) ->
Value {
1181 return vector::ExtractOp::create(
1182 b, loc, transposeSourceSlices[idx], iv);
1184 auto sliceVec = vector::FromElementsOp::create(
b, loc, sliceType,
1189 loopIterArgs.empty() ? writeOp.getBase() : loopIterArgs.front();
1190 auto newWriteOp = vector::TransferWriteOp::create(
1191 b, loc, sliceVec, dest, xferIndices,
1194 newWriteOp.getMaskMutable().assign(sliceMask);
1197 scf::YieldOp::create(
b, loc,
1199 : newWriteOp.getResult());
1202 if (isTensorOp(writeOp))
1217template <
typename OpTy>
1218static void maybeAssignMask(
OpBuilder &
b, OpTy xferOp, OpTy newXferOp,
1220 if (!xferOp.getMask())
1223 if (xferOp.isBroadcastDim(0)) {
1226 newXferOp.getMaskMutable().assign(xferOp.getMask());
1230 if (xferOp.getMaskType().getRank() > 1) {
1233 b.setInsertionPoint(newXferOp);
1237 auto newMask = vector::ExtractOp::create(
b, loc, xferOp.getMask(),
indices);
1238 newXferOp.getMaskMutable().assign(newMask);
1274struct UnrollTransferReadConversion
1275 :
public VectorToSCFPattern<TransferReadOp> {
1276 using VectorToSCFPattern<TransferReadOp>::VectorToSCFPattern;
1281 setHasBoundedRewriteRecursion();
1287 TransferReadOp xferOp)
const {
1288 if (
auto insertOp = getInsertOp(xferOp))
1289 return insertOp.getDest();
1291 return vector::BroadcastOp::create(rewriter, loc, xferOp.getVectorType(),
1292 xferOp.getPadding());
1297 vector::InsertOp getInsertOp(TransferReadOp xferOp)
const {
1298 if (xferOp->hasOneUse()) {
1300 if (
auto insertOp = dyn_cast<vector::InsertOp>(xferOpUser))
1304 return vector::InsertOp();
1309 void getInsertionIndices(TransferReadOp xferOp,
1311 if (
auto insertOp = getInsertOp(xferOp)) {
1312 auto pos = insertOp.getMixedPosition();
1313 indices.append(pos.begin(), pos.end());
1319 LogicalResult matchAndRewrite(TransferReadOp xferOp,
1321 if (xferOp.getVectorType().getRank() <=
options.targetRank)
1323 xferOp,
"vector rank is less or equal to target rank");
1324 if (failed(checkLowerTensors(xferOp, rewriter)))
1326 if (failed(checkNotMasked(xferOp, rewriter)))
1328 if (xferOp.getVectorType().getElementType() !=
1329 xferOp.getShapedType().getElementType())
1331 xferOp,
"not yet supported: element type mismatch");
1332 auto xferVecType = xferOp.getVectorType();
1333 if (xferVecType.getScalableDims()[0]) {
1335 xferOp,
"scalable dimensions cannot be unrolled at compile time");
1338 auto insertOp = getInsertOp(xferOp);
1339 auto vec = buildResultVector(rewriter, xferOp);
1340 auto vecType = dyn_cast<VectorType>(vec.getType());
1344 int64_t dimSize = xferVecType.getShape()[0];
1348 for (
int64_t i = 0; i < dimSize; ++i) {
1353 vec = generateInBoundsCheck(
1354 rewriter, xferOp, iv, unpackedDim(xferOp),
TypeRange(vecType),
1363 getInsertionIndices(xferOp, insertionIndices);
1366 auto inBoundsAttr = dropFirstElem(
b, xferOp.getInBoundsAttr());
1368 auto newXferOp = vector::TransferReadOp::create(
1369 b, loc, newXferVecType, xferOp.getBase(), xferIndices,
1370 AffineMapAttr::get(unpackedPermutationMap(
b, xferOp)),
1371 xferOp.getPadding(),
Value(), inBoundsAttr);
1372 maybeAssignMask(
b, xferOp, newXferOp, i);
1374 Value valToInser = newXferOp.getResult();
1375 if (newXferVecType.getRank() == 0) {
1378 valToInser = vector::ExtractOp::create(
b, loc, valToInser,
1381 return vector::InsertOp::create(
b, loc, valToInser, vec,
1429struct UnrollTransferWriteConversion
1430 :
public VectorToSCFPattern<TransferWriteOp> {
1431 using VectorToSCFPattern<TransferWriteOp>::VectorToSCFPattern;
1436 setHasBoundedRewriteRecursion();
1440 Value getDataVector(TransferWriteOp xferOp)
const {
1441 if (
auto extractOp = getExtractOp(xferOp))
1442 return extractOp.getSource();
1443 return xferOp.getVector();
1447 vector::ExtractOp getExtractOp(TransferWriteOp xferOp)
const {
1448 if (
auto *op = xferOp.getVector().getDefiningOp())
1449 return dyn_cast<vector::ExtractOp>(op);
1450 return vector::ExtractOp();
1455 void getExtractionIndices(TransferWriteOp xferOp,
1457 if (
auto extractOp = getExtractOp(xferOp)) {
1458 auto pos = extractOp.getMixedPosition();
1459 indices.append(pos.begin(), pos.end());
1465 LogicalResult matchAndRewrite(TransferWriteOp xferOp,
1467 VectorType inputVectorTy = xferOp.getVectorType();
1469 if (inputVectorTy.getRank() <=
options.targetRank)
1472 if (failed(checkLowerTensors(xferOp, rewriter)))
1474 if (failed(checkNotMasked(xferOp, rewriter)))
1477 if (inputVectorTy.getElementType() !=
1478 xferOp.getShapedType().getElementType())
1481 auto vec = getDataVector(xferOp);
1482 if (inputVectorTy.getScalableDims()[0]) {
1487 int64_t dimSize = inputVectorTy.getShape()[0];
1488 Value source = xferOp.getBase();
1489 auto sourceType = isTensorOp(xferOp) ? xferOp.getShapedType() :
Type();
1493 for (
int64_t i = 0; i < dimSize; ++i) {
1496 auto updatedSource = generateInBoundsCheck(
1497 rewriter, xferOp, iv, unpackedDim(xferOp),
1507 getExtractionIndices(xferOp, extractionIndices);
1508 extractionIndices.push_back(
b.getI64IntegerAttr(i));
1511 vector::ExtractOp::create(
b, loc, vec, extractionIndices);
1512 auto inBoundsAttr = dropFirstElem(
b, xferOp.getInBoundsAttr());
1514 if (inputVectorTy.getRank() == 1) {
1518 xferVec = vector::BroadcastOp::create(
1519 b, loc, VectorType::get({}, extracted.getType()), extracted);
1521 xferVec = extracted;
1523 auto newXferOp = vector::TransferWriteOp::create(
1524 b, loc, sourceType, xferVec, source, xferIndices,
1525 AffineMapAttr::get(unpackedPermutationMap(
b, xferOp)),
Value(),
1528 maybeAssignMask(
b, xferOp, newXferOp, i);
1530 return isTensorOp(xferOp) ? newXferOp->getResult(0) :
Value();
1534 return isTensorOp(xferOp) ? source :
Value();
1537 if (isTensorOp(xferOp))
1538 source = updatedSource;
1541 if (isTensorOp(xferOp))