[Mlir-commits] [mlir] [mlir] Add direct vectorization lowering for `tensor.pack` ops (PR #78660)
Han-Chung Wang
llvmlistbot at llvm.org
Sun Feb 4 21:45:08 PST 2024
================
@@ -1393,6 +1401,169 @@ vectorizeAsLinalgGeneric(RewriterBase &rewriter, VectorizationState &state,
return success();
}
+/// Given a tensor::PackOp, return the `dest` shape before any packing
+/// permutations.
+static SmallVector<int64_t> getTiledPackShape(tensor::PackOp packOp,
+ ArrayRef<int64_t> destShape) {
+ return applyPermutation(destShape,
+ tensor::getPackInverseDestPermutation(packOp));
+}
+
+/// Create a TransferReadOp from `source` with static shape `readShape`. If the
+/// vector type for the read is not the same as the type of `source`, then a
+/// mask is created on the read.
+static Value createReadOrMaskedRead(OpBuilder &builder, Location loc,
+ Value source, ArrayRef<int64_t> readShape,
+ Value padValue) {
+ assert(llvm::none_of(readShape,
+ [](int64_t s) { return s == ShapedType::kDynamic; }));
+ auto maskType = VectorType::get(readShape, builder.getI1Type());
+ auto vectorType = VectorType::get(readShape, padValue.getType());
+ int64_t readRank = readShape.size();
+ auto zero = builder.create<arith::ConstantIndexOp>(loc, 0);
+ auto transferReadOp = builder.create<vector::TransferReadOp>(
+ loc,
+ /*vectorType=*/vectorType,
+ /*source=*/source,
+ /*indices=*/SmallVector<Value>(readRank, zero),
+ /*padding=*/padValue,
+ /*inBounds=*/SmallVector<bool>(readRank, true));
+ auto sourceShape = llvm::dyn_cast<ShapedType>(source.getType()).getShape();
+ if (sourceShape.size() == readShape.size() &&
+ llvm::all_of(llvm::zip_equal(readShape, sourceShape), [](auto it) {
+ return std::get<0>(it) != ShapedType::kDynamic &&
+ std::get<0>(it) == std::get<1>(it);
+ })) {
+ return transferReadOp;
+ }
+ SmallVector<OpFoldResult> mixedSourceDims =
+ tensor::getMixedSizes(builder, loc, source);
+ Value mask =
+ builder.create<vector::CreateMaskOp>(loc, maskType, mixedSourceDims);
+ return mlir::vector::maskOperation(builder, transferReadOp, mask)
+ ->getResult(0);
+}
+
+/// Given an input, the mixed destSizes, and the vector sizes for vectorization,
+/// create an empty destination tensor and create a TransferWriteOp from the
+/// input to the empty tensor. If the destination shape is not the same as the
+/// inputVectorSizes for the first rank(inputVectorSizes) dims, then create a
+/// mask for the write.
+static Operation *createWriteOrMaskedWrite(OpBuilder &builder, Location loc,
+ Value input,
+ SmallVector<OpFoldResult> destSizes,
+ ArrayRef<int64_t> inputVectorSizes) {
+ auto inputType = cast<VectorType>(input.getType());
+ Value dest = builder.create<tensor::EmptyOp>(loc, destSizes,
+ inputType.getElementType());
+ int64_t rank = cast<ShapedType>(dest.getType()).getRank();
+ auto zero = builder.create<arith::ConstantIndexOp>(loc, 0);
+ Operation *write = builder.create<vector::TransferWriteOp>(
+ loc,
+ /*vector=*/input,
+ /*source=*/dest,
+ /*indices=*/SmallVector<Value>(rank, zero),
+ /*inBounds=*/SmallVector<bool>(rank, true));
+ auto destShape = cast<ShapedType>(dest.getType()).getShape();
+ assert(llvm::none_of(
+ destShape.drop_front(inputVectorSizes.size()),
+ [](int64_t size) { return size == ShapedType::kDynamic; }) &&
+ "Only dims aligned with inputVectorSizes may be dynamic");
+ bool needMaskForWrite = llvm::any_of(
+ llvm::zip_equal(inputVectorSizes,
+ destShape.take_front(inputVectorSizes.size())),
+ [](auto it) { return std::get<0>(it) != std::get<1>(it); });
----------------
hanhanW wrote:
Can we replace the lambda with `std::not_equal_to<int64_t>()`?
https://github.com/llvm/llvm-project/pull/78660
More information about the Mlir-commits
mailing list