290 assert(scope &&
"Expected op to be inside automatic allocation scope");
295template <
typename OpTy>
296static BufferAllocs allocBuffers(
OpBuilder &
b, OpTy xferOp) {
299 Operation *scope = getAutomaticAllocationScope(xferOp);
301 "AutomaticAllocationScope with >1 regions");
305 auto bufferType = MemRefType::get({}, xferOp.getVectorType());
306 result.dataBuffer = memref::AllocaOp::create(
b, loc, bufferType);
308 if (xferOp.getMask()) {
309 auto maskType = MemRefType::get({}, xferOp.getMask().
getType());
310 auto maskBuffer = memref::AllocaOp::create(
b, loc, maskType);
311 b.setInsertionPoint(xferOp);
312 memref::StoreOp::create(
b, loc, xferOp.getMask(), maskBuffer);
314 memref::LoadOp::create(
b, loc, maskBuffer,
ValueRange());
324static FailureOr<MemRefType> unpackOneDim(MemRefType type) {
325 auto vectorType = dyn_cast<VectorType>(type.getElementType());
328 if (vectorType.getScalableDims().front())
330 auto memrefShape = type.getShape();
332 newMemrefShape.append(memrefShape.begin(), memrefShape.end());
333 newMemrefShape.push_back(vectorType.getDimSize(0));
334 return MemRefType::get(newMemrefShape,
340template <
typename OpTy>
341static Value getMaskBuffer(OpTy xferOp) {
342 assert(xferOp.getMask() &&
"Expected that transfer op has mask");
343 auto loadOp = xferOp.getMask().template getDefiningOp<memref::LoadOp>();
344 assert(loadOp &&
"Expected transfer op mask produced by LoadOp");
345 return loadOp.getMemRef();
349template <
typename OpTy>
354struct Strategy<TransferReadOp> {
357 static memref::StoreOp getStoreOp(TransferReadOp xferOp) {
358 assert(xferOp->hasOneUse() &&
"Expected exactly one use of TransferReadOp");
359 auto storeOp = dyn_cast<memref::StoreOp>((*xferOp->use_begin()).getOwner());
360 assert(storeOp &&
"Expected TransferReadOp result used by StoreOp");
371 static Value getBuffer(TransferReadOp xferOp) {
372 return getStoreOp(xferOp).getMemRef();
376 static void getBufferIndices(TransferReadOp xferOp,
378 auto storeOp = getStoreOp(xferOp);
379 auto prevIndices = memref::StoreOpAdaptor(storeOp).getIndices();
380 indices.append(prevIndices.begin(), prevIndices.end());
412 TransferReadOp xferOp,
Value buffer,
Value iv,
415 getBufferIndices(xferOp, storeIndices);
416 storeIndices.push_back(iv);
422 auto bufferType = dyn_cast<ShapedType>(buffer.
getType());
423 auto vecType = dyn_cast<VectorType>(bufferType.getElementType());
424 auto inBoundsAttr = dropFirstElem(
b, xferOp.getInBoundsAttr());
425 auto newXferOp = vector::TransferReadOp::create(
426 b, loc, vecType, xferOp.getBase(), xferIndices,
427 AffineMapAttr::get(unpackedPermutationMap(
b, xferOp)),
428 xferOp.getPadding(),
Value(), inBoundsAttr);
430 maybeApplyPassLabel(
b, newXferOp,
options.targetRank);
432 memref::StoreOp::create(
b, loc, newXferOp.getVector(), buffer,
443 getBufferIndices(xferOp, storeIndices);
444 storeIndices.push_back(iv);
447 auto bufferType = dyn_cast<ShapedType>(buffer.
getType());
448 auto vecType = dyn_cast<VectorType>(bufferType.getElementType());
450 vector::BroadcastOp::create(
b, loc, vecType, xferOp.getPadding());
451 memref::StoreOp::create(
b, loc, vec, buffer, storeIndices);
459 rewriter.
eraseOp(getStoreOp(xferOp));
464 static Value initialLoopState(TransferReadOp xferOp) {
return Value(); }
469struct Strategy<TransferWriteOp> {
477 static Value getBuffer(TransferWriteOp xferOp) {
478 auto loadOp = xferOp.getVector().
getDefiningOp<memref::LoadOp>();
479 assert(loadOp &&
"Expected transfer op vector produced by LoadOp");
480 return loadOp.getMemRef();
484 static void getBufferIndices(TransferWriteOp xferOp,
486 auto loadOp = xferOp.getVector().getDefiningOp<memref::LoadOp>();
487 auto prevIndices = memref::LoadOpAdaptor(loadOp).getIndices();
488 indices.append(prevIndices.begin(), prevIndices.end());
500 static TransferWriteOp rewriteOp(
OpBuilder &
b,
502 TransferWriteOp xferOp,
Value buffer,
505 getBufferIndices(xferOp, loadIndices);
506 loadIndices.push_back(iv);
512 auto vec = memref::LoadOp::create(
b, loc, buffer, loadIndices);
513 auto inBoundsAttr = dropFirstElem(
b, xferOp.getInBoundsAttr());
514 auto source = loopState.empty() ? xferOp.getBase() : loopState[0];
515 Type type = isTensorOp(xferOp) ? xferOp.getShapedType() :
Type();
516 auto newXferOp = vector::TransferWriteOp::create(
517 b, loc, type, vec, source, xferIndices,
518 AffineMapAttr::get(unpackedPermutationMap(
b, xferOp)),
Value(),
521 maybeApplyPassLabel(
b, newXferOp,
options.targetRank);
527 static Value handleOutOfBoundsDim(
OpBuilder &
b, TransferWriteOp xferOp,
530 return isTensorOp(xferOp) ? loopState[0] :
Value();
536 if (isTensorOp(xferOp)) {
537 assert(forOp->getNumResults() == 1 &&
"Expected one for loop result");
538 rewriter.
replaceOp(xferOp, forOp->getResult(0));
545 static Value initialLoopState(TransferWriteOp xferOp) {
546 return isTensorOp(xferOp) ? xferOp.getBase() :
Value();
550template <
typename OpTy>
551static LogicalResult checkPrepareXferOp(OpTy xferOp,
PatternRewriter &rewriter,
553 if (xferOp->hasDiscardableAttr(kPassLabel))
555 xferOp,
"kPassLabel is present (vector-to-scf lowering in progress)");
556 if (xferOp.getVectorType().getRank() <=
options.targetRank)
558 xferOp,
"xferOp vector rank <= transformation target rank");
559 if (xferOp.getVectorType().getScalableDims().front())
561 xferOp,
"Unpacking of the leading dimension into the memref is not yet "
562 "supported for scalable dims");
563 if (isTensorOp(xferOp) && !
options.lowerTensors)
565 xferOp,
"Unpacking for tensors has been disabled.");
566 if (xferOp.getVectorType().getElementType() !=
567 xferOp.getShapedType().getElementType())
569 xferOp,
"Mismatching source and destination element types.");
573 xferOp,
"xferOp is not inside an automatic allocation scope");
601struct PrepareTransferReadConversion
602 :
public VectorToSCFPattern<TransferReadOp> {
603 using VectorToSCFPattern<TransferReadOp>::VectorToSCFPattern;
605 LogicalResult matchAndRewrite(TransferReadOp xferOp,
607 if (checkPrepareXferOp(xferOp, rewriter,
options).failed())
609 xferOp,
"checkPrepareXferOp conditions not met!");
611 auto buffers = allocBuffers(rewriter, xferOp);
612 auto *newXfer = rewriter.
clone(*xferOp.getOperation());
614 if (xferOp.getMask()) {
615 dyn_cast<TransferReadOp>(newXfer).getMaskMutable().assign(
620 memref::StoreOp::create(rewriter, loc, newXfer->getResult(0),
652struct PrepareTransferWriteConversion
653 :
public VectorToSCFPattern<TransferWriteOp> {
654 using VectorToSCFPattern<TransferWriteOp>::VectorToSCFPattern;
656 LogicalResult matchAndRewrite(TransferWriteOp xferOp,
658 if (checkPrepareXferOp(xferOp, rewriter,
options).failed())
660 xferOp,
"checkPrepareXferOp conditions not met!");
663 auto buffers = allocBuffers(rewriter, xferOp);
664 memref::StoreOp::create(rewriter, loc, xferOp.getVector(),
667 memref::LoadOp::create(rewriter, loc, buffers.dataBuffer,
ValueRange{});
669 xferOp.getValueToStoreMutable().assign(loadedVec);
670 xferOp->setDiscardableAttr(kPassLabel, rewriter.
getUnitAttr());
673 if (xferOp.getMask()) {
675 xferOp.getMaskMutable().assign(buffers.maskBuffer);
710struct DecomposePrintOpConversion :
public VectorToSCFPattern<vector::PrintOp> {
711 using VectorToSCFPattern<vector::PrintOp>::VectorToSCFPattern;
712 LogicalResult matchAndRewrite(vector::PrintOp
printOp,
717 VectorType vectorType = dyn_cast<VectorType>(
printOp.getPrintType());
727 if (vectorType.getRank() > 1 && vectorType.isScalable())
731 auto value =
printOp.getSource();
733 if (
auto intTy = dyn_cast<IntegerType>(vectorType.getElementType())) {
737 auto width = intTy.getWidth();
738 auto legalWidth = llvm::NextPowerOf2(std::max(8u, width) - 1);
739 auto legalIntTy = IntegerType::get(rewriter.
getContext(), legalWidth,
740 intTy.getSignedness());
742 auto signlessSourceVectorType =
743 vectorType.cloneWith({}, getIntTypeWithSignlessSemantics(intTy));
744 auto signlessTargetVectorType =
745 vectorType.cloneWith({}, getIntTypeWithSignlessSemantics(legalIntTy));
746 auto targetVectorType = vectorType.cloneWith({}, legalIntTy);
747 value = vector::BitCastOp::create(rewriter, loc, signlessSourceVectorType,
749 if (value.
getType() != signlessTargetVectorType) {
750 if (width == 1 || intTy.isUnsigned())
751 value = arith::ExtUIOp::create(rewriter, loc,
752 signlessTargetVectorType, value);
754 value = arith::ExtSIOp::create(rewriter, loc,
755 signlessTargetVectorType, value);
757 value = vector::BitCastOp::create(rewriter, loc, targetVectorType, value);
758 vectorType = targetVectorType;
761 auto scalableDimensions = vectorType.getScalableDims();
762 auto shape = vectorType.getShape();
763 constexpr int64_t singletonShape[] = {1};
764 if (vectorType.getRank() == 0)
765 shape = singletonShape;
767 if (vectorType.getRank() != 1) {
771 auto flatVectorType =
772 VectorType::get({flatLength}, vectorType.getElementType());
773 value = vector::ShapeCastOp::create(rewriter, loc, flatVectorType, value);
776 vector::PrintOp firstClose;
778 for (
unsigned d = 0; d <
shape.size(); d++) {
784 if (!scalableDimensions.empty() && scalableDimensions[d]) {
785 auto vscale = vector::VectorScaleOp::create(rewriter, loc,
787 upperBound = arith::MulIOp::create(rewriter, loc, upperBound, vscale);
789 auto lastIndex = arith::SubIOp::create(rewriter, loc, upperBound, step);
792 vector::PrintOp::create(rewriter, loc, vector::PrintPunctuation::Open);
794 scf::ForOp::create(rewriter, loc, lowerBound, upperBound, step);
796 rewriter, loc, vector::PrintPunctuation::Close);
800 auto loopIdx = loop.getInductionVar();
801 loopIndices.push_back(loopIdx);
805 auto notLastIndex = arith::CmpIOp::create(
806 rewriter, loc, arith::CmpIPredicate::ult, loopIdx, lastIndex);
807 scf::IfOp::create(rewriter, loc, notLastIndex,
809 vector::PrintOp::create(
810 builder, loc, vector::PrintPunctuation::Comma);
811 scf::YieldOp::create(builder, loc);
820 auto currentStride = 1;
821 for (
int d =
shape.size() - 1; d >= 0; d--) {
824 auto index = arith::MulIOp::create(rewriter, loc, stride, loopIndices[d]);
826 flatIndex = arith::AddIOp::create(rewriter, loc, flatIndex,
index);
829 currentStride *=
shape[d];
833 auto element = vector::ExtractOp::create(rewriter, loc, value, flatIndex);
834 vector::PrintOp::create(rewriter, loc, element,
835 vector::PrintPunctuation::NoPunctuation);
838 vector::PrintOp::create(rewriter, loc,
printOp.getPunctuation());
843 static IntegerType getIntTypeWithSignlessSemantics(IntegerType intTy) {
844 return IntegerType::get(intTy.getContext(), intTy.getWidth(),
845 IntegerType::Signless);
878template <
typename OpTy>
879struct TransferOpConversion :
public VectorToSCFPattern<OpTy> {
880 using VectorToSCFPattern<OpTy>::VectorToSCFPattern;
885 this->setHasBoundedRewriteRecursion();
888 static void getMaskBufferLoadIndices(OpTy xferOp,
Value castedMaskBuffer,
891 assert(xferOp.getMask() &&
"Expected transfer op to have mask");
897 Value maskBuffer = getMaskBuffer(xferOp);
900 if (
auto loadOp = dyn_cast<memref::LoadOp>(user)) {
902 loadIndices.append(prevIndices.begin(), prevIndices.end());
909 if (!xferOp.isBroadcastDim(0))
910 loadIndices.push_back(iv);
913 LogicalResult matchAndRewrite(OpTy xferOp,
915 if (!xferOp->hasDiscardableAttr(kPassLabel))
917 xferOp,
"kPassLabel is present (progressing lowering in progress)");
921 Value dataBuffer = Strategy<OpTy>::getBuffer(xferOp);
922 auto dataBufferType = dyn_cast<MemRefType>(dataBuffer.
getType());
923 FailureOr<MemRefType> castedDataType = unpackOneDim(dataBufferType);
924 if (failed(castedDataType))
926 "Failed to unpack one vector dim.");
928 auto castedDataBuffer =
929 vector::TypeCastOp::create(locB, *castedDataType, dataBuffer);
932 Value castedMaskBuffer;
933 if (xferOp.getMask()) {
934 Value maskBuffer = getMaskBuffer(xferOp);
935 if (xferOp.isBroadcastDim(0) || xferOp.getMaskType().getRank() == 1) {
941 castedMaskBuffer = maskBuffer;
945 auto maskBufferType = cast<MemRefType>(maskBuffer.
getType());
946 MemRefType castedMaskType = *unpackOneDim(maskBufferType);
948 vector::TypeCastOp::create(locB, castedMaskType, maskBuffer);
955 locB, castedDataType->getDimSize(castedDataType->getRank() - 1));
959 auto loopState = Strategy<OpTy>::initialLoopState(xferOp);
962 auto result = scf::ForOp::create(
967 auto result = generateInBoundsCheck(
968 b, xferOp, iv, unpackedDim(xferOp),
973 OpTy newXfer = Strategy<OpTy>::rewriteOp(
974 b, this->options, xferOp, castedDataBuffer, iv, loopState);
980 if (xferOp.getMask() && (xferOp.isBroadcastDim(0) ||
981 xferOp.getMaskType().getRank() > 1)) {
983 b.setInsertionPoint(newXfer);
986 getMaskBufferLoadIndices(xferOp, castedMaskBuffer,
988 auto mask = memref::LoadOp::create(
b, loc, castedMaskBuffer,
991 newXfer.getMaskMutable().assign(mask);
995 return loopState.empty() ?
Value() : newXfer->getResult(0);
999 return Strategy<OpTy>::handleOutOfBoundsDim(
1000 b, xferOp, castedDataBuffer, iv, loopState);
1003 maybeYieldValue(
b, loc, !loopState.empty(),
result);
1006 Strategy<OpTy>::cleanup(rewriter, xferOp,
result);
1013template <
typename VscaleConstantBuilder>
1014static FailureOr<SmallVector<OpFoldResult>>
1015getMaskDimSizes(
Value mask, VscaleConstantBuilder &createVscaleMultiple) {
1018 if (
auto createMaskOp = mask.getDefiningOp<vector::CreateMaskOp>()) {
1019 return llvm::map_to_vector(createMaskOp.getOperands(), [](
Value dimSize) {
1020 return OpFoldResult(dimSize);
1023 if (
auto constantMask = mask.getDefiningOp<vector::ConstantMaskOp>()) {
1025 VectorType maskType = constantMask.getVectorType();
1026 auto indexType = IndexType::get(mask.getContext());
1027 return llvm::map_to_vector(
1028 constantMask.getMaskDimSizes(), [&](
int64_t dimSize) {
1030 if (maskType.getScalableDims()[dimIdx++])
1031 return OpFoldResult(createVscaleMultiple(dimSize));
1032 return OpFoldResult(IntegerAttr::get(indexType, dimSize));
1075struct ScalableTransposeTransferWriteConversion
1076 : VectorToSCFPattern<vector::TransferWriteOp> {
1077 using VectorToSCFPattern::VectorToSCFPattern;
1079 LogicalResult matchAndRewrite(TransferWriteOp writeOp,
1081 if (failed(checkLowerTensors(writeOp, rewriter)))
1084 VectorType vectorType = writeOp.getVectorType();
1091 writeOp,
"expected vector of the form vector<[N]xMxty>");
1094 auto permutationMap = writeOp.getPermutationMap();
1095 if (!permutationMap.isIdentity()) {
1097 writeOp,
"non-identity permutations are unsupported (lower first)");
1103 if (!writeOp.isDimInBounds(0)) {
1105 writeOp,
"out-of-bounds dims are unsupported (use masking)");
1109 auto transposeOp =
vector.getDefiningOp<vector::TransposeOp>();
1115 auto loc = writeOp.getLoc();
1116 auto createVscaleMultiple =
1119 auto maskDims = getMaskDimSizes(writeOp.getMask(), createVscaleMultiple);
1120 if (failed(maskDims)) {
1122 "failed to resolve mask dims");
1125 int64_t fixedDimSize = vectorType.getDimSize(1);
1126 auto fixedDimOffsets = llvm::seq(fixedDimSize);
1129 auto transposeSource = transposeOp.getVector();
1131 llvm::map_to_vector(fixedDimOffsets, [&](
int64_t idx) ->
Value {
1132 return vector::ExtractOp::create(rewriter, loc, transposeSource, idx);
1139 ?
Value(createVscaleMultiple(vectorType.getDimSize(0)))
1145 Value sliceMask =
nullptr;
1146 if (!maskDims->empty()) {
1147 sliceMask = vector::CreateMaskOp::create(
1148 rewriter, loc, sliceType.clone(rewriter.
getI1Type()),
1152 Value initDest = isTensorOp(writeOp) ? writeOp.getBase() :
Value{};
1154 auto result = scf::ForOp::create(
1155 rewriter, loc, lb,
ub, step, initLoopArgs,
1163 llvm::map_to_vector(fixedDimOffsets, [&](
int64_t idx) ->
Value {
1164 return vector::ExtractOp::create(
1165 b, loc, transposeSourceSlices[idx], iv);
1167 auto sliceVec = vector::FromElementsOp::create(
b, loc, sliceType,
1172 loopIterArgs.empty() ? writeOp.getBase() : loopIterArgs.front();
1173 auto newWriteOp = vector::TransferWriteOp::create(
1174 b, loc, sliceVec, dest, xferIndices,
1177 newWriteOp.getMaskMutable().assign(sliceMask);
1180 scf::YieldOp::create(
b, loc,
1182 : newWriteOp.getResult());
1185 if (isTensorOp(writeOp))
1200template <
typename OpTy>
1201static void maybeAssignMask(
OpBuilder &
b, OpTy xferOp, OpTy newXferOp,
1203 if (!xferOp.getMask())
1206 if (xferOp.isBroadcastDim(0)) {
1209 newXferOp.getMaskMutable().assign(xferOp.getMask());
1213 if (xferOp.getMaskType().getRank() > 1) {
1216 b.setInsertionPoint(newXferOp);
1220 auto newMask = vector::ExtractOp::create(
b, loc, xferOp.getMask(),
indices);
1221 newXferOp.getMaskMutable().assign(newMask);
1257struct UnrollTransferReadConversion
1258 :
public VectorToSCFPattern<TransferReadOp> {
1259 using VectorToSCFPattern<TransferReadOp>::VectorToSCFPattern;
1264 setHasBoundedRewriteRecursion();
1270 TransferReadOp xferOp)
const {
1271 if (
auto insertOp = getInsertOp(xferOp))
1272 return insertOp.getDest();
1274 return vector::BroadcastOp::create(rewriter, loc, xferOp.getVectorType(),
1275 xferOp.getPadding());
1280 vector::InsertOp getInsertOp(TransferReadOp xferOp)
const {
1281 if (xferOp->hasOneUse()) {
1283 if (
auto insertOp = dyn_cast<vector::InsertOp>(xferOpUser))
1287 return vector::InsertOp();
1292 void getInsertionIndices(TransferReadOp xferOp,
1294 if (
auto insertOp = getInsertOp(xferOp)) {
1295 auto pos = insertOp.getMixedPosition();
1296 indices.append(pos.begin(), pos.end());
1302 LogicalResult matchAndRewrite(TransferReadOp xferOp,
1304 if (xferOp.getVectorType().getRank() <=
options.targetRank)
1306 xferOp,
"vector rank is less or equal to target rank");
1307 if (failed(checkLowerTensors(xferOp, rewriter)))
1309 if (xferOp.getVectorType().getElementType() !=
1310 xferOp.getShapedType().getElementType())
1312 xferOp,
"not yet supported: element type mismatch");
1313 auto xferVecType = xferOp.getVectorType();
1314 if (xferVecType.getScalableDims()[0]) {
1316 xferOp,
"scalable dimensions cannot be unrolled at compile time");
1319 auto insertOp = getInsertOp(xferOp);
1320 auto vec = buildResultVector(rewriter, xferOp);
1321 auto vecType = dyn_cast<VectorType>(vec.getType());
1325 int64_t dimSize = xferVecType.getShape()[0];
1329 for (
int64_t i = 0; i < dimSize; ++i) {
1334 vec = generateInBoundsCheck(
1335 rewriter, xferOp, iv, unpackedDim(xferOp),
TypeRange(vecType),
1344 getInsertionIndices(xferOp, insertionIndices);
1347 auto inBoundsAttr = dropFirstElem(
b, xferOp.getInBoundsAttr());
1349 auto newXferOp = vector::TransferReadOp::create(
1350 b, loc, newXferVecType, xferOp.getBase(), xferIndices,
1351 AffineMapAttr::get(unpackedPermutationMap(
b, xferOp)),
1352 xferOp.getPadding(),
Value(), inBoundsAttr);
1353 maybeAssignMask(
b, xferOp, newXferOp, i);
1355 Value valToInser = newXferOp.getResult();
1356 if (newXferVecType.getRank() == 0) {
1359 valToInser = vector::ExtractOp::create(
b, loc, valToInser,
1362 return vector::InsertOp::create(
b, loc, valToInser, vec,
1410struct UnrollTransferWriteConversion
1411 :
public VectorToSCFPattern<TransferWriteOp> {
1412 using VectorToSCFPattern<TransferWriteOp>::VectorToSCFPattern;
1417 setHasBoundedRewriteRecursion();
1421 Value getDataVector(TransferWriteOp xferOp)
const {
1422 if (
auto extractOp = getExtractOp(xferOp))
1423 return extractOp.getSource();
1424 return xferOp.getVector();
1428 vector::ExtractOp getExtractOp(TransferWriteOp xferOp)
const {
1429 if (
auto *op = xferOp.getVector().getDefiningOp())
1430 return dyn_cast<vector::ExtractOp>(op);
1431 return vector::ExtractOp();
1436 void getExtractionIndices(TransferWriteOp xferOp,
1438 if (
auto extractOp = getExtractOp(xferOp)) {
1439 auto pos = extractOp.getMixedPosition();
1440 indices.append(pos.begin(), pos.end());
1446 LogicalResult matchAndRewrite(TransferWriteOp xferOp,
1448 VectorType inputVectorTy = xferOp.getVectorType();
1450 if (inputVectorTy.getRank() <=
options.targetRank)
1453 if (failed(checkLowerTensors(xferOp, rewriter)))
1456 if (inputVectorTy.getElementType() !=
1457 xferOp.getShapedType().getElementType())
1460 auto vec = getDataVector(xferOp);
1461 if (inputVectorTy.getScalableDims()[0]) {
1466 int64_t dimSize = inputVectorTy.getShape()[0];
1467 Value source = xferOp.getBase();
1468 auto sourceType = isTensorOp(xferOp) ? xferOp.getShapedType() :
Type();
1472 for (
int64_t i = 0; i < dimSize; ++i) {
1475 auto updatedSource = generateInBoundsCheck(
1476 rewriter, xferOp, iv, unpackedDim(xferOp),
1486 getExtractionIndices(xferOp, extractionIndices);
1487 extractionIndices.push_back(
b.getI64IntegerAttr(i));
1490 vector::ExtractOp::create(
b, loc, vec, extractionIndices);
1491 auto inBoundsAttr = dropFirstElem(
b, xferOp.getInBoundsAttr());
1493 if (inputVectorTy.getRank() == 1) {
1497 xferVec = vector::BroadcastOp::create(
1498 b, loc, VectorType::get({}, extracted.getType()), extracted);
1500 xferVec = extracted;
1502 auto newXferOp = vector::TransferWriteOp::create(
1503 b, loc, sourceType, xferVec, source, xferIndices,
1504 AffineMapAttr::get(unpackedPermutationMap(
b, xferOp)),
Value(),
1507 maybeAssignMask(
b, xferOp, newXferOp, i);
1509 return isTensorOp(xferOp) ? newXferOp->getResult(0) :
Value();
1513 return isTensorOp(xferOp) ? source :
Value();
1516 if (isTensorOp(xferOp))
1517 source = updatedSource;
1520 if (isTensorOp(xferOp))