294 assert(scope &&
"Expected op to be inside automatic allocation scope");
299template <
typename OpTy>
300static BufferAllocs allocBuffers(
OpBuilder &
b, OpTy xferOp) {
303 Operation *scope = getAutomaticAllocationScope(xferOp);
305 "AutomaticAllocationScope with >1 regions");
309 auto bufferType = MemRefType::get({}, xferOp.getVectorType());
310 result.dataBuffer = memref::AllocaOp::create(
b, loc, bufferType);
312 if (xferOp.getMask()) {
313 auto maskType = MemRefType::get({}, xferOp.getMask().
getType());
314 auto maskBuffer = memref::AllocaOp::create(
b, loc, maskType);
315 b.setInsertionPoint(xferOp);
316 memref::StoreOp::create(
b, loc, xferOp.getMask(), maskBuffer);
318 memref::LoadOp::create(
b, loc, maskBuffer,
ValueRange());
328static FailureOr<MemRefType> unpackOneDim(MemRefType type) {
329 auto vectorType = dyn_cast<VectorType>(type.getElementType());
332 if (vectorType.getScalableDims().front())
334 auto memrefShape = type.getShape();
336 newMemrefShape.append(memrefShape.begin(), memrefShape.end());
337 newMemrefShape.push_back(vectorType.getDimSize(0));
338 return MemRefType::get(newMemrefShape,
344template <
typename OpTy>
345static Value getMaskBuffer(OpTy xferOp) {
346 assert(xferOp.getMask() &&
"Expected that transfer op has mask");
347 auto loadOp = xferOp.getMask().template getDefiningOp<memref::LoadOp>();
348 assert(loadOp &&
"Expected transfer op mask produced by LoadOp");
349 return loadOp.getMemRef();
353template <
typename OpTy>
358struct Strategy<TransferReadOp> {
361 static memref::StoreOp getStoreOp(TransferReadOp xferOp) {
362 assert(xferOp->hasOneUse() &&
"Expected exactly one use of TransferReadOp");
363 auto storeOp = dyn_cast<memref::StoreOp>((*xferOp->use_begin()).getOwner());
364 assert(storeOp &&
"Expected TransferReadOp result used by StoreOp");
375 static Value getBuffer(TransferReadOp xferOp) {
376 return getStoreOp(xferOp).getMemRef();
380 static void getBufferIndices(TransferReadOp xferOp,
382 auto storeOp = getStoreOp(xferOp);
383 auto prevIndices = memref::StoreOpAdaptor(storeOp).getIndices();
384 indices.append(prevIndices.begin(), prevIndices.end());
416 TransferReadOp xferOp,
Value buffer,
Value iv,
419 getBufferIndices(xferOp, storeIndices);
420 storeIndices.push_back(iv);
426 auto bufferType = dyn_cast<ShapedType>(buffer.
getType());
427 auto vecType = dyn_cast<VectorType>(bufferType.getElementType());
428 auto inBoundsAttr = dropFirstElem(
b, xferOp.getInBoundsAttr());
429 auto newXferOp = vector::TransferReadOp::create(
430 b, loc, vecType, xferOp.getBase(), xferIndices,
431 AffineMapAttr::get(unpackedPermutationMap(
b, xferOp)),
432 xferOp.getPadding(),
Value(), inBoundsAttr);
434 maybeApplyPassLabel(
b, newXferOp,
options.targetRank);
436 memref::StoreOp::create(
b, loc, newXferOp.getVector(), buffer,
447 getBufferIndices(xferOp, storeIndices);
448 storeIndices.push_back(iv);
451 auto bufferType = dyn_cast<ShapedType>(buffer.
getType());
452 auto vecType = dyn_cast<VectorType>(bufferType.getElementType());
454 vector::BroadcastOp::create(
b, loc, vecType, xferOp.getPadding());
455 memref::StoreOp::create(
b, loc, vec, buffer, storeIndices);
463 rewriter.
eraseOp(getStoreOp(xferOp));
468 static Value initialLoopState(TransferReadOp xferOp) {
return Value(); }
473struct Strategy<TransferWriteOp> {
481 static Value getBuffer(TransferWriteOp xferOp) {
482 auto loadOp = xferOp.getVector().
getDefiningOp<memref::LoadOp>();
483 assert(loadOp &&
"Expected transfer op vector produced by LoadOp");
484 return loadOp.getMemRef();
488 static void getBufferIndices(TransferWriteOp xferOp,
490 auto loadOp = xferOp.getVector().getDefiningOp<memref::LoadOp>();
491 auto prevIndices = memref::LoadOpAdaptor(loadOp).getIndices();
492 indices.append(prevIndices.begin(), prevIndices.end());
504 static TransferWriteOp rewriteOp(
OpBuilder &
b,
506 TransferWriteOp xferOp,
Value buffer,
509 getBufferIndices(xferOp, loadIndices);
510 loadIndices.push_back(iv);
516 auto vec = memref::LoadOp::create(
b, loc, buffer, loadIndices);
517 auto inBoundsAttr = dropFirstElem(
b, xferOp.getInBoundsAttr());
518 auto source = loopState.empty() ? xferOp.getBase() : loopState[0];
519 Type type = isTensorOp(xferOp) ? xferOp.getShapedType() :
Type();
520 auto newXferOp = vector::TransferWriteOp::create(
521 b, loc, type, vec, source, xferIndices,
522 AffineMapAttr::get(unpackedPermutationMap(
b, xferOp)),
Value(),
525 maybeApplyPassLabel(
b, newXferOp,
options.targetRank);
531 static Value handleOutOfBoundsDim(
OpBuilder &
b, TransferWriteOp xferOp,
534 return isTensorOp(xferOp) ? loopState[0] :
Value();
540 if (isTensorOp(xferOp)) {
541 assert(forOp->getNumResults() == 1 &&
"Expected one for loop result");
542 rewriter.
replaceOp(xferOp, forOp->getResult(0));
549 static Value initialLoopState(TransferWriteOp xferOp) {
550 return isTensorOp(xferOp) ? xferOp.getBase() :
Value();
554template <
typename OpTy>
555static LogicalResult checkPrepareXferOp(OpTy xferOp,
PatternRewriter &rewriter,
557 if (xferOp->hasDiscardableAttr(kPassLabel))
559 xferOp,
"kPassLabel is present (vector-to-scf lowering in progress)");
560 if (xferOp.getVectorType().getRank() <=
options.targetRank)
562 xferOp,
"xferOp vector rank <= transformation target rank");
563 if (xferOp.getVectorType().getScalableDims().front())
565 xferOp,
"Unpacking of the leading dimension into the memref is not yet "
566 "supported for scalable dims");
567 if (isTensorOp(xferOp) && !
options.lowerTensors)
569 xferOp,
"Unpacking for tensors has been disabled.");
570 if (xferOp.getVectorType().getElementType() !=
571 xferOp.getShapedType().getElementType())
573 xferOp,
"Mismatching source and destination element types.");
577 xferOp,
"xferOp is not inside an automatic allocation scope");
605struct PrepareTransferReadConversion
606 :
public VectorToSCFPattern<TransferReadOp> {
607 using VectorToSCFPattern<TransferReadOp>::VectorToSCFPattern;
609 LogicalResult matchAndRewrite(TransferReadOp xferOp,
611 if (checkPrepareXferOp(xferOp, rewriter,
options).failed())
613 xferOp,
"checkPrepareXferOp conditions not met!");
615 auto buffers = allocBuffers(rewriter, xferOp);
616 auto *newXfer = rewriter.
clone(*xferOp.getOperation());
618 if (xferOp.getMask()) {
619 dyn_cast<TransferReadOp>(newXfer).getMaskMutable().assign(
624 memref::StoreOp::create(rewriter, loc, newXfer->getResult(0),
656struct PrepareTransferWriteConversion
657 :
public VectorToSCFPattern<TransferWriteOp> {
658 using VectorToSCFPattern<TransferWriteOp>::VectorToSCFPattern;
660 LogicalResult matchAndRewrite(TransferWriteOp xferOp,
662 if (checkPrepareXferOp(xferOp, rewriter,
options).failed())
664 xferOp,
"checkPrepareXferOp conditions not met!");
667 auto buffers = allocBuffers(rewriter, xferOp);
668 memref::StoreOp::create(rewriter, loc, xferOp.getVector(),
671 memref::LoadOp::create(rewriter, loc, buffers.dataBuffer,
ValueRange{});
673 xferOp.getValueToStoreMutable().assign(loadedVec);
674 xferOp->setDiscardableAttr(kPassLabel, rewriter.
getUnitAttr());
677 if (xferOp.getMask()) {
679 xferOp.getMaskMutable().assign(buffers.maskBuffer);
714struct DecomposePrintOpConversion :
public VectorToSCFPattern<vector::PrintOp> {
715 using VectorToSCFPattern<vector::PrintOp>::VectorToSCFPattern;
716 LogicalResult matchAndRewrite(vector::PrintOp
printOp,
721 VectorType vectorType = dyn_cast<VectorType>(
printOp.getPrintType());
731 if (vectorType.getRank() > 1 && vectorType.isScalable())
735 auto value =
printOp.getSource();
737 if (
auto intTy = dyn_cast<IntegerType>(vectorType.getElementType())) {
741 auto width = intTy.getWidth();
742 auto legalWidth = llvm::NextPowerOf2(std::max(8u, width) - 1);
743 auto legalIntTy = IntegerType::get(rewriter.
getContext(), legalWidth,
744 intTy.getSignedness());
746 auto signlessSourceVectorType =
747 vectorType.cloneWith({}, getIntTypeWithSignlessSemantics(intTy));
748 auto signlessTargetVectorType =
749 vectorType.cloneWith({}, getIntTypeWithSignlessSemantics(legalIntTy));
750 auto targetVectorType = vectorType.cloneWith({}, legalIntTy);
751 value = vector::BitCastOp::create(rewriter, loc, signlessSourceVectorType,
753 if (value.
getType() != signlessTargetVectorType) {
754 if (width == 1 || intTy.isUnsigned())
755 value = arith::ExtUIOp::create(rewriter, loc,
756 signlessTargetVectorType, value);
758 value = arith::ExtSIOp::create(rewriter, loc,
759 signlessTargetVectorType, value);
761 value = vector::BitCastOp::create(rewriter, loc, targetVectorType, value);
762 vectorType = targetVectorType;
765 auto scalableDimensions = vectorType.getScalableDims();
766 auto shape = vectorType.getShape();
767 constexpr int64_t singletonShape[] = {1};
768 if (vectorType.getRank() == 0)
769 shape = singletonShape;
771 if (vectorType.getRank() != 1) {
775 auto flatVectorType =
776 VectorType::get({flatLength}, vectorType.getElementType());
777 value = vector::ShapeCastOp::create(rewriter, loc, flatVectorType, value);
780 vector::PrintOp firstClose;
782 for (
unsigned d = 0; d <
shape.size(); d++) {
788 if (!scalableDimensions.empty() && scalableDimensions[d]) {
789 auto vscale = vector::VectorScaleOp::create(rewriter, loc,
791 upperBound = arith::MulIOp::create(rewriter, loc, upperBound, vscale);
793 auto lastIndex = arith::SubIOp::create(rewriter, loc, upperBound, step);
796 vector::PrintOp::create(rewriter, loc, vector::PrintPunctuation::Open);
798 scf::ForOp::create(rewriter, loc, lowerBound, upperBound, step);
800 rewriter, loc, vector::PrintPunctuation::Close);
804 auto loopIdx = loop.getInductionVar();
805 loopIndices.push_back(loopIdx);
809 auto notLastIndex = arith::CmpIOp::create(
810 rewriter, loc, arith::CmpIPredicate::ult, loopIdx, lastIndex);
811 scf::IfOp::create(rewriter, loc, notLastIndex,
813 vector::PrintOp::create(
814 builder, loc, vector::PrintPunctuation::Comma);
815 scf::YieldOp::create(builder, loc);
824 auto currentStride = 1;
825 for (
int d =
shape.size() - 1; d >= 0; d--) {
828 auto index = arith::MulIOp::create(rewriter, loc, stride, loopIndices[d]);
830 flatIndex = arith::AddIOp::create(rewriter, loc, flatIndex,
index);
833 currentStride *=
shape[d];
837 auto element = vector::ExtractOp::create(rewriter, loc, value, flatIndex);
838 vector::PrintOp::create(rewriter, loc, element,
839 vector::PrintPunctuation::NoPunctuation);
842 vector::PrintOp::create(rewriter, loc,
printOp.getPunctuation());
847 static IntegerType getIntTypeWithSignlessSemantics(IntegerType intTy) {
848 return IntegerType::get(intTy.getContext(), intTy.getWidth(),
849 IntegerType::Signless);
882template <
typename OpTy>
883struct TransferOpConversion :
public VectorToSCFPattern<OpTy> {
884 using VectorToSCFPattern<OpTy>::VectorToSCFPattern;
889 this->setHasBoundedRewriteRecursion();
892 static void getMaskBufferLoadIndices(OpTy xferOp,
Value castedMaskBuffer,
895 assert(xferOp.getMask() &&
"Expected transfer op to have mask");
901 Value maskBuffer = getMaskBuffer(xferOp);
904 if (
auto loadOp = dyn_cast<memref::LoadOp>(user)) {
906 loadIndices.append(prevIndices.begin(), prevIndices.end());
913 if (!xferOp.isBroadcastDim(0))
914 loadIndices.push_back(iv);
917 LogicalResult matchAndRewrite(OpTy xferOp,
919 if (!xferOp->hasDiscardableAttr(kPassLabel))
921 xferOp,
"kPassLabel is present (progressing lowering in progress)");
925 Value dataBuffer = Strategy<OpTy>::getBuffer(xferOp);
926 auto dataBufferType = dyn_cast<MemRefType>(dataBuffer.
getType());
927 FailureOr<MemRefType> castedDataType = unpackOneDim(dataBufferType);
928 if (failed(castedDataType))
930 "Failed to unpack one vector dim.");
932 auto castedDataBuffer =
933 vector::TypeCastOp::create(locB, *castedDataType, dataBuffer);
936 Value castedMaskBuffer;
937 if (xferOp.getMask()) {
938 Value maskBuffer = getMaskBuffer(xferOp);
939 if (xferOp.isBroadcastDim(0) || xferOp.getMaskType().getRank() == 1) {
945 castedMaskBuffer = maskBuffer;
949 auto maskBufferType = cast<MemRefType>(maskBuffer.
getType());
950 MemRefType castedMaskType = *unpackOneDim(maskBufferType);
952 vector::TypeCastOp::create(locB, castedMaskType, maskBuffer);
959 locB, castedDataType->getDimSize(castedDataType->getRank() - 1));
963 auto loopState = Strategy<OpTy>::initialLoopState(xferOp);
966 auto result = scf::ForOp::create(
971 auto result = generateInBoundsCheck(
972 b, xferOp, iv, unpackedDim(xferOp),
977 OpTy newXfer = Strategy<OpTy>::rewriteOp(
978 b, this->options, xferOp, castedDataBuffer, iv, loopState);
984 if (xferOp.getMask() && (xferOp.isBroadcastDim(0) ||
985 xferOp.getMaskType().getRank() > 1)) {
987 b.setInsertionPoint(newXfer);
990 getMaskBufferLoadIndices(xferOp, castedMaskBuffer,
992 auto mask = memref::LoadOp::create(
b, loc, castedMaskBuffer,
995 newXfer.getMaskMutable().assign(mask);
999 return loopState.empty() ?
Value() : newXfer->getResult(0);
1003 return Strategy<OpTy>::handleOutOfBoundsDim(
1004 b, xferOp, castedDataBuffer, iv, loopState);
1007 maybeYieldValue(
b, loc, !loopState.empty(),
result);
1010 Strategy<OpTy>::cleanup(rewriter, xferOp,
result);
1017template <
typename VscaleConstantBuilder>
1018static FailureOr<SmallVector<OpFoldResult>>
1019getMaskDimSizes(
Value mask, VscaleConstantBuilder &createVscaleMultiple) {
1022 if (
auto createMaskOp = mask.getDefiningOp<vector::CreateMaskOp>()) {
1023 return llvm::map_to_vector(createMaskOp.getOperands(), [](
Value dimSize) {
1024 return OpFoldResult(dimSize);
1027 if (
auto constantMask = mask.getDefiningOp<vector::ConstantMaskOp>()) {
1029 VectorType maskType = constantMask.getVectorType();
1030 auto indexType = IndexType::get(mask.getContext());
1031 return llvm::map_to_vector(
1032 constantMask.getMaskDimSizes(), [&](
int64_t dimSize) {
1034 if (maskType.getScalableDims()[dimIdx++])
1035 return OpFoldResult(createVscaleMultiple(dimSize));
1036 return OpFoldResult(IntegerAttr::get(indexType, dimSize));
1079struct ScalableTransposeTransferWriteConversion
1080 : VectorToSCFPattern<vector::TransferWriteOp> {
1081 using VectorToSCFPattern::VectorToSCFPattern;
1083 LogicalResult matchAndRewrite(TransferWriteOp writeOp,
1085 if (failed(checkLowerTensors(writeOp, rewriter)))
1088 VectorType vectorType = writeOp.getVectorType();
1095 writeOp,
"expected vector of the form vector<[N]xMxty>");
1098 auto permutationMap = writeOp.getPermutationMap();
1099 if (!permutationMap.isIdentity()) {
1101 writeOp,
"non-identity permutations are unsupported (lower first)");
1107 if (!writeOp.isDimInBounds(0)) {
1109 writeOp,
"out-of-bounds dims are unsupported (use masking)");
1113 auto transposeOp =
vector.getDefiningOp<vector::TransposeOp>();
1119 auto loc = writeOp.getLoc();
1120 auto createVscaleMultiple =
1123 auto maskDims = getMaskDimSizes(writeOp.getMask(), createVscaleMultiple);
1124 if (failed(maskDims)) {
1126 "failed to resolve mask dims");
1129 int64_t fixedDimSize = vectorType.getDimSize(1);
1130 auto fixedDimOffsets = llvm::seq(fixedDimSize);
1133 auto transposeSource = transposeOp.getVector();
1135 llvm::map_to_vector(fixedDimOffsets, [&](
int64_t idx) ->
Value {
1136 return vector::ExtractOp::create(rewriter, loc, transposeSource, idx);
1143 ?
Value(createVscaleMultiple(vectorType.getDimSize(0)))
1149 Value sliceMask =
nullptr;
1150 if (!maskDims->empty()) {
1151 sliceMask = vector::CreateMaskOp::create(
1152 rewriter, loc, sliceType.clone(rewriter.
getI1Type()),
1156 Value initDest = isTensorOp(writeOp) ? writeOp.getBase() :
Value{};
1158 auto result = scf::ForOp::create(
1159 rewriter, loc, lb,
ub, step, initLoopArgs,
1167 llvm::map_to_vector(fixedDimOffsets, [&](
int64_t idx) ->
Value {
1168 return vector::ExtractOp::create(
1169 b, loc, transposeSourceSlices[idx], iv);
1171 auto sliceVec = vector::FromElementsOp::create(
b, loc, sliceType,
1176 loopIterArgs.empty() ? writeOp.getBase() : loopIterArgs.front();
1177 auto newWriteOp = vector::TransferWriteOp::create(
1178 b, loc, sliceVec, dest, xferIndices,
1181 newWriteOp.getMaskMutable().assign(sliceMask);
1184 scf::YieldOp::create(
b, loc,
1186 : newWriteOp.getResult());
1189 if (isTensorOp(writeOp))
1204template <
typename OpTy>
1205static void maybeAssignMask(
OpBuilder &
b, OpTy xferOp, OpTy newXferOp,
1207 if (!xferOp.getMask())
1210 if (xferOp.isBroadcastDim(0)) {
1213 newXferOp.getMaskMutable().assign(xferOp.getMask());
1217 if (xferOp.getMaskType().getRank() > 1) {
1220 b.setInsertionPoint(newXferOp);
1224 auto newMask = vector::ExtractOp::create(
b, loc, xferOp.getMask(),
indices);
1225 newXferOp.getMaskMutable().assign(newMask);
1261struct UnrollTransferReadConversion
1262 :
public VectorToSCFPattern<TransferReadOp> {
1263 using VectorToSCFPattern<TransferReadOp>::VectorToSCFPattern;
1268 setHasBoundedRewriteRecursion();
1274 TransferReadOp xferOp)
const {
1275 if (
auto insertOp = getInsertOp(xferOp))
1276 return insertOp.getDest();
1278 return vector::BroadcastOp::create(rewriter, loc, xferOp.getVectorType(),
1279 xferOp.getPadding());
1284 vector::InsertOp getInsertOp(TransferReadOp xferOp)
const {
1285 if (xferOp->hasOneUse()) {
1287 if (
auto insertOp = dyn_cast<vector::InsertOp>(xferOpUser))
1291 return vector::InsertOp();
1296 void getInsertionIndices(TransferReadOp xferOp,
1298 if (
auto insertOp = getInsertOp(xferOp)) {
1299 auto pos = insertOp.getMixedPosition();
1300 indices.append(pos.begin(), pos.end());
1306 LogicalResult matchAndRewrite(TransferReadOp xferOp,
1308 if (xferOp.getVectorType().getRank() <=
options.targetRank)
1310 xferOp,
"vector rank is less or equal to target rank");
1311 if (failed(checkLowerTensors(xferOp, rewriter)))
1313 if (xferOp.getVectorType().getElementType() !=
1314 xferOp.getShapedType().getElementType())
1316 xferOp,
"not yet supported: element type mismatch");
1317 auto xferVecType = xferOp.getVectorType();
1318 if (xferVecType.getScalableDims()[0]) {
1320 xferOp,
"scalable dimensions cannot be unrolled at compile time");
1323 auto insertOp = getInsertOp(xferOp);
1324 auto vec = buildResultVector(rewriter, xferOp);
1325 auto vecType = dyn_cast<VectorType>(vec.getType());
1329 int64_t dimSize = xferVecType.getShape()[0];
1333 for (
int64_t i = 0; i < dimSize; ++i) {
1338 vec = generateInBoundsCheck(
1339 rewriter, xferOp, iv, unpackedDim(xferOp),
TypeRange(vecType),
1348 getInsertionIndices(xferOp, insertionIndices);
1351 auto inBoundsAttr = dropFirstElem(
b, xferOp.getInBoundsAttr());
1353 auto newXferOp = vector::TransferReadOp::create(
1354 b, loc, newXferVecType, xferOp.getBase(), xferIndices,
1355 AffineMapAttr::get(unpackedPermutationMap(
b, xferOp)),
1356 xferOp.getPadding(),
Value(), inBoundsAttr);
1357 maybeAssignMask(
b, xferOp, newXferOp, i);
1359 Value valToInser = newXferOp.getResult();
1360 if (newXferVecType.getRank() == 0) {
1363 valToInser = vector::ExtractOp::create(
b, loc, valToInser,
1366 return vector::InsertOp::create(
b, loc, valToInser, vec,
1414struct UnrollTransferWriteConversion
1415 :
public VectorToSCFPattern<TransferWriteOp> {
1416 using VectorToSCFPattern<TransferWriteOp>::VectorToSCFPattern;
1421 setHasBoundedRewriteRecursion();
1425 Value getDataVector(TransferWriteOp xferOp)
const {
1426 if (
auto extractOp = getExtractOp(xferOp))
1427 return extractOp.getSource();
1428 return xferOp.getVector();
1432 vector::ExtractOp getExtractOp(TransferWriteOp xferOp)
const {
1433 if (
auto *op = xferOp.getVector().getDefiningOp())
1434 return dyn_cast<vector::ExtractOp>(op);
1435 return vector::ExtractOp();
1440 void getExtractionIndices(TransferWriteOp xferOp,
1442 if (
auto extractOp = getExtractOp(xferOp)) {
1443 auto pos = extractOp.getMixedPosition();
1444 indices.append(pos.begin(), pos.end());
1450 LogicalResult matchAndRewrite(TransferWriteOp xferOp,
1452 VectorType inputVectorTy = xferOp.getVectorType();
1454 if (inputVectorTy.getRank() <=
options.targetRank)
1457 if (failed(checkLowerTensors(xferOp, rewriter)))
1460 if (inputVectorTy.getElementType() !=
1461 xferOp.getShapedType().getElementType())
1464 auto vec = getDataVector(xferOp);
1465 if (inputVectorTy.getScalableDims()[0]) {
1470 int64_t dimSize = inputVectorTy.getShape()[0];
1471 Value source = xferOp.getBase();
1472 auto sourceType = isTensorOp(xferOp) ? xferOp.getShapedType() :
Type();
1476 for (
int64_t i = 0; i < dimSize; ++i) {
1479 auto updatedSource = generateInBoundsCheck(
1480 rewriter, xferOp, iv, unpackedDim(xferOp),
1490 getExtractionIndices(xferOp, extractionIndices);
1491 extractionIndices.push_back(
b.getI64IntegerAttr(i));
1494 vector::ExtractOp::create(
b, loc, vec, extractionIndices);
1495 auto inBoundsAttr = dropFirstElem(
b, xferOp.getInBoundsAttr());
1497 if (inputVectorTy.getRank() == 1) {
1501 xferVec = vector::BroadcastOp::create(
1502 b, loc, VectorType::get({}, extracted.getType()), extracted);
1504 xferVec = extracted;
1506 auto newXferOp = vector::TransferWriteOp::create(
1507 b, loc, sourceType, xferVec, source, xferIndices,
1508 AffineMapAttr::get(unpackedPermutationMap(
b, xferOp)),
Value(),
1511 maybeAssignMask(
b, xferOp, newXferOp, i);
1513 return isTensorOp(xferOp) ? newXferOp->getResult(0) :
Value();
1517 return isTensorOp(xferOp) ? source :
Value();
1520 if (isTensorOp(xferOp))
1521 source = updatedSource;
1524 if (isTensorOp(xferOp))