13c2a74a3SMatthias Springer //===- LinalgTransformOps.cpp - Implementation of Linalg transform ops ----===// 23c2a74a3SMatthias Springer // 33c2a74a3SMatthias Springer // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43c2a74a3SMatthias Springer // See https://llvm.org/LICENSE.txt for license information. 53c2a74a3SMatthias Springer // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63c2a74a3SMatthias Springer // 73c2a74a3SMatthias Springer //===----------------------------------------------------------------------===// 83c2a74a3SMatthias Springer 93c2a74a3SMatthias Springer #include "mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.h" 103c2a74a3SMatthias Springer 113c2a74a3SMatthias Springer #include "mlir/Dialect/Linalg/IR/Linalg.h" 123c2a74a3SMatthias Springer #include "mlir/Dialect/Linalg/Transforms/Transforms.h" 133c2a74a3SMatthias Springer #include "mlir/Dialect/PDL/IR/PDL.h" 143c2a74a3SMatthias Springer #include "mlir/Dialect/PDL/IR/PDLTypes.h" 153c2a74a3SMatthias Springer #include "mlir/Dialect/Transform/IR/TransformDialect.h" 163c2a74a3SMatthias Springer #include "mlir/Parser/Parser.h" 17cc6c1592SAlex Zinenko #include "mlir/Transforms/GreedyPatternRewriteDriver.h" 183c2a74a3SMatthias Springer 193c2a74a3SMatthias Springer using namespace mlir; 203c2a74a3SMatthias Springer using namespace mlir::linalg; 213c2a74a3SMatthias Springer using namespace mlir::transform; 223c2a74a3SMatthias Springer 233c2a74a3SMatthias Springer /// Extracts a vector of int64_t from an array attribute. Asserts if the 243c2a74a3SMatthias Springer /// attribute contains values other than integers. 253c2a74a3SMatthias Springer static SmallVector<int64_t> extractI64Array(ArrayAttr attr) { 263c2a74a3SMatthias Springer SmallVector<int64_t> result; 273c2a74a3SMatthias Springer result.reserve(attr.size()); 283c2a74a3SMatthias Springer for (APInt value : attr.getAsValueRange<IntegerAttr>()) 293c2a74a3SMatthias Springer result.push_back(value.getSExtValue()); 303c2a74a3SMatthias Springer return result; 313c2a74a3SMatthias Springer } 323c2a74a3SMatthias Springer 333c2a74a3SMatthias Springer /// Extracts a vector of unsigned from an array attribute. Asserts if the 343c2a74a3SMatthias Springer /// attribute contains values other than intergers. May truncate. 353c2a74a3SMatthias Springer static SmallVector<unsigned> extractUIntArray(ArrayAttr attr) { 363c2a74a3SMatthias Springer SmallVector<unsigned> result; 373c2a74a3SMatthias Springer result.reserve(attr.size()); 383c2a74a3SMatthias Springer for (APInt value : attr.getAsValueRange<IntegerAttr>()) 393c2a74a3SMatthias Springer result.push_back(value.getZExtValue()); 403c2a74a3SMatthias Springer return result; 413c2a74a3SMatthias Springer } 423c2a74a3SMatthias Springer 433c2a74a3SMatthias Springer namespace { 443c2a74a3SMatthias Springer /// A simple pattern rewriter that implements no special logic. 453c2a74a3SMatthias Springer class SimpleRewriter : public PatternRewriter { 463c2a74a3SMatthias Springer public: 473c2a74a3SMatthias Springer SimpleRewriter(MLIRContext *context) : PatternRewriter(context) {} 483c2a74a3SMatthias Springer }; 493c2a74a3SMatthias Springer } // namespace 503c2a74a3SMatthias Springer 51ce2e198bSAlex Zinenko /// Attempts to apply the pattern specified as template argument to the given 52ce2e198bSAlex Zinenko /// operation. The pattern is expected to have a `returningMatchAndRewrite` 53ce2e198bSAlex Zinenko /// function that returns the "main" result or failure. Returns failure if the 54ce2e198bSAlex Zinenko /// pattern failed to apply. Extra arguments are forwarded to the pattern 55ce2e198bSAlex Zinenko /// constructor. 56ce2e198bSAlex Zinenko template <typename PatternTy, typename... Args> 57ce2e198bSAlex Zinenko static FailureOr<LinalgOp> tryApply(Operation *operation, Args &&...args) { 58ce2e198bSAlex Zinenko // Check if the given operation has the type expected by the pattern. 59ce2e198bSAlex Zinenko using OpTy = typename llvm::function_traits< 60ce2e198bSAlex Zinenko decltype(&PatternTy::returningMatchAndRewrite)>::template arg_t<0>; 61ce2e198bSAlex Zinenko auto op = dyn_cast<OpTy>(operation); 62ce2e198bSAlex Zinenko if (!op) 63ce2e198bSAlex Zinenko return failure(); 64ce2e198bSAlex Zinenko 65ce2e198bSAlex Zinenko // Apply the pattern directly to the op. 66ce2e198bSAlex Zinenko PatternTy pattern(operation->getContext(), std::forward<Args>(args)...); 67ce2e198bSAlex Zinenko SimpleRewriter rewriter(operation->getContext()); 68ce2e198bSAlex Zinenko rewriter.setInsertionPoint(operation); 69ce2e198bSAlex Zinenko auto result = pattern.returningMatchAndRewrite(op, rewriter); 70ce2e198bSAlex Zinenko if (failed(result)) 71ce2e198bSAlex Zinenko return failure(); 72ce2e198bSAlex Zinenko return cast<LinalgOp>(result->getOperation()); 73ce2e198bSAlex Zinenko } 74ce2e198bSAlex Zinenko 75ce2e198bSAlex Zinenko //===----------------------------------------------------------------------===// 76ce2e198bSAlex Zinenko // DecomposeOp 77ce2e198bSAlex Zinenko //===----------------------------------------------------------------------===// 78ce2e198bSAlex Zinenko 79*52307109SNicolas Vasilache DiagnosedSilenceableFailure 80*52307109SNicolas Vasilache transform::DecomposeOp::applyToOne(linalg::LinalgOp target, 81*52307109SNicolas Vasilache SmallVectorImpl<Operation *> &results, 82*52307109SNicolas Vasilache transform::TransformState &state) { 83ce2e198bSAlex Zinenko FailureOr<LinalgOp> windowed = 84ce2e198bSAlex Zinenko tryApply<DownscaleSizeOneWindowed2DConvolution>(target); 85*52307109SNicolas Vasilache if (succeeded(windowed)) { 86*52307109SNicolas Vasilache results.push_back(*windowed); 87*52307109SNicolas Vasilache return DiagnosedSilenceableFailure(success()); 88*52307109SNicolas Vasilache } 89ce2e198bSAlex Zinenko FailureOr<LinalgOp> depthwise = 90ce2e198bSAlex Zinenko tryApply<DownscaleDepthwiseConv2DNhwcHwcOp>(target); 91*52307109SNicolas Vasilache if (succeeded(depthwise)) { 92*52307109SNicolas Vasilache results.push_back(*depthwise); 93*52307109SNicolas Vasilache return DiagnosedSilenceableFailure(success()); 94*52307109SNicolas Vasilache } 95*52307109SNicolas Vasilache results.assign(1, nullptr); 96*52307109SNicolas Vasilache return emitDefaultSilenceableFailure(target); 97ce2e198bSAlex Zinenko } 98ce2e198bSAlex Zinenko 99ce2e198bSAlex Zinenko //===----------------------------------------------------------------------===// 100b6c58ec4SAlex Zinenko // FuseOp 101b6c58ec4SAlex Zinenko //===----------------------------------------------------------------------===// 102b6c58ec4SAlex Zinenko 103b6c58ec4SAlex Zinenko /// Apply a tiling transformation to all payload ops and store both the 104b6c58ec4SAlex Zinenko /// tiled operation as well as the created tile loops. 105b6c58ec4SAlex Zinenko static LogicalResult 106b6c58ec4SAlex Zinenko applyTilingToAll(Operation *transformOp, Value target, 107b6c58ec4SAlex Zinenko ArrayRef<int64_t> tileSizes, 108b6c58ec4SAlex Zinenko transform::TransformResults &transformResults, 109b6c58ec4SAlex Zinenko transform::TransformState &state, 110b6c58ec4SAlex Zinenko function_ref<FailureOr<TiledLinalgOp>(LinalgOp)> applyFn) { 111b6c58ec4SAlex Zinenko // Number of loops: Number of tiles sizes that are not zero. 112b6c58ec4SAlex Zinenko size_t numLoops = tileSizes.size() - llvm::count(tileSizes, 0); 113b6c58ec4SAlex Zinenko // All payload ops. These should all be LinalgOps for now. 114b6c58ec4SAlex Zinenko ArrayRef<Operation *> payloadOps = state.getPayloadOps(target); 115b6c58ec4SAlex Zinenko 116b6c58ec4SAlex Zinenko SmallVector<Operation *> tiledLinalgOps; 117b6c58ec4SAlex Zinenko SmallVector<SmallVector<Operation *>> loopOps(numLoops); 118b6c58ec4SAlex Zinenko for (unsigned int i = 0; i < numLoops; ++i) 119b6c58ec4SAlex Zinenko loopOps[i].reserve(payloadOps.size()); 120b6c58ec4SAlex Zinenko 121b6c58ec4SAlex Zinenko for (Operation *target : payloadOps) { 122b6c58ec4SAlex Zinenko auto linalgOp = dyn_cast<linalg::LinalgOp>(target); 123b6c58ec4SAlex Zinenko if (!linalgOp) 124b6c58ec4SAlex Zinenko return transformOp->emitError("only LinalgOps are supported"); 125b6c58ec4SAlex Zinenko 126b6c58ec4SAlex Zinenko FailureOr<TiledLinalgOp> tiled = applyFn(linalgOp); 127b6c58ec4SAlex Zinenko if (failed(tiled)) 128b6c58ec4SAlex Zinenko return failure(); 129b6c58ec4SAlex Zinenko 130b6c58ec4SAlex Zinenko tiledLinalgOps.push_back(tiled->op); 131b6c58ec4SAlex Zinenko if (tiled->loops.size() != numLoops) 132b6c58ec4SAlex Zinenko // Not enough loops were generated. This usually means that the input size 133b6c58ec4SAlex Zinenko // was smaller than the tiling size. 134b6c58ec4SAlex Zinenko // TODO: LinalgTilingPattern should return failure(). 135b6c58ec4SAlex Zinenko return failure(); 136b6c58ec4SAlex Zinenko for (unsigned int i = 0; i < numLoops; ++i) 137b6c58ec4SAlex Zinenko loopOps[i].push_back(tiled->loops[i]); 138b6c58ec4SAlex Zinenko } 139b6c58ec4SAlex Zinenko 140b6c58ec4SAlex Zinenko transformResults.set(transformOp->getOpResult(0), tiledLinalgOps); 141b6c58ec4SAlex Zinenko for (unsigned int i = 0; i < numLoops; ++i) 142b6c58ec4SAlex Zinenko transformResults.set(transformOp->getOpResult(i + 1), loopOps[i]); 143b6c58ec4SAlex Zinenko return success(); 144b6c58ec4SAlex Zinenko } 145b6c58ec4SAlex Zinenko 146b6c58ec4SAlex Zinenko /// Parse a tiling-like operation that returns the tiled op as well as the 147b6c58ec4SAlex Zinenko /// created tile loops. The function counts the non-zero tile sizes to compute 148b6c58ec4SAlex Zinenko /// the number of results. 149b6c58ec4SAlex Zinenko static ParseResult parseTileLikeOp(OpAsmParser &parser, OperationState &result, 150b6c58ec4SAlex Zinenko StringRef sizesAttrName) { 151b6c58ec4SAlex Zinenko OpAsmParser::UnresolvedOperand targetOperand; 152b6c58ec4SAlex Zinenko SMLoc opLoc = parser.getCurrentLocation(); 153b6c58ec4SAlex Zinenko if (parser.parseOperand(targetOperand) || 154b6c58ec4SAlex Zinenko parser.parseOptionalAttrDict(result.attributes)) 155b6c58ec4SAlex Zinenko return failure(); 156b6c58ec4SAlex Zinenko Attribute sizesAttr = result.attributes.get(sizesAttrName); 157b6c58ec4SAlex Zinenko if (!sizesAttr) 158b6c58ec4SAlex Zinenko return parser.emitError(opLoc) 159b6c58ec4SAlex Zinenko << "expected '" << sizesAttrName << "' attribute"; 160b6c58ec4SAlex Zinenko auto sizesArrayAttr = sizesAttr.dyn_cast<ArrayAttr>(); 161b6c58ec4SAlex Zinenko if (!sizesArrayAttr) 162b6c58ec4SAlex Zinenko return parser.emitError(opLoc) 163b6c58ec4SAlex Zinenko << "'" << sizesAttrName << "' attribute must be an array"; 164b6c58ec4SAlex Zinenko Type pdlOpType = parser.getBuilder().getType<pdl::OperationType>(); 165b6c58ec4SAlex Zinenko size_t numExpectedLoops = 166b6c58ec4SAlex Zinenko sizesArrayAttr.size() - llvm::count(extractI64Array(sizesArrayAttr), 0); 167b6c58ec4SAlex Zinenko result.addTypes(SmallVector<Type>(numExpectedLoops + 1, pdlOpType)); 168b6c58ec4SAlex Zinenko if (parser.resolveOperand(targetOperand, pdlOpType, result.operands)) 169b6c58ec4SAlex Zinenko return failure(); 170b6c58ec4SAlex Zinenko return success(); 171b6c58ec4SAlex Zinenko } 172b6c58ec4SAlex Zinenko 1731d45282aSAlex Zinenko DiagnosedSilenceableFailure 174b6c58ec4SAlex Zinenko transform::FuseOp::apply(mlir::transform::TransformResults &transformResults, 175b6c58ec4SAlex Zinenko mlir::transform::TransformState &state) { 176b6c58ec4SAlex Zinenko LinalgTilingAndFusionOptions fusionOptions; 177b6c58ec4SAlex Zinenko fusionOptions.tileSizes = extractI64Array(getTileSizes()); 178b6c58ec4SAlex Zinenko fusionOptions.tileInterchange = extractI64Array(getTileInterchange()); 179b6c58ec4SAlex Zinenko 180e3890b7fSAlex Zinenko LogicalResult result = applyTilingToAll( 181b6c58ec4SAlex Zinenko getOperation(), getTarget(), fusionOptions.tileSizes, transformResults, 182b6c58ec4SAlex Zinenko state, [&](LinalgOp linalgOp) -> FailureOr<TiledLinalgOp> { 183b6c58ec4SAlex Zinenko LinalgTileAndFuseTensorOpsPattern pattern(getContext(), fusionOptions); 184b6c58ec4SAlex Zinenko SimpleRewriter rewriter(getContext()); 185b6c58ec4SAlex Zinenko rewriter.setInsertionPoint(linalgOp); 186b6c58ec4SAlex Zinenko FailureOr<TileLoopNest> tileLoopNest = 187b6c58ec4SAlex Zinenko pattern.returningMatchAndRewrite(linalgOp, rewriter); 188b6c58ec4SAlex Zinenko if (failed(tileLoopNest)) 189b6c58ec4SAlex Zinenko return failure(); 190b6c58ec4SAlex Zinenko 191b6c58ec4SAlex Zinenko TiledLinalgOp tiledLinalgOp; 192b6c58ec4SAlex Zinenko tiledLinalgOp.op = tileLoopNest->getRootOp(); 193b6c58ec4SAlex Zinenko tiledLinalgOp.loops = {tileLoopNest->getLoopOps().begin(), 194b6c58ec4SAlex Zinenko tileLoopNest->getLoopOps().end()}; 195b6c58ec4SAlex Zinenko return tiledLinalgOp; 196b6c58ec4SAlex Zinenko }); 1971d45282aSAlex Zinenko return failed(result) ? DiagnosedSilenceableFailure::definiteFailure() 1981d45282aSAlex Zinenko : DiagnosedSilenceableFailure::success(); 199b6c58ec4SAlex Zinenko } 200b6c58ec4SAlex Zinenko 201b6c58ec4SAlex Zinenko ParseResult transform::FuseOp::parse(OpAsmParser &parser, 202b6c58ec4SAlex Zinenko OperationState &result) { 203b6c58ec4SAlex Zinenko return parseTileLikeOp( 204b6c58ec4SAlex Zinenko parser, result, 205b6c58ec4SAlex Zinenko transform::FuseOp::getTileSizesAttrName(result.name).getValue()); 206b6c58ec4SAlex Zinenko } 207b6c58ec4SAlex Zinenko 208b6c58ec4SAlex Zinenko void transform::FuseOp::print(OpAsmPrinter &p) { 209b6c58ec4SAlex Zinenko p << ' '; 210b6c58ec4SAlex Zinenko p << getTarget(); 211b6c58ec4SAlex Zinenko p.printOptionalAttrDict((*this)->getAttrs()); 212b6c58ec4SAlex Zinenko } 213b6c58ec4SAlex Zinenko 214b6c58ec4SAlex Zinenko LogicalResult transform::FuseOp::verify() { 215b6c58ec4SAlex Zinenko SmallVector<int64_t> permutation = extractI64Array(getTileInterchange()); 216b6c58ec4SAlex Zinenko auto sequence = llvm::to_vector(llvm::seq<int64_t>(0, permutation.size())); 217b6c58ec4SAlex Zinenko if (!std::is_permutation(sequence.begin(), sequence.end(), 218b6c58ec4SAlex Zinenko permutation.begin(), permutation.end())) { 219b6c58ec4SAlex Zinenko return emitOpError() << "expects interchange to be a permutation, found " 220b6c58ec4SAlex Zinenko << getTileInterchange(); 221b6c58ec4SAlex Zinenko } 222b6c58ec4SAlex Zinenko return success(); 223b6c58ec4SAlex Zinenko } 224b6c58ec4SAlex Zinenko 225b6c58ec4SAlex Zinenko //===----------------------------------------------------------------------===// 226ce2e198bSAlex Zinenko // GeneralizeOp 227ce2e198bSAlex Zinenko //===----------------------------------------------------------------------===// 228ce2e198bSAlex Zinenko 229*52307109SNicolas Vasilache DiagnosedSilenceableFailure 230*52307109SNicolas Vasilache transform::GeneralizeOp::applyToOne(linalg::LinalgOp target, 231*52307109SNicolas Vasilache SmallVectorImpl<Operation *> &results, 232*52307109SNicolas Vasilache transform::TransformState &state) { 233ce2e198bSAlex Zinenko // Exit early if no transformation is needed. 234*52307109SNicolas Vasilache if (isa<GenericOp>(target)) { 235*52307109SNicolas Vasilache results.push_back(target); 236*52307109SNicolas Vasilache return DiagnosedSilenceableFailure(success()); 237*52307109SNicolas Vasilache } 238ce2e198bSAlex Zinenko FailureOr<LinalgOp> generic = tryApply<LinalgGeneralizationPattern>(target); 239*52307109SNicolas Vasilache if (succeeded(generic)) { 240*52307109SNicolas Vasilache results.push_back(generic->getOperation()); 241*52307109SNicolas Vasilache return DiagnosedSilenceableFailure(success()); 242*52307109SNicolas Vasilache } 243*52307109SNicolas Vasilache results.assign(1, nullptr); 244*52307109SNicolas Vasilache return emitDefaultSilenceableFailure(target); 245ce2e198bSAlex Zinenko } 246ce2e198bSAlex Zinenko 2473c2a74a3SMatthias Springer //===----------------------------------------------------------------------===// 2485cde5a57SAlex Zinenko // InterchangeOp 2495cde5a57SAlex Zinenko //===----------------------------------------------------------------------===// 2505cde5a57SAlex Zinenko 251*52307109SNicolas Vasilache DiagnosedSilenceableFailure 252*52307109SNicolas Vasilache transform::InterchangeOp::applyToOne(linalg::GenericOp target, 253*52307109SNicolas Vasilache SmallVectorImpl<Operation *> &results, 254*52307109SNicolas Vasilache transform::TransformState &state) { 2555cde5a57SAlex Zinenko SmallVector<unsigned> interchangeVector = 2565cde5a57SAlex Zinenko extractUIntArray(getIteratorInterchange()); 2575cde5a57SAlex Zinenko // Exit early if no transformation is needed. 258*52307109SNicolas Vasilache if (interchangeVector.empty()) { 259*52307109SNicolas Vasilache results.push_back(target); 260*52307109SNicolas Vasilache return DiagnosedSilenceableFailure(success()); 2615cde5a57SAlex Zinenko } 262*52307109SNicolas Vasilache SimpleRewriter rewriter(target->getContext()); 263*52307109SNicolas Vasilache FailureOr<GenericOp> res = 264*52307109SNicolas Vasilache interchangeGenericOp(rewriter, target, interchangeVector); 265*52307109SNicolas Vasilache if (failed(res)) 266*52307109SNicolas Vasilache return DiagnosedSilenceableFailure::definiteFailure(); 267*52307109SNicolas Vasilache results.push_back(res->getOperation()); 268*52307109SNicolas Vasilache return DiagnosedSilenceableFailure(success()); 2695cde5a57SAlex Zinenko } 2705cde5a57SAlex Zinenko 2715cde5a57SAlex Zinenko LogicalResult transform::InterchangeOp::verify() { 2725cde5a57SAlex Zinenko SmallVector<unsigned> permutation = 2735cde5a57SAlex Zinenko extractUIntArray(getIteratorInterchange()); 2745cde5a57SAlex Zinenko auto sequence = llvm::to_vector(llvm::seq<unsigned>(0, permutation.size())); 2755cde5a57SAlex Zinenko if (!std::is_permutation(sequence.begin(), sequence.end(), 2765cde5a57SAlex Zinenko permutation.begin(), permutation.end())) { 2775cde5a57SAlex Zinenko return emitOpError() 2785cde5a57SAlex Zinenko << "expects iterator_interchange to be a permutation, found " 2795cde5a57SAlex Zinenko << getIteratorInterchange(); 2805cde5a57SAlex Zinenko } 2815cde5a57SAlex Zinenko return success(); 2825cde5a57SAlex Zinenko } 2835cde5a57SAlex Zinenko 2845cde5a57SAlex Zinenko //===---------------------------------------------------------------------===// 2855cde5a57SAlex Zinenko // PadOp 2865cde5a57SAlex Zinenko //===---------------------------------------------------------------------===// 2875cde5a57SAlex Zinenko 288*52307109SNicolas Vasilache DiagnosedSilenceableFailure 289*52307109SNicolas Vasilache transform::PadOp::applyToOne(linalg::LinalgOp target, 290*52307109SNicolas Vasilache SmallVectorImpl<Operation *> &results, 291*52307109SNicolas Vasilache transform::TransformState &state) { 2925cde5a57SAlex Zinenko // Convert the integer packing flags to booleans. 2935cde5a57SAlex Zinenko SmallVector<bool> packPaddings; 2945cde5a57SAlex Zinenko for (int64_t packPadding : extractI64Array(getPackPaddings())) 2955cde5a57SAlex Zinenko packPaddings.push_back(static_cast<bool>(packPadding)); 2965cde5a57SAlex Zinenko 2975cde5a57SAlex Zinenko // Convert the padding values to attributes. 2985cde5a57SAlex Zinenko SmallVector<Attribute> paddingValues; 2995cde5a57SAlex Zinenko for (auto const &it : 3005cde5a57SAlex Zinenko llvm::zip(getPaddingValues(), target->getOperandTypes())) { 3015cde5a57SAlex Zinenko Attribute attr = std::get<0>(it); 3025cde5a57SAlex Zinenko Type elementType = getElementTypeOrSelf(std::get<1>(it)); 3035cde5a57SAlex Zinenko // Try to parse string attributes to obtain an attribute of element type. 3045cde5a57SAlex Zinenko if (auto stringAttr = attr.dyn_cast<StringAttr>()) { 3055cde5a57SAlex Zinenko paddingValues.push_back( 3065cde5a57SAlex Zinenko parseAttribute(attr.cast<StringAttr>(), elementType)); 3075cde5a57SAlex Zinenko if (!paddingValues.back()) { 308*52307109SNicolas Vasilache auto diag = this->emitOpError("expects a padding that parses to ") 3095cde5a57SAlex Zinenko << elementType << ", got " << std::get<0>(it); 3105cde5a57SAlex Zinenko diag.attachNote(target.getLoc()) << "when applied to this op"; 311*52307109SNicolas Vasilache return DiagnosedSilenceableFailure::definiteFailure(); 3125cde5a57SAlex Zinenko } 3135cde5a57SAlex Zinenko continue; 3145cde5a57SAlex Zinenko } 3155cde5a57SAlex Zinenko // Otherwise, add the attribute directly. 3165cde5a57SAlex Zinenko if (attr.getType() != elementType) { 317*52307109SNicolas Vasilache auto diag = this->emitOpError("expects a padding value of type ") 3185cde5a57SAlex Zinenko << elementType << ", got " << attr; 3195cde5a57SAlex Zinenko diag.attachNote(target.getLoc()) << "when applied to this op"; 320*52307109SNicolas Vasilache return DiagnosedSilenceableFailure::definiteFailure(); 3215cde5a57SAlex Zinenko } 3225cde5a57SAlex Zinenko paddingValues.push_back(attr); 3235cde5a57SAlex Zinenko } 3245cde5a57SAlex Zinenko 3255cde5a57SAlex Zinenko // Extract the transpose vectors. 3265cde5a57SAlex Zinenko SmallVector<SmallVector<int64_t>> transposePaddings; 3275cde5a57SAlex Zinenko for (Attribute transposeVector : getTransposePaddings().cast<ArrayAttr>()) 3285cde5a57SAlex Zinenko transposePaddings.push_back( 3295cde5a57SAlex Zinenko extractI64Array(transposeVector.cast<ArrayAttr>())); 3305cde5a57SAlex Zinenko 3315cde5a57SAlex Zinenko LinalgPaddingOptions paddingOptions; 3325cde5a57SAlex Zinenko paddingOptions.setPaddingValues(paddingValues); 3335cde5a57SAlex Zinenko paddingOptions.setPaddingDimensions(extractI64Array(getPaddingDimensions())); 3345cde5a57SAlex Zinenko paddingOptions.setPackPaddings(packPaddings); 3355cde5a57SAlex Zinenko paddingOptions.setHoistPaddings(extractI64Array(getHoistPaddings())); 3365cde5a57SAlex Zinenko paddingOptions.setTransposePaddings(transposePaddings); 3375cde5a57SAlex Zinenko 338ce2e198bSAlex Zinenko FailureOr<LinalgOp> result = 339ce2e198bSAlex Zinenko tryApply<LinalgPaddingPattern>(target, paddingOptions); 340*52307109SNicolas Vasilache if (succeeded(result)) { 341*52307109SNicolas Vasilache results.push_back(result->getOperation()); 342*52307109SNicolas Vasilache return DiagnosedSilenceableFailure(success()); 343*52307109SNicolas Vasilache } 344ce2e198bSAlex Zinenko 345*52307109SNicolas Vasilache results.assign(1, nullptr); 346*52307109SNicolas Vasilache return emitDefaultSilenceableFailure(target); 3475cde5a57SAlex Zinenko } 3485cde5a57SAlex Zinenko 3495cde5a57SAlex Zinenko LogicalResult transform::PadOp::verify() { 3505cde5a57SAlex Zinenko SmallVector<int64_t> packPaddings = extractI64Array(getPackPaddings()); 3515cde5a57SAlex Zinenko if (any_of(packPaddings, [](int64_t packPadding) { 3525cde5a57SAlex Zinenko return packPadding != 0 && packPadding != 1; 3535cde5a57SAlex Zinenko })) { 3545cde5a57SAlex Zinenko return emitOpError() 3555cde5a57SAlex Zinenko << "expects pack_paddings to contain booleans (0/1), found " 3565cde5a57SAlex Zinenko << getPackPaddings(); 3575cde5a57SAlex Zinenko } 3585cde5a57SAlex Zinenko 3595cde5a57SAlex Zinenko SmallVector<int64_t> paddingDimensions = 3605cde5a57SAlex Zinenko extractI64Array(getPaddingDimensions()); 3615cde5a57SAlex Zinenko if (any_of(paddingDimensions, 3625cde5a57SAlex Zinenko [](int64_t paddingDimension) { return paddingDimension < 0; })) { 3635cde5a57SAlex Zinenko return emitOpError() 3645cde5a57SAlex Zinenko << "expects padding_dimensions to contain positive integers, found " 3655cde5a57SAlex Zinenko << getPaddingDimensions(); 3665cde5a57SAlex Zinenko } 3675cde5a57SAlex Zinenko 3685cde5a57SAlex Zinenko SmallVector<int64_t> hoistPaddings = extractI64Array(getHoistPaddings()); 3695cde5a57SAlex Zinenko if (any_of(hoistPaddings, 3705cde5a57SAlex Zinenko [](int64_t hoistPadding) { return hoistPadding < 0; })) { 3715cde5a57SAlex Zinenko return emitOpError() 3725cde5a57SAlex Zinenko << "expects hoist_paddings to contain positive integers, found " 3735cde5a57SAlex Zinenko << getHoistPaddings(); 3745cde5a57SAlex Zinenko } 3755cde5a57SAlex Zinenko 3765cde5a57SAlex Zinenko ArrayAttr transposes = getTransposePaddings(); 3775cde5a57SAlex Zinenko for (Attribute attr : transposes) { 3785cde5a57SAlex Zinenko SmallVector<int64_t> transpose = extractFromI64ArrayAttr(attr); 3795cde5a57SAlex Zinenko auto sequence = llvm::to_vector(llvm::seq<int64_t>(0, transpose.size())); 3805cde5a57SAlex Zinenko if (!std::is_permutation(sequence.begin(), sequence.end(), 3815cde5a57SAlex Zinenko transpose.begin(), transpose.end())) { 3825cde5a57SAlex Zinenko return emitOpError() 3835cde5a57SAlex Zinenko << "expects transpose_paddings to be a permutation, found " 3845cde5a57SAlex Zinenko << attr; 3855cde5a57SAlex Zinenko } 3865cde5a57SAlex Zinenko } 3875cde5a57SAlex Zinenko return success(); 3885cde5a57SAlex Zinenko } 3895cde5a57SAlex Zinenko 3905cde5a57SAlex Zinenko //===----------------------------------------------------------------------===// 3915cde5a57SAlex Zinenko // ScalarizeOp 3925cde5a57SAlex Zinenko //===----------------------------------------------------------------------===// 3935cde5a57SAlex Zinenko 394*52307109SNicolas Vasilache DiagnosedSilenceableFailure 395*52307109SNicolas Vasilache transform::ScalarizeOp::applyToOne(linalg::LinalgOp target, 396*52307109SNicolas Vasilache SmallVectorImpl<Operation *> &results, 397*52307109SNicolas Vasilache transform::TransformState &state) { 3985cde5a57SAlex Zinenko LinalgTilingOptions tilingOptions; 3995cde5a57SAlex Zinenko tilingOptions.scalarizeDynamicDims(); 4005cde5a57SAlex Zinenko // Tiling with "scalarize_dyn_dims" actually sets the same lambda as the tile 4015cde5a57SAlex Zinenko // sizes and asserts that it is not already set. 4025cde5a57SAlex Zinenko SmallVector<int64_t> emptyTileSizes; 4035cde5a57SAlex Zinenko LinalgTilingPattern pattern(getContext(), tilingOptions); 4045cde5a57SAlex Zinenko SimpleRewriter rewriter(getContext()); 4055cde5a57SAlex Zinenko rewriter.setInsertionPoint(target); 4065cde5a57SAlex Zinenko FailureOr<TiledLinalgOp> result = 4075cde5a57SAlex Zinenko pattern.returningMatchAndRewrite(target, rewriter); 4085cde5a57SAlex Zinenko if (failed(result)) 409*52307109SNicolas Vasilache return DiagnosedSilenceableFailure(reportUnknownTransformError(target)); 4105cde5a57SAlex Zinenko 411*52307109SNicolas Vasilache results.push_back(result->op); 412*52307109SNicolas Vasilache return DiagnosedSilenceableFailure(success()); 4135cde5a57SAlex Zinenko } 4145cde5a57SAlex Zinenko 4155cde5a57SAlex Zinenko //===----------------------------------------------------------------------===// 416ff6e5508SAlex Zinenko // SplitOp 417ff6e5508SAlex Zinenko //===----------------------------------------------------------------------===// 418ff6e5508SAlex Zinenko 419ff6e5508SAlex Zinenko DiagnosedSilenceableFailure SplitOp::apply(TransformResults &results, 420ff6e5508SAlex Zinenko TransformState &state) { 421ff6e5508SAlex Zinenko // Collect the dynamic split points if provided. 422ff6e5508SAlex Zinenko ArrayRef<Operation *> payload = state.getPayloadOps(getTarget()); 423ff6e5508SAlex Zinenko SimpleRewriter rewriter(getContext()); 424ff6e5508SAlex Zinenko SmallVector<OpFoldResult> splitPoints; 425ff6e5508SAlex Zinenko splitPoints.reserve(payload.size()); 426ff6e5508SAlex Zinenko if (getDynamicSplitPoint()) { 427ff6e5508SAlex Zinenko auto diag = DiagnosedSilenceableFailure::success(); 428ff6e5508SAlex Zinenko splitPoints = llvm::to_vector(llvm::map_range( 429ff6e5508SAlex Zinenko state.getPayloadOps(getDynamicSplitPoint()), [&](Operation *op) { 430ff6e5508SAlex Zinenko if (op->getNumResults() != 1 || 431ff6e5508SAlex Zinenko !op->getResult(0).getType().isIndex()) { 432ff6e5508SAlex Zinenko diag = emitSilenceableError() 433ff6e5508SAlex Zinenko << "expected dynamic split point handle to point to a " 434ff6e5508SAlex Zinenko "single-result index-typed op"; 435ff6e5508SAlex Zinenko diag.attachNote(op->getLoc()) << "dynamic split point"; 436ff6e5508SAlex Zinenko } 437ff6e5508SAlex Zinenko return OpFoldResult(op->getResult(0)); 438ff6e5508SAlex Zinenko })); 439ff6e5508SAlex Zinenko if (!diag.succeeded()) 440ff6e5508SAlex Zinenko return diag; 441ff6e5508SAlex Zinenko 442ff6e5508SAlex Zinenko if (splitPoints.size() != payload.size()) { 443ff6e5508SAlex Zinenko emitError() << "expected the dynamic split point handle to point to as " 444ff6e5508SAlex Zinenko "many operations (" 445ff6e5508SAlex Zinenko << splitPoints.size() << ") as the target handle (" 446ff6e5508SAlex Zinenko << payload.size() << ")"; 447ff6e5508SAlex Zinenko return DiagnosedSilenceableFailure::definiteFailure(); 448ff6e5508SAlex Zinenko } 449ff6e5508SAlex Zinenko } else { 450ff6e5508SAlex Zinenko splitPoints.resize(payload.size(), 451ff6e5508SAlex Zinenko rewriter.getIndexAttr(getStaticSplitPoint())); 452ff6e5508SAlex Zinenko } 453ff6e5508SAlex Zinenko 454ff6e5508SAlex Zinenko // Split each target operation. 455ff6e5508SAlex Zinenko SmallVector<Operation *> first, second; 456ff6e5508SAlex Zinenko for (const auto &pair : llvm::zip(payload, splitPoints)) { 457ff6e5508SAlex Zinenko Operation *target = std::get<0>(pair); 458ff6e5508SAlex Zinenko auto linalgOp = dyn_cast<LinalgOp>(target); 459ff6e5508SAlex Zinenko if (!linalgOp) { 460ff6e5508SAlex Zinenko auto diag = emitSilenceableError() << "only applies to structured ops"; 461ff6e5508SAlex Zinenko diag.attachNote(target->getLoc()) << "target op"; 462ff6e5508SAlex Zinenko return diag; 463ff6e5508SAlex Zinenko } 464ff6e5508SAlex Zinenko 465ff6e5508SAlex Zinenko if (getDimension() >= linalgOp.getNumLoops()) { 466ff6e5508SAlex Zinenko auto diag = emitSilenceableError() << "dimension " << getDimension() 467ff6e5508SAlex Zinenko << " does not exist in target op"; 468ff6e5508SAlex Zinenko diag.attachNote(target->getLoc()) << "target op"; 469ff6e5508SAlex Zinenko return diag; 470ff6e5508SAlex Zinenko } 471ff6e5508SAlex Zinenko 472ff6e5508SAlex Zinenko rewriter.setInsertionPoint(linalgOp); 473ff6e5508SAlex Zinenko std::tie(first.emplace_back(), second.emplace_back()) = 474ff6e5508SAlex Zinenko linalg::splitOp(rewriter, linalgOp, getDimension(), std::get<1>(pair)); 475ff6e5508SAlex Zinenko } 476ff6e5508SAlex Zinenko 477ff6e5508SAlex Zinenko results.set(getFirst().cast<OpResult>(), first); 478ff6e5508SAlex Zinenko results.set(getSecond().cast<OpResult>(), second); 479ff6e5508SAlex Zinenko return DiagnosedSilenceableFailure::success(); 480ff6e5508SAlex Zinenko } 481ff6e5508SAlex Zinenko 482ff6e5508SAlex Zinenko void SplitOp::getEffects( 483ff6e5508SAlex Zinenko SmallVectorImpl<MemoryEffects::EffectInstance> &effects) { 484ff6e5508SAlex Zinenko // The target handle is consumed. 485ff6e5508SAlex Zinenko effects.emplace_back(MemoryEffects::Read::get(), getTarget(), 486ff6e5508SAlex Zinenko TransformMappingResource::get()); 487ff6e5508SAlex Zinenko effects.emplace_back(MemoryEffects::Free::get(), getTarget(), 488ff6e5508SAlex Zinenko TransformMappingResource::get()); 489ff6e5508SAlex Zinenko 490ff6e5508SAlex Zinenko // The dynamic split point handle is not consumed. 491ff6e5508SAlex Zinenko if (getDynamicSplitPoint()) { 492ff6e5508SAlex Zinenko effects.emplace_back(MemoryEffects::Read::get(), getDynamicSplitPoint(), 493ff6e5508SAlex Zinenko TransformMappingResource::get()); 494ff6e5508SAlex Zinenko } 495ff6e5508SAlex Zinenko 496ff6e5508SAlex Zinenko // The resulting handles are produced. 497ff6e5508SAlex Zinenko for (Value result : getResults()) { 498ff6e5508SAlex Zinenko effects.emplace_back(MemoryEffects::Allocate::get(), result, 499ff6e5508SAlex Zinenko TransformMappingResource::get()); 500ff6e5508SAlex Zinenko effects.emplace_back(MemoryEffects::Write::get(), result, 501ff6e5508SAlex Zinenko TransformMappingResource::get()); 502ff6e5508SAlex Zinenko } 503ff6e5508SAlex Zinenko 504ff6e5508SAlex Zinenko effects.emplace_back(MemoryEffects::Read::get(), PayloadIRResource::get()); 505ff6e5508SAlex Zinenko effects.emplace_back(MemoryEffects::Write::get(), PayloadIRResource::get()); 506ff6e5508SAlex Zinenko } 507ff6e5508SAlex Zinenko 508ff6e5508SAlex Zinenko ParseResult SplitOp::parse(OpAsmParser &parser, OperationState &result) { 509ff6e5508SAlex Zinenko OpAsmParser::UnresolvedOperand target, dynamicSplitPoint; 510ff6e5508SAlex Zinenko IntegerAttr staticSplitPoint; 511ff6e5508SAlex Zinenko auto pdlOperationType = 512ff6e5508SAlex Zinenko pdl::OperationType::get(parser.getBuilder().getContext()); 513ff6e5508SAlex Zinenko if (parser.parseOperand(target) || 514ff6e5508SAlex Zinenko parser.resolveOperand(target, pdlOperationType, result.operands) || 515ff6e5508SAlex Zinenko parser.parseKeyword("after")) 516ff6e5508SAlex Zinenko return failure(); 517ff6e5508SAlex Zinenko 518ff6e5508SAlex Zinenko OptionalParseResult dynamicPointParseResult = 519ff6e5508SAlex Zinenko parser.parseOptionalOperand(dynamicSplitPoint); 520ff6e5508SAlex Zinenko if (!dynamicPointParseResult.hasValue()) { 521ff6e5508SAlex Zinenko int64_t staticSplitPointValue; 522ff6e5508SAlex Zinenko if (failed(parser.parseInteger(staticSplitPointValue))) 523ff6e5508SAlex Zinenko return failure(); 524ff6e5508SAlex Zinenko 525ff6e5508SAlex Zinenko staticSplitPoint = 526ff6e5508SAlex Zinenko parser.getBuilder().getI64IntegerAttr(staticSplitPointValue); 527ff6e5508SAlex Zinenko } else { 528ff6e5508SAlex Zinenko if (failed(*dynamicPointParseResult) || 529ff6e5508SAlex Zinenko parser.resolveOperand(dynamicSplitPoint, pdlOperationType, 530ff6e5508SAlex Zinenko result.operands)) { 531ff6e5508SAlex Zinenko return failure(); 532ff6e5508SAlex Zinenko } 533ff6e5508SAlex Zinenko 534ff6e5508SAlex Zinenko staticSplitPoint = 535ff6e5508SAlex Zinenko parser.getBuilder().getI64IntegerAttr(ShapedType::kDynamicSize); 536ff6e5508SAlex Zinenko } 537ff6e5508SAlex Zinenko 538ff6e5508SAlex Zinenko result.addAttribute( 539ff6e5508SAlex Zinenko SplitOp::getStaticSplitPointAttrName(result.name).getValue(), 540ff6e5508SAlex Zinenko staticSplitPoint); 541ff6e5508SAlex Zinenko if (failed(parser.parseOptionalAttrDict(result.attributes))) 542ff6e5508SAlex Zinenko return failure(); 543ff6e5508SAlex Zinenko 544ff6e5508SAlex Zinenko result.addTypes({pdlOperationType, pdlOperationType}); 545ff6e5508SAlex Zinenko return success(); 546ff6e5508SAlex Zinenko } 547ff6e5508SAlex Zinenko 548ff6e5508SAlex Zinenko void SplitOp::print(OpAsmPrinter &printer) { 549ff6e5508SAlex Zinenko printer << " " << getTarget() << " after "; 550ff6e5508SAlex Zinenko int64_t staticSplitSize = static_cast<int64_t>(getStaticSplitPoint()); 551ff6e5508SAlex Zinenko if (staticSplitSize != ShapedType::kDynamicSize) 552ff6e5508SAlex Zinenko printer << staticSplitSize; 553ff6e5508SAlex Zinenko else 554ff6e5508SAlex Zinenko printer << getDynamicSplitPoint(); 555ff6e5508SAlex Zinenko printer << " "; 556ff6e5508SAlex Zinenko printer.printOptionalAttrDict(getOperation()->getAttrs(), 557ff6e5508SAlex Zinenko {getStaticSplitPointAttrName()}); 558ff6e5508SAlex Zinenko } 559ff6e5508SAlex Zinenko 560ff6e5508SAlex Zinenko LogicalResult SplitOp::verify() { 561ff6e5508SAlex Zinenko if ((static_cast<int64_t>(getStaticSplitPoint()) != 562ff6e5508SAlex Zinenko ShapedType::kDynamicSize) ^ 563ff6e5508SAlex Zinenko (getDynamicSplitPoint() == nullptr)) { 564ff6e5508SAlex Zinenko return emitOpError() 565ff6e5508SAlex Zinenko << "expects either a dynamic or a static split point to be provided"; 566ff6e5508SAlex Zinenko } 567ff6e5508SAlex Zinenko return success(); 568ff6e5508SAlex Zinenko } 569ff6e5508SAlex Zinenko 570ff6e5508SAlex Zinenko //===----------------------------------------------------------------------===// 571f439b319SNicolas Vasilache // SplitReductionOp 572f439b319SNicolas Vasilache //===----------------------------------------------------------------------===// 573f439b319SNicolas Vasilache 574*52307109SNicolas Vasilache DiagnosedSilenceableFailure 575*52307109SNicolas Vasilache transform::SplitReductionOp::applyToOne(linalg::LinalgOp target, 576*52307109SNicolas Vasilache SmallVectorImpl<Operation *> &results, 577*52307109SNicolas Vasilache transform::TransformState &state) { 578f439b319SNicolas Vasilache ControlSplitReductionFn splitFn = [&](LinalgOp) { 579f439b319SNicolas Vasilache return std::pair<int64_t, unsigned>(getSplitFactor(), 580f439b319SNicolas Vasilache getInsertSplitDimension()); 581f439b319SNicolas Vasilache }; 582f439b319SNicolas Vasilache SimpleRewriter rewriter(getContext()); 583f439b319SNicolas Vasilache rewriter.setInsertionPoint(target); 584f439b319SNicolas Vasilache FailureOr<SplitReductionResult> splitResult = 585178f9bd6SNicolas Vasilache (getUseScalingAlgorithm()) 586178f9bd6SNicolas Vasilache ? splitReductionByScaling(rewriter, target, splitFn, getUseAlloc()) 587178f9bd6SNicolas Vasilache : splitReduction(rewriter, target, splitFn, getUseAlloc()); 588d5716395SNicolas Vasilache if (failed(splitResult)) 589*52307109SNicolas Vasilache return DiagnosedSilenceableFailure(reportUnknownTransformError(target)); 590*52307109SNicolas Vasilache 591*52307109SNicolas Vasilache results.push_back(splitResult->initOrAlloc); 592*52307109SNicolas Vasilache results.push_back(splitResult->fillOp); 593*52307109SNicolas Vasilache results.push_back(splitResult->splitLinalgOp); 594*52307109SNicolas Vasilache results.push_back(splitResult->resultCombiningLinalgOp); 595*52307109SNicolas Vasilache return DiagnosedSilenceableFailure(success()); 596d5716395SNicolas Vasilache } 597d5716395SNicolas Vasilache 598d5716395SNicolas Vasilache //===----------------------------------------------------------------------===// 5993c2a74a3SMatthias Springer // TileOp 6003c2a74a3SMatthias Springer //===----------------------------------------------------------------------===// 6013c2a74a3SMatthias Springer 6021d45282aSAlex Zinenko DiagnosedSilenceableFailure 603e3890b7fSAlex Zinenko transform::TileOp::apply(TransformResults &transformResults, 6043c2a74a3SMatthias Springer TransformState &state) { 6053c2a74a3SMatthias Springer LinalgTilingOptions tilingOptions; 6063c2a74a3SMatthias Springer SmallVector<int64_t> tileSizes = extractI64Array(getSizes()); 6073c2a74a3SMatthias Springer 6083c2a74a3SMatthias Springer if (!tileSizes.empty()) 6093c2a74a3SMatthias Springer tilingOptions.setTileSizes(tileSizes); 6103c2a74a3SMatthias Springer tilingOptions.setInterchange(extractUIntArray(getInterchange())); 6113c2a74a3SMatthias Springer LinalgTilingPattern pattern(getContext(), tilingOptions); 6123c2a74a3SMatthias Springer 613e3890b7fSAlex Zinenko LogicalResult result = applyTilingToAll( 614e3890b7fSAlex Zinenko getOperation(), getTarget(), tileSizes, transformResults, state, 615e3890b7fSAlex Zinenko [&](LinalgOp linalgOp) { 6163c2a74a3SMatthias Springer SimpleRewriter rewriter(linalgOp.getContext()); 617e3890b7fSAlex Zinenko return pattern.returningMatchAndRewrite(linalgOp, rewriter); 6183c2a74a3SMatthias Springer }); 6191d45282aSAlex Zinenko return DiagnosedSilenceableFailure(result); 6203c2a74a3SMatthias Springer } 6213c2a74a3SMatthias Springer 6223c2a74a3SMatthias Springer ParseResult transform::TileOp::parse(OpAsmParser &parser, 6233c2a74a3SMatthias Springer OperationState &result) { 624b6c58ec4SAlex Zinenko return parseTileLikeOp(parser, result, 625b6c58ec4SAlex Zinenko TileOp::getSizesAttrName(result.name).getValue()); 6263c2a74a3SMatthias Springer } 6273c2a74a3SMatthias Springer 6283c2a74a3SMatthias Springer void TileOp::print(OpAsmPrinter &p) { 6293c2a74a3SMatthias Springer p << ' '; 6303c2a74a3SMatthias Springer p << getTarget(); 6313c2a74a3SMatthias Springer p.printOptionalAttrDict((*this)->getAttrs()); 6323c2a74a3SMatthias Springer } 6333c2a74a3SMatthias Springer 6343c2a74a3SMatthias Springer //===----------------------------------------------------------------------===// 635cc6c1592SAlex Zinenko // VectorizeOp 636cc6c1592SAlex Zinenko //===----------------------------------------------------------------------===// 637cc6c1592SAlex Zinenko 638*52307109SNicolas Vasilache DiagnosedSilenceableFailure 639*52307109SNicolas Vasilache transform::VectorizeOp::applyToOne(Operation *target, 640*52307109SNicolas Vasilache SmallVectorImpl<Operation *> &results, 641*52307109SNicolas Vasilache transform::TransformState &state) { 642cc6c1592SAlex Zinenko if (!target->hasTrait<OpTrait::IsIsolatedFromAbove>()) { 643*52307109SNicolas Vasilache auto diag = this->emitOpError("requires isolated-from-above targets"); 644cc6c1592SAlex Zinenko diag.attachNote(target->getLoc()) << "non-isolated target"; 645*52307109SNicolas Vasilache return DiagnosedSilenceableFailure::definiteFailure(); 646cc6c1592SAlex Zinenko } 647cc6c1592SAlex Zinenko 648cc6c1592SAlex Zinenko MLIRContext *ctx = getContext(); 649cc6c1592SAlex Zinenko RewritePatternSet patterns(ctx); 650cc6c1592SAlex Zinenko patterns.add<LinalgVectorizationPattern>(ctx); 651cc6c1592SAlex Zinenko 652cc6c1592SAlex Zinenko vector::populateVectorTransferPermutationMapLoweringPatterns(patterns); 653cc6c1592SAlex Zinenko vector::populateVectorReductionToContractPatterns(patterns); 654cc6c1592SAlex Zinenko patterns.add<linalg::LinalgCopyVTRForwardingPattern, 655cc6c1592SAlex Zinenko linalg::LinalgCopyVTWForwardingPattern>(ctx, 656cc6c1592SAlex Zinenko /*benefit=*/2); 657cc6c1592SAlex Zinenko vector::TransferReadOp::getCanonicalizationPatterns(patterns, ctx); 658cc6c1592SAlex Zinenko vector::TransferWriteOp::getCanonicalizationPatterns(patterns, ctx); 659cc6c1592SAlex Zinenko if (getVectorizePadding()) 660cc6c1592SAlex Zinenko linalg::populatePadOpVectorizationPatterns(patterns); 661cc6c1592SAlex Zinenko 6625f0d4f20SAlex Zinenko if (failed(applyPatternsAndFoldGreedily(target, std::move(patterns)))) 663*52307109SNicolas Vasilache return DiagnosedSilenceableFailure(reportUnknownTransformError(target)); 664*52307109SNicolas Vasilache 665*52307109SNicolas Vasilache results.push_back(target); 666*52307109SNicolas Vasilache return DiagnosedSilenceableFailure(success()); 667cc6c1592SAlex Zinenko } 668cc6c1592SAlex Zinenko 669cc6c1592SAlex Zinenko //===----------------------------------------------------------------------===// 6703c2a74a3SMatthias Springer // Transform op registration 6713c2a74a3SMatthias Springer //===----------------------------------------------------------------------===// 6723c2a74a3SMatthias Springer 6733c2a74a3SMatthias Springer namespace { 6743c2a74a3SMatthias Springer /// Registers new ops and declares PDL as dependent dialect since the additional 6753c2a74a3SMatthias Springer /// ops are using PDL types for operands and results. 6763c2a74a3SMatthias Springer class LinalgTransformDialectExtension 6773c2a74a3SMatthias Springer : public transform::TransformDialectExtension< 6783c2a74a3SMatthias Springer LinalgTransformDialectExtension> { 6793c2a74a3SMatthias Springer public: 6803c2a74a3SMatthias Springer LinalgTransformDialectExtension() { 6813c2a74a3SMatthias Springer declareDependentDialect<pdl::PDLDialect>(); 6823c2a74a3SMatthias Springer declareDependentDialect<scf::SCFDialect>(); 683cc6c1592SAlex Zinenko declareDependentDialect<vector::VectorDialect>(); 6843c2a74a3SMatthias Springer registerTransformOps< 6853c2a74a3SMatthias Springer #define GET_OP_LIST 6863c2a74a3SMatthias Springer #include "mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp.inc" 6873c2a74a3SMatthias Springer >(); 6883c2a74a3SMatthias Springer } 6893c2a74a3SMatthias Springer }; 6903c2a74a3SMatthias Springer } // namespace 6913c2a74a3SMatthias Springer 6923c2a74a3SMatthias Springer #define GET_OP_CLASSES 6933c2a74a3SMatthias Springer #include "mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp.inc" 6943c2a74a3SMatthias Springer 6953c2a74a3SMatthias Springer void mlir::linalg::registerTransformDialectExtension( 6963c2a74a3SMatthias Springer DialectRegistry ®istry) { 6973c2a74a3SMatthias Springer registry.addExtensions<LinalgTransformDialectExtension>(); 6983c2a74a3SMatthias Springer } 699