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/Interfaces/SideEffectInterfaces.h"
173c2a74a3SMatthias Springer #include "mlir/Parser/Parser.h"
183c2a74a3SMatthias Springer #include "llvm/Support/FormatVariadic.h"
193c2a74a3SMatthias Springer 
203c2a74a3SMatthias Springer using namespace mlir;
213c2a74a3SMatthias Springer using namespace mlir::linalg;
223c2a74a3SMatthias Springer using namespace mlir::transform;
233c2a74a3SMatthias Springer 
243c2a74a3SMatthias Springer /// Extracts a vector of int64_t from an array attribute. Asserts if the
253c2a74a3SMatthias Springer /// attribute contains values other than integers.
263c2a74a3SMatthias Springer static SmallVector<int64_t> extractI64Array(ArrayAttr attr) {
273c2a74a3SMatthias Springer   SmallVector<int64_t> result;
283c2a74a3SMatthias Springer   result.reserve(attr.size());
293c2a74a3SMatthias Springer   for (APInt value : attr.getAsValueRange<IntegerAttr>())
303c2a74a3SMatthias Springer     result.push_back(value.getSExtValue());
313c2a74a3SMatthias Springer   return result;
323c2a74a3SMatthias Springer }
333c2a74a3SMatthias Springer 
343c2a74a3SMatthias Springer /// Extracts a vector of unsigned from an array attribute. Asserts if the
353c2a74a3SMatthias Springer /// attribute contains values other than intergers. May truncate.
363c2a74a3SMatthias Springer static SmallVector<unsigned> extractUIntArray(ArrayAttr attr) {
373c2a74a3SMatthias Springer   SmallVector<unsigned> result;
383c2a74a3SMatthias Springer   result.reserve(attr.size());
393c2a74a3SMatthias Springer   for (APInt value : attr.getAsValueRange<IntegerAttr>())
403c2a74a3SMatthias Springer     result.push_back(value.getZExtValue());
413c2a74a3SMatthias Springer   return result;
423c2a74a3SMatthias Springer }
433c2a74a3SMatthias Springer 
443c2a74a3SMatthias Springer namespace {
453c2a74a3SMatthias Springer /// A simple pattern rewriter that implements no special logic.
463c2a74a3SMatthias Springer class SimpleRewriter : public PatternRewriter {
473c2a74a3SMatthias Springer public:
483c2a74a3SMatthias Springer   SimpleRewriter(MLIRContext *context) : PatternRewriter(context) {}
493c2a74a3SMatthias Springer };
503c2a74a3SMatthias Springer } // namespace
513c2a74a3SMatthias Springer 
523c2a74a3SMatthias Springer //===----------------------------------------------------------------------===//
53*5cde5a57SAlex Zinenko // InterchangeOp
54*5cde5a57SAlex Zinenko //===----------------------------------------------------------------------===//
55*5cde5a57SAlex Zinenko 
56*5cde5a57SAlex Zinenko FailureOr<LinalgOp> transform::InterchangeOp::applyToOne(LinalgOp target) {
57*5cde5a57SAlex Zinenko   SmallVector<unsigned> interchangeVector =
58*5cde5a57SAlex Zinenko       extractUIntArray(getIteratorInterchange());
59*5cde5a57SAlex Zinenko   // Exit early if no transformation is needed.
60*5cde5a57SAlex Zinenko   if (interchangeVector.empty())
61*5cde5a57SAlex Zinenko     return target;
62*5cde5a57SAlex Zinenko 
63*5cde5a57SAlex Zinenko   auto genericTarget = dyn_cast<GenericOp>(target.getOperation());
64*5cde5a57SAlex Zinenko   if (!genericTarget) {
65*5cde5a57SAlex Zinenko     InFlightDiagnostic diag = emitOpError()
66*5cde5a57SAlex Zinenko                               << "applies to " << GenericOp::getOperationName()
67*5cde5a57SAlex Zinenko                               << " ops";
68*5cde5a57SAlex Zinenko     diag.attachNote(target.getLoc()) << "attempted to apply to this op";
69*5cde5a57SAlex Zinenko     return diag;
70*5cde5a57SAlex Zinenko   }
71*5cde5a57SAlex Zinenko 
72*5cde5a57SAlex Zinenko   GenericOpInterchangePattern pattern(getContext(), interchangeVector);
73*5cde5a57SAlex Zinenko   SimpleRewriter rewriter(getContext());
74*5cde5a57SAlex Zinenko   rewriter.setInsertionPoint(target);
75*5cde5a57SAlex Zinenko   FailureOr<GenericOp> result =
76*5cde5a57SAlex Zinenko       pattern.returningMatchAndRewrite(genericTarget, rewriter);
77*5cde5a57SAlex Zinenko   if (failed(result))
78*5cde5a57SAlex Zinenko     return failure();
79*5cde5a57SAlex Zinenko 
80*5cde5a57SAlex Zinenko   return cast<LinalgOp>(result->getOperation());
81*5cde5a57SAlex Zinenko }
82*5cde5a57SAlex Zinenko 
83*5cde5a57SAlex Zinenko LogicalResult transform::InterchangeOp::verify() {
84*5cde5a57SAlex Zinenko   SmallVector<unsigned> permutation =
85*5cde5a57SAlex Zinenko       extractUIntArray(getIteratorInterchange());
86*5cde5a57SAlex Zinenko   auto sequence = llvm::to_vector(llvm::seq<unsigned>(0, permutation.size()));
87*5cde5a57SAlex Zinenko   if (!std::is_permutation(sequence.begin(), sequence.end(),
88*5cde5a57SAlex Zinenko                            permutation.begin(), permutation.end())) {
89*5cde5a57SAlex Zinenko     return emitOpError()
90*5cde5a57SAlex Zinenko            << "expects iterator_interchange to be a permutation, found "
91*5cde5a57SAlex Zinenko            << getIteratorInterchange();
92*5cde5a57SAlex Zinenko   }
93*5cde5a57SAlex Zinenko   return success();
94*5cde5a57SAlex Zinenko }
95*5cde5a57SAlex Zinenko 
96*5cde5a57SAlex Zinenko //===---------------------------------------------------------------------===//
97*5cde5a57SAlex Zinenko // PadOp
98*5cde5a57SAlex Zinenko //===---------------------------------------------------------------------===//
99*5cde5a57SAlex Zinenko 
100*5cde5a57SAlex Zinenko FailureOr<LinalgOp> transform::PadOp::applyToOne(LinalgOp target) {
101*5cde5a57SAlex Zinenko   // Convert the integer packing flags to booleans.
102*5cde5a57SAlex Zinenko   SmallVector<bool> packPaddings;
103*5cde5a57SAlex Zinenko   for (int64_t packPadding : extractI64Array(getPackPaddings()))
104*5cde5a57SAlex Zinenko     packPaddings.push_back(static_cast<bool>(packPadding));
105*5cde5a57SAlex Zinenko 
106*5cde5a57SAlex Zinenko   // Convert the padding values to attributes.
107*5cde5a57SAlex Zinenko   SmallVector<Attribute> paddingValues;
108*5cde5a57SAlex Zinenko   for (auto const &it :
109*5cde5a57SAlex Zinenko        llvm::zip(getPaddingValues(), target->getOperandTypes())) {
110*5cde5a57SAlex Zinenko     Attribute attr = std::get<0>(it);
111*5cde5a57SAlex Zinenko     Type elementType = getElementTypeOrSelf(std::get<1>(it));
112*5cde5a57SAlex Zinenko     // Try to parse string attributes to obtain an attribute of element type.
113*5cde5a57SAlex Zinenko     if (auto stringAttr = attr.dyn_cast<StringAttr>()) {
114*5cde5a57SAlex Zinenko       paddingValues.push_back(
115*5cde5a57SAlex Zinenko           parseAttribute(attr.cast<StringAttr>(), elementType));
116*5cde5a57SAlex Zinenko       if (!paddingValues.back()) {
117*5cde5a57SAlex Zinenko         InFlightDiagnostic diag = emitOpError()
118*5cde5a57SAlex Zinenko                                   << "expects a padding value that parses to "
119*5cde5a57SAlex Zinenko                                   << elementType << ", got " << std::get<0>(it);
120*5cde5a57SAlex Zinenko         diag.attachNote(target.getLoc()) << "when applied to this op";
121*5cde5a57SAlex Zinenko         return diag;
122*5cde5a57SAlex Zinenko       }
123*5cde5a57SAlex Zinenko       continue;
124*5cde5a57SAlex Zinenko     }
125*5cde5a57SAlex Zinenko     // Otherwise, add the attribute directly.
126*5cde5a57SAlex Zinenko     if (attr.getType() != elementType) {
127*5cde5a57SAlex Zinenko       InFlightDiagnostic diag = emitOpError()
128*5cde5a57SAlex Zinenko                                 << "expects a padding value of type "
129*5cde5a57SAlex Zinenko                                 << elementType << ", got " << attr;
130*5cde5a57SAlex Zinenko       diag.attachNote(target.getLoc()) << "when applied to this op";
131*5cde5a57SAlex Zinenko       return diag;
132*5cde5a57SAlex Zinenko     }
133*5cde5a57SAlex Zinenko     paddingValues.push_back(attr);
134*5cde5a57SAlex Zinenko   }
135*5cde5a57SAlex Zinenko 
136*5cde5a57SAlex Zinenko   // Extract the transpose vectors.
137*5cde5a57SAlex Zinenko   SmallVector<SmallVector<int64_t>> transposePaddings;
138*5cde5a57SAlex Zinenko   for (Attribute transposeVector : getTransposePaddings().cast<ArrayAttr>())
139*5cde5a57SAlex Zinenko     transposePaddings.push_back(
140*5cde5a57SAlex Zinenko         extractI64Array(transposeVector.cast<ArrayAttr>()));
141*5cde5a57SAlex Zinenko 
142*5cde5a57SAlex Zinenko   LinalgPaddingOptions paddingOptions;
143*5cde5a57SAlex Zinenko   paddingOptions.setPaddingValues(paddingValues);
144*5cde5a57SAlex Zinenko   paddingOptions.setPaddingDimensions(extractI64Array(getPaddingDimensions()));
145*5cde5a57SAlex Zinenko   paddingOptions.setPackPaddings(packPaddings);
146*5cde5a57SAlex Zinenko   paddingOptions.setHoistPaddings(extractI64Array(getHoistPaddings()));
147*5cde5a57SAlex Zinenko   paddingOptions.setTransposePaddings(transposePaddings);
148*5cde5a57SAlex Zinenko 
149*5cde5a57SAlex Zinenko   LinalgPaddingPattern pattern(getContext(), paddingOptions);
150*5cde5a57SAlex Zinenko   SimpleRewriter rewriter(getContext());
151*5cde5a57SAlex Zinenko   rewriter.setInsertionPoint(target);
152*5cde5a57SAlex Zinenko   FailureOr<LinalgOp> patternResult =
153*5cde5a57SAlex Zinenko       pattern.returningMatchAndRewrite(target, rewriter);
154*5cde5a57SAlex Zinenko   if (failed(patternResult)) {
155*5cde5a57SAlex Zinenko     InFlightDiagnostic diag = emitError()
156*5cde5a57SAlex Zinenko                               << "failed to apply pattern to target op";
157*5cde5a57SAlex Zinenko     diag.attachNote(target.getLoc()) << "target op";
158*5cde5a57SAlex Zinenko     return diag;
159*5cde5a57SAlex Zinenko   }
160*5cde5a57SAlex Zinenko   return patternResult;
161*5cde5a57SAlex Zinenko }
162*5cde5a57SAlex Zinenko 
163*5cde5a57SAlex Zinenko LogicalResult transform::PadOp::verify() {
164*5cde5a57SAlex Zinenko   SmallVector<int64_t> packPaddings = extractI64Array(getPackPaddings());
165*5cde5a57SAlex Zinenko   if (any_of(packPaddings, [](int64_t packPadding) {
166*5cde5a57SAlex Zinenko         return packPadding != 0 && packPadding != 1;
167*5cde5a57SAlex Zinenko       })) {
168*5cde5a57SAlex Zinenko     return emitOpError()
169*5cde5a57SAlex Zinenko            << "expects pack_paddings to contain booleans (0/1), found "
170*5cde5a57SAlex Zinenko            << getPackPaddings();
171*5cde5a57SAlex Zinenko   }
172*5cde5a57SAlex Zinenko 
173*5cde5a57SAlex Zinenko   SmallVector<int64_t> paddingDimensions =
174*5cde5a57SAlex Zinenko       extractI64Array(getPaddingDimensions());
175*5cde5a57SAlex Zinenko   if (any_of(paddingDimensions,
176*5cde5a57SAlex Zinenko              [](int64_t paddingDimension) { return paddingDimension < 0; })) {
177*5cde5a57SAlex Zinenko     return emitOpError()
178*5cde5a57SAlex Zinenko            << "expects padding_dimensions to contain positive integers, found "
179*5cde5a57SAlex Zinenko            << getPaddingDimensions();
180*5cde5a57SAlex Zinenko   }
181*5cde5a57SAlex Zinenko 
182*5cde5a57SAlex Zinenko   SmallVector<int64_t> hoistPaddings = extractI64Array(getHoistPaddings());
183*5cde5a57SAlex Zinenko   if (any_of(hoistPaddings,
184*5cde5a57SAlex Zinenko              [](int64_t hoistPadding) { return hoistPadding < 0; })) {
185*5cde5a57SAlex Zinenko     return emitOpError()
186*5cde5a57SAlex Zinenko            << "expects hoist_paddings to contain positive integers, found "
187*5cde5a57SAlex Zinenko            << getHoistPaddings();
188*5cde5a57SAlex Zinenko   }
189*5cde5a57SAlex Zinenko 
190*5cde5a57SAlex Zinenko   ArrayAttr transposes = getTransposePaddings();
191*5cde5a57SAlex Zinenko   for (Attribute attr : transposes) {
192*5cde5a57SAlex Zinenko     SmallVector<int64_t> transpose = extractFromI64ArrayAttr(attr);
193*5cde5a57SAlex Zinenko     auto sequence = llvm::to_vector(llvm::seq<int64_t>(0, transpose.size()));
194*5cde5a57SAlex Zinenko     if (!std::is_permutation(sequence.begin(), sequence.end(),
195*5cde5a57SAlex Zinenko                              transpose.begin(), transpose.end())) {
196*5cde5a57SAlex Zinenko       return emitOpError()
197*5cde5a57SAlex Zinenko              << "expects transpose_paddings to be a permutation, found "
198*5cde5a57SAlex Zinenko              << attr;
199*5cde5a57SAlex Zinenko     }
200*5cde5a57SAlex Zinenko   }
201*5cde5a57SAlex Zinenko   return success();
202*5cde5a57SAlex Zinenko }
203*5cde5a57SAlex Zinenko 
204*5cde5a57SAlex Zinenko //===----------------------------------------------------------------------===//
205*5cde5a57SAlex Zinenko // ScalarizeOp
206*5cde5a57SAlex Zinenko //===----------------------------------------------------------------------===//
207*5cde5a57SAlex Zinenko 
208*5cde5a57SAlex Zinenko FailureOr<LinalgOp> transform::ScalarizeOp::applyToOne(LinalgOp target) {
209*5cde5a57SAlex Zinenko   LinalgTilingOptions tilingOptions;
210*5cde5a57SAlex Zinenko   tilingOptions.scalarizeDynamicDims();
211*5cde5a57SAlex Zinenko   // Tiling with "scalarize_dyn_dims" actually sets the same lambda as the tile
212*5cde5a57SAlex Zinenko   // sizes and asserts that it is not already set.
213*5cde5a57SAlex Zinenko   SmallVector<int64_t> emptyTileSizes;
214*5cde5a57SAlex Zinenko   LinalgTilingPattern pattern(getContext(), tilingOptions);
215*5cde5a57SAlex Zinenko   SimpleRewriter rewriter(getContext());
216*5cde5a57SAlex Zinenko   rewriter.setInsertionPoint(target);
217*5cde5a57SAlex Zinenko   FailureOr<TiledLinalgOp> result =
218*5cde5a57SAlex Zinenko       pattern.returningMatchAndRewrite(target, rewriter);
219*5cde5a57SAlex Zinenko   if (failed(result))
220*5cde5a57SAlex Zinenko     return failure();
221*5cde5a57SAlex Zinenko 
222*5cde5a57SAlex Zinenko   return result->op;
223*5cde5a57SAlex Zinenko }
224*5cde5a57SAlex Zinenko 
225*5cde5a57SAlex Zinenko //===----------------------------------------------------------------------===//
2263c2a74a3SMatthias Springer // TileOp
2273c2a74a3SMatthias Springer //===----------------------------------------------------------------------===//
2283c2a74a3SMatthias Springer 
2293c2a74a3SMatthias Springer /// Apply a tiling transformation to all payload ops and store both the
2303c2a74a3SMatthias Springer /// tiled operation as well as the created tile loops.
2313c2a74a3SMatthias Springer static LogicalResult
2323c2a74a3SMatthias Springer applyTilingToAll(Operation *transformOp, Value target,
2333c2a74a3SMatthias Springer                  ArrayRef<int64_t> tileSizes,
2343c2a74a3SMatthias Springer                  transform::TransformResults &transformResults,
2353c2a74a3SMatthias Springer                  transform::TransformState &state,
2363c2a74a3SMatthias Springer                  function_ref<FailureOr<TiledLinalgOp>(LinalgOp)> applyFn) {
2373c2a74a3SMatthias Springer   // Number of loops: Number of tiles sizes that are not zero.
2383c2a74a3SMatthias Springer   size_t numLoops = tileSizes.size() - llvm::count(tileSizes, 0);
2393c2a74a3SMatthias Springer   // All payload ops. These should all be LinalgOps for now.
2403c2a74a3SMatthias Springer   ArrayRef<Operation *> payloadOps = state.getPayloadOps(target);
2413c2a74a3SMatthias Springer 
2423c2a74a3SMatthias Springer   SmallVector<Operation *> tiledLinalgOps;
2433c2a74a3SMatthias Springer   SmallVector<SmallVector<Operation *>> loopOps(numLoops);
2443c2a74a3SMatthias Springer   for (unsigned int i = 0; i < numLoops; ++i)
2453c2a74a3SMatthias Springer     loopOps[i].reserve(payloadOps.size());
2463c2a74a3SMatthias Springer 
2473c2a74a3SMatthias Springer   for (Operation *target : payloadOps) {
2483c2a74a3SMatthias Springer     auto linalgOp = dyn_cast<linalg::LinalgOp>(target);
2493c2a74a3SMatthias Springer     if (!linalgOp)
2503c2a74a3SMatthias Springer       return transformOp->emitError("only LinalgOps are supported");
2513c2a74a3SMatthias Springer 
2523c2a74a3SMatthias Springer     FailureOr<TiledLinalgOp> tiled = applyFn(linalgOp);
2533c2a74a3SMatthias Springer     if (failed(tiled))
2543c2a74a3SMatthias Springer       return failure();
2553c2a74a3SMatthias Springer 
2563c2a74a3SMatthias Springer     tiledLinalgOps.push_back(tiled->op);
2573c2a74a3SMatthias Springer     if (tiled->loops.size() != numLoops)
2583c2a74a3SMatthias Springer       // Not enough loops were generated. This usually means that the input size
2593c2a74a3SMatthias Springer       // was smaller than the tiling size.
2603c2a74a3SMatthias Springer       // TODO: LinalgTilingPattern should return failure().
2613c2a74a3SMatthias Springer       return failure();
2623c2a74a3SMatthias Springer     for (unsigned int i = 0; i < numLoops; ++i)
2633c2a74a3SMatthias Springer       loopOps[i].push_back(tiled->loops[i]);
2643c2a74a3SMatthias Springer   }
2653c2a74a3SMatthias Springer 
2663c2a74a3SMatthias Springer   transformResults.set(transformOp->getOpResult(0), tiledLinalgOps);
2673c2a74a3SMatthias Springer   for (unsigned int i = 0; i < numLoops; ++i)
2683c2a74a3SMatthias Springer     transformResults.set(transformOp->getOpResult(i + 1), loopOps[i]);
2693c2a74a3SMatthias Springer   return success();
2703c2a74a3SMatthias Springer }
2713c2a74a3SMatthias Springer 
2723c2a74a3SMatthias Springer LogicalResult transform::TileOp::apply(TransformResults &transformResults,
2733c2a74a3SMatthias Springer                                        TransformState &state) {
2743c2a74a3SMatthias Springer   LinalgTilingOptions tilingOptions;
2753c2a74a3SMatthias Springer   SmallVector<int64_t> tileSizes = extractI64Array(getSizes());
2763c2a74a3SMatthias Springer 
2773c2a74a3SMatthias Springer   if (!tileSizes.empty())
2783c2a74a3SMatthias Springer     tilingOptions.setTileSizes(tileSizes);
2793c2a74a3SMatthias Springer   tilingOptions.setInterchange(extractUIntArray(getInterchange()));
2803c2a74a3SMatthias Springer   LinalgTilingPattern pattern(getContext(), tilingOptions);
2813c2a74a3SMatthias Springer 
2823c2a74a3SMatthias Springer   return applyTilingToAll(getOperation(), getTarget(), tileSizes,
2833c2a74a3SMatthias Springer                           transformResults, state, [&](LinalgOp linalgOp) {
2843c2a74a3SMatthias Springer                             SimpleRewriter rewriter(linalgOp.getContext());
2853c2a74a3SMatthias Springer                             return pattern.returningMatchAndRewrite(linalgOp,
2863c2a74a3SMatthias Springer                                                                     rewriter);
2873c2a74a3SMatthias Springer                           });
2883c2a74a3SMatthias Springer }
2893c2a74a3SMatthias Springer 
2903c2a74a3SMatthias Springer ParseResult transform::TileOp::parse(OpAsmParser &parser,
2913c2a74a3SMatthias Springer                                      OperationState &result) {
2923c2a74a3SMatthias Springer   StringRef sizesAttrName = TileOp::getSizesAttrName(result.name).getValue();
2933c2a74a3SMatthias Springer   OpAsmParser::UnresolvedOperand targetOperand;
2941d7b5cd5SChris Lattner   SMLoc opLoc = parser.getCurrentLocation();
2951d7b5cd5SChris Lattner   if (parser.parseOperand(targetOperand) ||
2961d7b5cd5SChris Lattner       parser.parseOptionalAttrDict(result.attributes))
2973c2a74a3SMatthias Springer     return failure();
2983c2a74a3SMatthias Springer   Attribute sizesAttr = result.attributes.get(sizesAttrName);
2993c2a74a3SMatthias Springer   if (!sizesAttr)
3003c2a74a3SMatthias Springer     return parser.emitError(opLoc)
3013c2a74a3SMatthias Springer            << "expected '" << sizesAttrName << "' attribute";
3023c2a74a3SMatthias Springer   auto sizesArrayAttr = sizesAttr.dyn_cast<ArrayAttr>();
3033c2a74a3SMatthias Springer   if (!sizesArrayAttr)
3043c2a74a3SMatthias Springer     return parser.emitError(opLoc)
3053c2a74a3SMatthias Springer            << "'" << sizesAttrName << "' attribute must be an array";
3063c2a74a3SMatthias Springer   Type pdlOpType = parser.getBuilder().getType<pdl::OperationType>();
3073c2a74a3SMatthias Springer   size_t numExpectedLoops =
3083c2a74a3SMatthias Springer       sizesArrayAttr.size() - llvm::count(extractI64Array(sizesArrayAttr), 0);
3093c2a74a3SMatthias Springer   result.addTypes(SmallVector<Type>(numExpectedLoops + 1, pdlOpType));
3103c2a74a3SMatthias Springer   if (parser.resolveOperand(targetOperand, pdlOpType, result.operands))
3113c2a74a3SMatthias Springer     return failure();
3123c2a74a3SMatthias Springer   return success();
3133c2a74a3SMatthias Springer }
3143c2a74a3SMatthias Springer 
3153c2a74a3SMatthias Springer void TileOp::print(OpAsmPrinter &p) {
3163c2a74a3SMatthias Springer   p << ' ';
3173c2a74a3SMatthias Springer   p << getTarget();
3183c2a74a3SMatthias Springer   p.printOptionalAttrDict((*this)->getAttrs());
3193c2a74a3SMatthias Springer }
3203c2a74a3SMatthias Springer 
3213c2a74a3SMatthias Springer void TileOp::getEffects(
3223c2a74a3SMatthias Springer     SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
3233c2a74a3SMatthias Springer         &effects) {
3243c2a74a3SMatthias Springer   // `target` arg is consumed and can no longer be used.
3253c2a74a3SMatthias Springer   effects.emplace_back(MemoryEffects::Read::get(), getTarget(),
3263c2a74a3SMatthias Springer                        TransformMappingResource::get());
3273c2a74a3SMatthias Springer   effects.emplace_back(MemoryEffects::Free::get(), getTarget(),
3283c2a74a3SMatthias Springer                        TransformMappingResource::get());
3293c2a74a3SMatthias Springer 
3303c2a74a3SMatthias Springer   for (Value r : getResults()) {
3313c2a74a3SMatthias Springer     effects.emplace_back(MemoryEffects::Write::get(), r,
3323c2a74a3SMatthias Springer                          TransformMappingResource::get());
3333c2a74a3SMatthias Springer     effects.emplace_back(MemoryEffects::Allocate::get(), r,
3343c2a74a3SMatthias Springer                          TransformMappingResource::get());
3353c2a74a3SMatthias Springer   }
3363c2a74a3SMatthias Springer 
3373c2a74a3SMatthias Springer   effects.emplace_back(MemoryEffects::Read::get(), PayloadIRResource::get());
3383c2a74a3SMatthias Springer   effects.emplace_back(MemoryEffects::Write::get(), PayloadIRResource::get());
3393c2a74a3SMatthias Springer }
3403c2a74a3SMatthias Springer 
3413c2a74a3SMatthias Springer //===----------------------------------------------------------------------===//
3423c2a74a3SMatthias Springer // Transform op registration
3433c2a74a3SMatthias Springer //===----------------------------------------------------------------------===//
3443c2a74a3SMatthias Springer 
3453c2a74a3SMatthias Springer namespace {
3463c2a74a3SMatthias Springer /// Registers new ops and declares PDL as dependent dialect since the additional
3473c2a74a3SMatthias Springer /// ops are using PDL types for operands and results.
3483c2a74a3SMatthias Springer class LinalgTransformDialectExtension
3493c2a74a3SMatthias Springer     : public transform::TransformDialectExtension<
3503c2a74a3SMatthias Springer           LinalgTransformDialectExtension> {
3513c2a74a3SMatthias Springer public:
3523c2a74a3SMatthias Springer   LinalgTransformDialectExtension() {
3533c2a74a3SMatthias Springer     declareDependentDialect<pdl::PDLDialect>();
3543c2a74a3SMatthias Springer     declareDependentDialect<scf::SCFDialect>();
3553c2a74a3SMatthias Springer     registerTransformOps<
3563c2a74a3SMatthias Springer #define GET_OP_LIST
3573c2a74a3SMatthias Springer #include "mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp.inc"
3583c2a74a3SMatthias Springer         >();
3593c2a74a3SMatthias Springer   }
3603c2a74a3SMatthias Springer };
3613c2a74a3SMatthias Springer } // namespace
3623c2a74a3SMatthias Springer 
3633c2a74a3SMatthias Springer #define GET_OP_CLASSES
3643c2a74a3SMatthias Springer #include "mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp.inc"
3653c2a74a3SMatthias Springer 
3663c2a74a3SMatthias Springer void mlir::linalg::registerTransformDialectExtension(
3673c2a74a3SMatthias Springer     DialectRegistry &registry) {
3683c2a74a3SMatthias Springer   registry.addExtensions<LinalgTransformDialectExtension>();
3693c2a74a3SMatthias Springer }
370