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 
113963b4d0SAlex Zinenko #include "mlir/Dialect/Affine/IR/AffineOps.h"
124e4a4c05SAlex Zinenko #include "mlir/Dialect/Arithmetic/IR/Arithmetic.h"
133c2a74a3SMatthias Springer #include "mlir/Dialect/Linalg/IR/Linalg.h"
143c2a74a3SMatthias Springer #include "mlir/Dialect/Linalg/Transforms/Transforms.h"
153c2a74a3SMatthias Springer #include "mlir/Dialect/PDL/IR/PDL.h"
163c2a74a3SMatthias Springer #include "mlir/Dialect/PDL/IR/PDLTypes.h"
173c2a74a3SMatthias Springer #include "mlir/Dialect/Transform/IR/TransformDialect.h"
183963b4d0SAlex Zinenko #include "mlir/Dialect/Transform/IR/TransformInterfaces.h"
1918b92c66SNicolas Vasilache #include "mlir/Interfaces/TilingInterface.h"
203c2a74a3SMatthias Springer #include "mlir/Parser/Parser.h"
21cc6c1592SAlex Zinenko #include "mlir/Transforms/GreedyPatternRewriteDriver.h"
221f77f01cSNicolas Vasilache #include "llvm/ADT/StringSet.h"
233c2a74a3SMatthias Springer 
243c2a74a3SMatthias Springer using namespace mlir;
253c2a74a3SMatthias Springer using namespace mlir::linalg;
263c2a74a3SMatthias Springer using namespace mlir::transform;
273c2a74a3SMatthias Springer 
283c2a74a3SMatthias Springer /// Extracts a vector of unsigned from an array attribute. Asserts if the
293c2a74a3SMatthias Springer /// attribute contains values other than intergers. May truncate.
303c2a74a3SMatthias Springer static SmallVector<unsigned> extractUIntArray(ArrayAttr attr) {
313c2a74a3SMatthias Springer   SmallVector<unsigned> result;
323c2a74a3SMatthias Springer   result.reserve(attr.size());
333c2a74a3SMatthias Springer   for (APInt value : attr.getAsValueRange<IntegerAttr>())
343c2a74a3SMatthias Springer     result.push_back(value.getZExtValue());
353c2a74a3SMatthias Springer   return result;
363c2a74a3SMatthias Springer }
373c2a74a3SMatthias Springer 
383c2a74a3SMatthias Springer namespace {
393c2a74a3SMatthias Springer /// A simple pattern rewriter that implements no special logic.
403c2a74a3SMatthias Springer class SimpleRewriter : public PatternRewriter {
413c2a74a3SMatthias Springer public:
423c2a74a3SMatthias Springer   SimpleRewriter(MLIRContext *context) : PatternRewriter(context) {}
433c2a74a3SMatthias Springer };
443c2a74a3SMatthias Springer } // namespace
453c2a74a3SMatthias Springer 
46ce2e198bSAlex Zinenko /// Attempts to apply the pattern specified as template argument to the given
47ce2e198bSAlex Zinenko /// operation. The pattern is expected to have a `returningMatchAndRewrite`
48ce2e198bSAlex Zinenko /// function that returns the "main" result or failure. Returns failure if the
49ce2e198bSAlex Zinenko /// pattern failed to apply. Extra arguments are forwarded to the pattern
50ce2e198bSAlex Zinenko /// constructor.
51ce2e198bSAlex Zinenko template <typename PatternTy, typename... Args>
52ce2e198bSAlex Zinenko static FailureOr<LinalgOp> tryApply(Operation *operation, Args &&...args) {
53ce2e198bSAlex Zinenko   // Check if the given operation has the type expected by the pattern.
54ce2e198bSAlex Zinenko   using OpTy = typename llvm::function_traits<
55ce2e198bSAlex Zinenko       decltype(&PatternTy::returningMatchAndRewrite)>::template arg_t<0>;
56ce2e198bSAlex Zinenko   auto op = dyn_cast<OpTy>(operation);
57ce2e198bSAlex Zinenko   if (!op)
58ce2e198bSAlex Zinenko     return failure();
59ce2e198bSAlex Zinenko 
60ce2e198bSAlex Zinenko   // Apply the pattern directly to the op.
61ce2e198bSAlex Zinenko   PatternTy pattern(operation->getContext(), std::forward<Args>(args)...);
62ce2e198bSAlex Zinenko   SimpleRewriter rewriter(operation->getContext());
63ce2e198bSAlex Zinenko   rewriter.setInsertionPoint(operation);
64ce2e198bSAlex Zinenko   auto result = pattern.returningMatchAndRewrite(op, rewriter);
65ce2e198bSAlex Zinenko   if (failed(result))
66ce2e198bSAlex Zinenko     return failure();
67ce2e198bSAlex Zinenko   return cast<LinalgOp>(result->getOperation());
68ce2e198bSAlex Zinenko }
69ce2e198bSAlex Zinenko 
70ce2e198bSAlex Zinenko //===----------------------------------------------------------------------===//
71ce2e198bSAlex Zinenko // DecomposeOp
72ce2e198bSAlex Zinenko //===----------------------------------------------------------------------===//
73ce2e198bSAlex Zinenko 
7452307109SNicolas Vasilache DiagnosedSilenceableFailure
7552307109SNicolas Vasilache transform::DecomposeOp::applyToOne(linalg::LinalgOp target,
7652307109SNicolas Vasilache                                    SmallVectorImpl<Operation *> &results,
7752307109SNicolas Vasilache                                    transform::TransformState &state) {
78ce2e198bSAlex Zinenko   FailureOr<LinalgOp> windowed =
79ce2e198bSAlex Zinenko       tryApply<DownscaleSizeOneWindowed2DConvolution>(target);
8052307109SNicolas Vasilache   if (succeeded(windowed)) {
8152307109SNicolas Vasilache     results.push_back(*windowed);
8252307109SNicolas Vasilache     return DiagnosedSilenceableFailure(success());
8352307109SNicolas Vasilache   }
84ce2e198bSAlex Zinenko   FailureOr<LinalgOp> depthwise =
85ce2e198bSAlex Zinenko       tryApply<DownscaleDepthwiseConv2DNhwcHwcOp>(target);
8652307109SNicolas Vasilache   if (succeeded(depthwise)) {
8752307109SNicolas Vasilache     results.push_back(*depthwise);
8852307109SNicolas Vasilache     return DiagnosedSilenceableFailure(success());
8952307109SNicolas Vasilache   }
9052307109SNicolas Vasilache   results.assign(1, nullptr);
9152307109SNicolas Vasilache   return emitDefaultSilenceableFailure(target);
92ce2e198bSAlex Zinenko }
93ce2e198bSAlex Zinenko 
94ce2e198bSAlex Zinenko //===----------------------------------------------------------------------===//
95b6c58ec4SAlex Zinenko // FuseOp
96b6c58ec4SAlex Zinenko //===----------------------------------------------------------------------===//
97b6c58ec4SAlex Zinenko 
98b6c58ec4SAlex Zinenko /// Apply a tiling transformation to all payload ops and store both the
99b6c58ec4SAlex Zinenko /// tiled operation as well as the created tile loops.
100b6c58ec4SAlex Zinenko static LogicalResult
1014e4a4c05SAlex Zinenko applyTilingToAll(Operation *transformOp, ArrayRef<Operation *> payloadOps,
1024e4a4c05SAlex Zinenko                  unsigned numLoops,
103b6c58ec4SAlex Zinenko                  transform::TransformResults &transformResults,
104b6c58ec4SAlex Zinenko                  function_ref<FailureOr<TiledLinalgOp>(LinalgOp)> applyFn) {
105b6c58ec4SAlex Zinenko   SmallVector<Operation *> tiledLinalgOps;
106b6c58ec4SAlex Zinenko   SmallVector<SmallVector<Operation *>> loopOps(numLoops);
107b6c58ec4SAlex Zinenko   for (unsigned int i = 0; i < numLoops; ++i)
108b6c58ec4SAlex Zinenko     loopOps[i].reserve(payloadOps.size());
109b6c58ec4SAlex Zinenko 
110b6c58ec4SAlex Zinenko   for (Operation *target : payloadOps) {
111b6c58ec4SAlex Zinenko     auto linalgOp = dyn_cast<linalg::LinalgOp>(target);
112b6c58ec4SAlex Zinenko     if (!linalgOp)
113b6c58ec4SAlex Zinenko       return transformOp->emitError("only LinalgOps are supported");
114b6c58ec4SAlex Zinenko 
115b6c58ec4SAlex Zinenko     FailureOr<TiledLinalgOp> tiled = applyFn(linalgOp);
116b6c58ec4SAlex Zinenko     if (failed(tiled))
117b6c58ec4SAlex Zinenko       return failure();
118b6c58ec4SAlex Zinenko 
119b6c58ec4SAlex Zinenko     tiledLinalgOps.push_back(tiled->op);
120b6c58ec4SAlex Zinenko     if (tiled->loops.size() != numLoops)
121b6c58ec4SAlex Zinenko       // Not enough loops were generated. This usually means that the input size
122b6c58ec4SAlex Zinenko       // was smaller than the tiling size.
123b6c58ec4SAlex Zinenko       // TODO: LinalgTilingPattern should return failure().
124b6c58ec4SAlex Zinenko       return failure();
125b6c58ec4SAlex Zinenko     for (unsigned int i = 0; i < numLoops; ++i)
126b6c58ec4SAlex Zinenko       loopOps[i].push_back(tiled->loops[i]);
127b6c58ec4SAlex Zinenko   }
128b6c58ec4SAlex Zinenko 
129b6c58ec4SAlex Zinenko   transformResults.set(transformOp->getOpResult(0), tiledLinalgOps);
130b6c58ec4SAlex Zinenko   for (unsigned int i = 0; i < numLoops; ++i)
131b6c58ec4SAlex Zinenko     transformResults.set(transformOp->getOpResult(i + 1), loopOps[i]);
132b6c58ec4SAlex Zinenko   return success();
133b6c58ec4SAlex Zinenko }
134b6c58ec4SAlex Zinenko 
135b6c58ec4SAlex Zinenko /// Parse a tiling-like operation that returns the tiled op as well as the
136b6c58ec4SAlex Zinenko /// created tile loops. The function counts the non-zero tile sizes to compute
137b6c58ec4SAlex Zinenko /// the number of results.
138b6c58ec4SAlex Zinenko static ParseResult parseTileLikeOp(OpAsmParser &parser, OperationState &result,
139b6c58ec4SAlex Zinenko                                    StringRef sizesAttrName) {
140b6c58ec4SAlex Zinenko   OpAsmParser::UnresolvedOperand targetOperand;
141b6c58ec4SAlex Zinenko   SMLoc opLoc = parser.getCurrentLocation();
142b6c58ec4SAlex Zinenko   if (parser.parseOperand(targetOperand) ||
143b6c58ec4SAlex Zinenko       parser.parseOptionalAttrDict(result.attributes))
144b6c58ec4SAlex Zinenko     return failure();
145b6c58ec4SAlex Zinenko   Attribute sizesAttr = result.attributes.get(sizesAttrName);
146b6c58ec4SAlex Zinenko   if (!sizesAttr)
147b6c58ec4SAlex Zinenko     return parser.emitError(opLoc)
148b6c58ec4SAlex Zinenko            << "expected '" << sizesAttrName << "' attribute";
149b6c58ec4SAlex Zinenko   auto sizesArrayAttr = sizesAttr.dyn_cast<ArrayAttr>();
150b6c58ec4SAlex Zinenko   if (!sizesArrayAttr)
151b6c58ec4SAlex Zinenko     return parser.emitError(opLoc)
152b6c58ec4SAlex Zinenko            << "'" << sizesAttrName << "' attribute must be an array";
153b6c58ec4SAlex Zinenko   Type pdlOpType = parser.getBuilder().getType<pdl::OperationType>();
154b6c58ec4SAlex Zinenko   size_t numExpectedLoops =
15518b92c66SNicolas Vasilache       sizesArrayAttr.size() -
15618b92c66SNicolas Vasilache       llvm::count(extractFromI64ArrayAttr(sizesArrayAttr), 0);
157b6c58ec4SAlex Zinenko   result.addTypes(SmallVector<Type>(numExpectedLoops + 1, pdlOpType));
158b6c58ec4SAlex Zinenko   if (parser.resolveOperand(targetOperand, pdlOpType, result.operands))
159b6c58ec4SAlex Zinenko     return failure();
160b6c58ec4SAlex Zinenko   return success();
161b6c58ec4SAlex Zinenko }
162b6c58ec4SAlex Zinenko 
1631d45282aSAlex Zinenko DiagnosedSilenceableFailure
164b6c58ec4SAlex Zinenko transform::FuseOp::apply(mlir::transform::TransformResults &transformResults,
165b6c58ec4SAlex Zinenko                          mlir::transform::TransformState &state) {
166b6c58ec4SAlex Zinenko   LinalgTilingAndFusionOptions fusionOptions;
16718b92c66SNicolas Vasilache   fusionOptions.tileSizes = extractFromI64ArrayAttr(getTileSizes());
16818b92c66SNicolas Vasilache   fusionOptions.tileInterchange = extractFromI64ArrayAttr(getTileInterchange());
169b6c58ec4SAlex Zinenko 
170e3890b7fSAlex Zinenko   LogicalResult result = applyTilingToAll(
1714e4a4c05SAlex Zinenko       getOperation(), state.getPayloadOps(getTarget()),
1724e4a4c05SAlex Zinenko       fusionOptions.tileSizes.size() - llvm::count(fusionOptions.tileSizes, 0),
1734e4a4c05SAlex Zinenko       transformResults, [&](LinalgOp linalgOp) -> FailureOr<TiledLinalgOp> {
174b6c58ec4SAlex Zinenko         LinalgTileAndFuseTensorOpsPattern pattern(getContext(), fusionOptions);
175b6c58ec4SAlex Zinenko         SimpleRewriter rewriter(getContext());
176b6c58ec4SAlex Zinenko         rewriter.setInsertionPoint(linalgOp);
177b6c58ec4SAlex Zinenko         FailureOr<TileLoopNest> tileLoopNest =
178b6c58ec4SAlex Zinenko             pattern.returningMatchAndRewrite(linalgOp, rewriter);
179b6c58ec4SAlex Zinenko         if (failed(tileLoopNest))
180b6c58ec4SAlex Zinenko           return failure();
181b6c58ec4SAlex Zinenko 
182b6c58ec4SAlex Zinenko         TiledLinalgOp tiledLinalgOp;
183b6c58ec4SAlex Zinenko         tiledLinalgOp.op = tileLoopNest->getRootOp();
184b6c58ec4SAlex Zinenko         tiledLinalgOp.loops = {tileLoopNest->getLoopOps().begin(),
185b6c58ec4SAlex Zinenko                                tileLoopNest->getLoopOps().end()};
186b6c58ec4SAlex Zinenko         return tiledLinalgOp;
187b6c58ec4SAlex Zinenko       });
1884e4a4c05SAlex Zinenko   return DiagnosedSilenceableFailure(result);
189b6c58ec4SAlex Zinenko }
190b6c58ec4SAlex Zinenko 
191b6c58ec4SAlex Zinenko ParseResult transform::FuseOp::parse(OpAsmParser &parser,
192b6c58ec4SAlex Zinenko                                      OperationState &result) {
193b6c58ec4SAlex Zinenko   return parseTileLikeOp(
194b6c58ec4SAlex Zinenko       parser, result,
195b6c58ec4SAlex Zinenko       transform::FuseOp::getTileSizesAttrName(result.name).getValue());
196b6c58ec4SAlex Zinenko }
197b6c58ec4SAlex Zinenko 
198b6c58ec4SAlex Zinenko void transform::FuseOp::print(OpAsmPrinter &p) {
199b6c58ec4SAlex Zinenko   p << ' ';
200b6c58ec4SAlex Zinenko   p << getTarget();
201b6c58ec4SAlex Zinenko   p.printOptionalAttrDict((*this)->getAttrs());
202b6c58ec4SAlex Zinenko }
203b6c58ec4SAlex Zinenko 
204b6c58ec4SAlex Zinenko LogicalResult transform::FuseOp::verify() {
20518b92c66SNicolas Vasilache   SmallVector<int64_t> permutation =
20618b92c66SNicolas Vasilache       extractFromI64ArrayAttr(getTileInterchange());
207b6c58ec4SAlex Zinenko   auto sequence = llvm::to_vector(llvm::seq<int64_t>(0, permutation.size()));
208b6c58ec4SAlex Zinenko   if (!std::is_permutation(sequence.begin(), sequence.end(),
209b6c58ec4SAlex Zinenko                            permutation.begin(), permutation.end())) {
210b6c58ec4SAlex Zinenko     return emitOpError() << "expects interchange to be a permutation, found "
211b6c58ec4SAlex Zinenko                          << getTileInterchange();
212b6c58ec4SAlex Zinenko   }
213b6c58ec4SAlex Zinenko   return success();
214b6c58ec4SAlex Zinenko }
215b6c58ec4SAlex Zinenko 
216b6c58ec4SAlex Zinenko //===----------------------------------------------------------------------===//
217ce2e198bSAlex Zinenko // GeneralizeOp
218ce2e198bSAlex Zinenko //===----------------------------------------------------------------------===//
219ce2e198bSAlex Zinenko 
22052307109SNicolas Vasilache DiagnosedSilenceableFailure
22152307109SNicolas Vasilache transform::GeneralizeOp::applyToOne(linalg::LinalgOp target,
22252307109SNicolas Vasilache                                     SmallVectorImpl<Operation *> &results,
22352307109SNicolas Vasilache                                     transform::TransformState &state) {
224ce2e198bSAlex Zinenko   // Exit early if no transformation is needed.
22552307109SNicolas Vasilache   if (isa<GenericOp>(target)) {
22652307109SNicolas Vasilache     results.push_back(target);
22752307109SNicolas Vasilache     return DiagnosedSilenceableFailure(success());
22852307109SNicolas Vasilache   }
229ce2e198bSAlex Zinenko   FailureOr<LinalgOp> generic = tryApply<LinalgGeneralizationPattern>(target);
23052307109SNicolas Vasilache   if (succeeded(generic)) {
23152307109SNicolas Vasilache     results.push_back(generic->getOperation());
23252307109SNicolas Vasilache     return DiagnosedSilenceableFailure(success());
23352307109SNicolas Vasilache   }
23452307109SNicolas Vasilache   results.assign(1, nullptr);
23552307109SNicolas Vasilache   return emitDefaultSilenceableFailure(target);
236ce2e198bSAlex Zinenko }
237ce2e198bSAlex Zinenko 
2383c2a74a3SMatthias Springer //===----------------------------------------------------------------------===//
2395cde5a57SAlex Zinenko // InterchangeOp
2405cde5a57SAlex Zinenko //===----------------------------------------------------------------------===//
2415cde5a57SAlex Zinenko 
24252307109SNicolas Vasilache DiagnosedSilenceableFailure
24352307109SNicolas Vasilache transform::InterchangeOp::applyToOne(linalg::GenericOp target,
24452307109SNicolas Vasilache                                      SmallVectorImpl<Operation *> &results,
24552307109SNicolas Vasilache                                      transform::TransformState &state) {
2465cde5a57SAlex Zinenko   SmallVector<unsigned> interchangeVector =
2475cde5a57SAlex Zinenko       extractUIntArray(getIteratorInterchange());
2485cde5a57SAlex Zinenko   // Exit early if no transformation is needed.
24952307109SNicolas Vasilache   if (interchangeVector.empty()) {
25052307109SNicolas Vasilache     results.push_back(target);
25152307109SNicolas Vasilache     return DiagnosedSilenceableFailure(success());
2525cde5a57SAlex Zinenko   }
25352307109SNicolas Vasilache   SimpleRewriter rewriter(target->getContext());
25452307109SNicolas Vasilache   FailureOr<GenericOp> res =
25552307109SNicolas Vasilache       interchangeGenericOp(rewriter, target, interchangeVector);
25652307109SNicolas Vasilache   if (failed(res))
25752307109SNicolas Vasilache     return DiagnosedSilenceableFailure::definiteFailure();
25852307109SNicolas Vasilache   results.push_back(res->getOperation());
25952307109SNicolas Vasilache   return DiagnosedSilenceableFailure(success());
2605cde5a57SAlex Zinenko }
2615cde5a57SAlex Zinenko 
2625cde5a57SAlex Zinenko LogicalResult transform::InterchangeOp::verify() {
2635cde5a57SAlex Zinenko   SmallVector<unsigned> permutation =
2645cde5a57SAlex Zinenko       extractUIntArray(getIteratorInterchange());
2655cde5a57SAlex Zinenko   auto sequence = llvm::to_vector(llvm::seq<unsigned>(0, permutation.size()));
2665cde5a57SAlex Zinenko   if (!std::is_permutation(sequence.begin(), sequence.end(),
2675cde5a57SAlex Zinenko                            permutation.begin(), permutation.end())) {
2685cde5a57SAlex Zinenko     return emitOpError()
2695cde5a57SAlex Zinenko            << "expects iterator_interchange to be a permutation, found "
2705cde5a57SAlex Zinenko            << getIteratorInterchange();
2715cde5a57SAlex Zinenko   }
2725cde5a57SAlex Zinenko   return success();
2735cde5a57SAlex Zinenko }
2745cde5a57SAlex Zinenko 
2755cde5a57SAlex Zinenko //===---------------------------------------------------------------------===//
2761f77f01cSNicolas Vasilache // MatchOp
2771f77f01cSNicolas Vasilache //===---------------------------------------------------------------------===//
2781f77f01cSNicolas Vasilache 
2791f77f01cSNicolas Vasilache LogicalResult transform::MatchOp::verify() {
2801f77f01cSNicolas Vasilache   bool opXorIface = getOps().hasValue() ^ getInterface().hasValue();
2811f77f01cSNicolas Vasilache   if (!opXorIface)
2821f77f01cSNicolas Vasilache     return this->emitOpError(
2831f77f01cSNicolas Vasilache         "requires a either a match_op or a match_interface attribute (but not "
2841f77f01cSNicolas Vasilache         "both)");
2851f77f01cSNicolas Vasilache   return success();
2861f77f01cSNicolas Vasilache }
2871f77f01cSNicolas Vasilache 
2881f77f01cSNicolas Vasilache DiagnosedSilenceableFailure
2891f77f01cSNicolas Vasilache transform::MatchOp::apply(transform::TransformResults &results,
2901f77f01cSNicolas Vasilache                           transform::TransformState &state) {
2911f77f01cSNicolas Vasilache   llvm::StringSet<> strs;
2921f77f01cSNicolas Vasilache   if (getOps().hasValue())
2931f77f01cSNicolas Vasilache     strs.insert(getOps()->getAsValueRange<StringAttr>().begin(),
2941f77f01cSNicolas Vasilache                 getOps()->getAsValueRange<StringAttr>().end());
2951f77f01cSNicolas Vasilache 
2961f77f01cSNicolas Vasilache   ArrayRef<Operation *> payloadOps = state.getPayloadOps(getTarget());
2971f77f01cSNicolas Vasilache   if (payloadOps.size() != 1)
2981f77f01cSNicolas Vasilache     return DiagnosedSilenceableFailure(
2991f77f01cSNicolas Vasilache         this->emitOpError("requires exactly one target handle"));
3001f77f01cSNicolas Vasilache 
3011f77f01cSNicolas Vasilache   SmallVector<Operation *> res;
3021f77f01cSNicolas Vasilache 
3031f77f01cSNicolas Vasilache   auto matchFun = [&](Operation *op) {
3041f77f01cSNicolas Vasilache     if (strs.contains(op->getName().getStringRef()))
3051f77f01cSNicolas Vasilache       res.push_back(op);
3061f77f01cSNicolas Vasilache     // Interfaces cannot be matched by name, just by ID.
3071f77f01cSNicolas Vasilache     // So we specifically encode the interfaces we care about for this op.
3081f77f01cSNicolas Vasilache     if (getInterface().hasValue()) {
3091f77f01cSNicolas Vasilache       auto iface = getInterface().getValue();
3101f77f01cSNicolas Vasilache       if (iface == transform::MatchInterfaceEnum::LinalgOp &&
3111f77f01cSNicolas Vasilache           isa<linalg::LinalgOp>(op))
3121f77f01cSNicolas Vasilache         res.push_back(op);
3131f77f01cSNicolas Vasilache       if (iface == transform::MatchInterfaceEnum::TilingInterface &&
3141f77f01cSNicolas Vasilache           isa<TilingInterface>(op))
3151f77f01cSNicolas Vasilache         res.push_back(op);
3161f77f01cSNicolas Vasilache     }
3171f77f01cSNicolas Vasilache   };
3181f77f01cSNicolas Vasilache 
3191f77f01cSNicolas Vasilache   payloadOps.front()->walk(matchFun);
3201f77f01cSNicolas Vasilache   results.set(getResult().cast<OpResult>(), res);
3211f77f01cSNicolas Vasilache   return DiagnosedSilenceableFailure(success());
3221f77f01cSNicolas Vasilache }
3231f77f01cSNicolas Vasilache 
3241f77f01cSNicolas Vasilache ParseResult transform::MatchOp::parse(OpAsmParser &parser,
3251f77f01cSNicolas Vasilache                                       OperationState &result) {
3261f77f01cSNicolas Vasilache   // Parse 'match_op' or 'interface' clause.
3271f77f01cSNicolas Vasilache   if (succeeded(parser.parseOptionalKeyword("ops"))) {
3281f77f01cSNicolas Vasilache     ArrayAttr opsAttr;
3291f77f01cSNicolas Vasilache     if (parser.parseLBrace() ||
3301f77f01cSNicolas Vasilache         parser.parseCustomAttributeWithFallback(
3311f77f01cSNicolas Vasilache             opsAttr, parser.getBuilder().getType<NoneType>(), "ops",
3321f77f01cSNicolas Vasilache             result.attributes) ||
3331f77f01cSNicolas Vasilache         parser.parseRBrace())
3341f77f01cSNicolas Vasilache       return failure();
3351f77f01cSNicolas Vasilache   } else if (succeeded(parser.parseOptionalKeyword("interface"))) {
3361f77f01cSNicolas Vasilache     if (parser.parseLBrace())
3371f77f01cSNicolas Vasilache       return failure();
3381f77f01cSNicolas Vasilache     StringRef attrStr;
3391f77f01cSNicolas Vasilache     auto loc = parser.getCurrentLocation();
3401f77f01cSNicolas Vasilache     if (parser.parseKeyword(&attrStr))
3411f77f01cSNicolas Vasilache       return failure();
3421f77f01cSNicolas Vasilache     auto interfaceEnum = transform::symbolizeMatchInterfaceEnum(attrStr);
3431f77f01cSNicolas Vasilache     if (!interfaceEnum)
3441f77f01cSNicolas Vasilache       return parser.emitError(loc, "invalid ")
3451f77f01cSNicolas Vasilache              << "match_interface attribute specification: \"" << attrStr << '"';
3461f77f01cSNicolas Vasilache     transform::MatchInterfaceEnumAttr match_interfaceAttr =
3471f77f01cSNicolas Vasilache         transform::MatchInterfaceEnumAttr::get(parser.getBuilder().getContext(),
3481f77f01cSNicolas Vasilache                                                interfaceEnum.value());
3491f77f01cSNicolas Vasilache     result.addAttribute("interface", match_interfaceAttr);
3501f77f01cSNicolas Vasilache     if (parser.parseRBrace())
3511f77f01cSNicolas Vasilache       return failure();
3521f77f01cSNicolas Vasilache   } else {
3531f77f01cSNicolas Vasilache     auto loc = parser.getCurrentLocation();
3541f77f01cSNicolas Vasilache     return parser.emitError(loc, "expected ops or interface");
3551f77f01cSNicolas Vasilache   }
3561f77f01cSNicolas Vasilache 
3571f77f01cSNicolas Vasilache   OpAsmParser::UnresolvedOperand targetRawOperands[1];
3581f77f01cSNicolas Vasilache   ArrayRef<OpAsmParser::UnresolvedOperand> targetOperands(targetRawOperands);
3591f77f01cSNicolas Vasilache   if (parser.parseKeyword("in") || parser.parseOperand(targetRawOperands[0]) ||
3601f77f01cSNicolas Vasilache       parser.parseOptionalAttrDict(result.attributes))
3611f77f01cSNicolas Vasilache     return failure();
3621f77f01cSNicolas Vasilache   Type pdlOpType = parser.getBuilder().getType<pdl::OperationType>();
3631f77f01cSNicolas Vasilache   result.addTypes(pdlOpType);
3641f77f01cSNicolas Vasilache   if (parser.resolveOperands(targetOperands, pdlOpType, result.operands))
3651f77f01cSNicolas Vasilache     return failure();
3661f77f01cSNicolas Vasilache   return success();
3671f77f01cSNicolas Vasilache }
3681f77f01cSNicolas Vasilache 
3691f77f01cSNicolas Vasilache void transform::MatchOp::print(OpAsmPrinter &p) {
3701f77f01cSNicolas Vasilache   if ((*this)->getAttr("ops")) {
3711f77f01cSNicolas Vasilache     p << " ops{";
3721f77f01cSNicolas Vasilache     p.printAttributeWithoutType(getOpsAttr());
3731f77f01cSNicolas Vasilache     p << "}";
3741f77f01cSNicolas Vasilache   }
3751f77f01cSNicolas Vasilache   if ((*this)->getAttr("interface")) {
3761f77f01cSNicolas Vasilache     p << " interface{" << stringifyMatchInterfaceEnum(*getInterface()) << "}";
3771f77f01cSNicolas Vasilache   }
3781f77f01cSNicolas Vasilache   p << " in " << getTarget();
3791f77f01cSNicolas Vasilache   p.printOptionalAttrDict((*this)->getAttrs(),
3801f77f01cSNicolas Vasilache                           /*elidedAttrs=*/{"ops", "interface"});
3811f77f01cSNicolas Vasilache }
3821f77f01cSNicolas Vasilache 
3831f77f01cSNicolas Vasilache //===---------------------------------------------------------------------===//
3843963b4d0SAlex Zinenko // MultiTileSizesOp
3853963b4d0SAlex Zinenko //===---------------------------------------------------------------------===//
3863963b4d0SAlex Zinenko 
3873963b4d0SAlex Zinenko DiagnosedSilenceableFailure transform::MultiTileSizesOp::applyToOne(
3883963b4d0SAlex Zinenko     LinalgOp target, SmallVector<Operation *> &results, TransformState &state) {
3893963b4d0SAlex Zinenko   OpBuilder builder(target.getContext());
3903963b4d0SAlex Zinenko   builder.setInsertionPoint(target);
3913963b4d0SAlex Zinenko   OpFoldResult targetSize = builder.getIndexAttr(getTargetSize());
3923963b4d0SAlex Zinenko   OpFoldResult divisor = builder.getIndexAttr(getDivisor());
3933963b4d0SAlex Zinenko   FailureOr<MultiSizeSpecification> spec = computeMultiTileSizes(
3943963b4d0SAlex Zinenko       builder, target, getDimension(), targetSize, divisor);
3953963b4d0SAlex Zinenko   if (failed(spec)) {
3963963b4d0SAlex Zinenko     return emitSilenceableError() << "could not generate tile size computation";
3973963b4d0SAlex Zinenko   }
3983963b4d0SAlex Zinenko 
399a5c802a4SAlex Zinenko   AffineExpr s0 = builder.getAffineSymbolExpr(0);
400a5c802a4SAlex Zinenko   AffineExpr s1 = builder.getAffineSymbolExpr(1);
4013963b4d0SAlex Zinenko   Operation *splitPoint =
402a5c802a4SAlex Zinenko       makeComposedAffineApply(builder, target.getLoc(), s0 * s1,
403a5c802a4SAlex Zinenko                               {spec->lowTileSize, spec->lowTripCount});
4043963b4d0SAlex Zinenko   Operation *lowTileSize = spec->lowTileSize.getDefiningOp();
4053963b4d0SAlex Zinenko   Operation *highTileSize = spec->highTileSize.getDefiningOp();
4063963b4d0SAlex Zinenko   assert(lowTileSize && highTileSize && splitPoint &&
4073963b4d0SAlex Zinenko          "tile sizes are not produced by operations");
4083963b4d0SAlex Zinenko   results.reserve(results.size() + 3);
4093963b4d0SAlex Zinenko   results.push_back(lowTileSize);
4103963b4d0SAlex Zinenko   results.push_back(highTileSize);
4113963b4d0SAlex Zinenko   results.push_back(splitPoint);
4123963b4d0SAlex Zinenko   return DiagnosedSilenceableFailure::success();
4133963b4d0SAlex Zinenko }
4143963b4d0SAlex Zinenko 
4153963b4d0SAlex Zinenko void transform::MultiTileSizesOp::getEffects(
4163963b4d0SAlex Zinenko     SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
417e15b855eSAlex Zinenko   onlyReadsHandle(getTarget(), effects);
418e15b855eSAlex Zinenko   producesHandle(getResults(), effects);
419e15b855eSAlex Zinenko   modifiesPayload(effects);
4203963b4d0SAlex Zinenko }
4213963b4d0SAlex Zinenko 
4223963b4d0SAlex Zinenko //===---------------------------------------------------------------------===//
4235cde5a57SAlex Zinenko // PadOp
4245cde5a57SAlex Zinenko //===---------------------------------------------------------------------===//
4255cde5a57SAlex Zinenko 
42652307109SNicolas Vasilache DiagnosedSilenceableFailure
42752307109SNicolas Vasilache transform::PadOp::applyToOne(linalg::LinalgOp target,
42852307109SNicolas Vasilache                              SmallVectorImpl<Operation *> &results,
42952307109SNicolas Vasilache                              transform::TransformState &state) {
4305cde5a57SAlex Zinenko   // Convert the integer packing flags to booleans.
4315cde5a57SAlex Zinenko   SmallVector<bool> packPaddings;
43218b92c66SNicolas Vasilache   for (int64_t packPadding : extractFromI64ArrayAttr(getPackPaddings()))
4335cde5a57SAlex Zinenko     packPaddings.push_back(static_cast<bool>(packPadding));
4345cde5a57SAlex Zinenko 
4355cde5a57SAlex Zinenko   // Convert the padding values to attributes.
4365cde5a57SAlex Zinenko   SmallVector<Attribute> paddingValues;
4375cde5a57SAlex Zinenko   for (auto const &it :
4385cde5a57SAlex Zinenko        llvm::zip(getPaddingValues(), target->getOperandTypes())) {
4395cde5a57SAlex Zinenko     Attribute attr = std::get<0>(it);
4405cde5a57SAlex Zinenko     Type elementType = getElementTypeOrSelf(std::get<1>(it));
4415cde5a57SAlex Zinenko     // Try to parse string attributes to obtain an attribute of element type.
4425cde5a57SAlex Zinenko     if (auto stringAttr = attr.dyn_cast<StringAttr>()) {
4435cde5a57SAlex Zinenko       paddingValues.push_back(
4445cde5a57SAlex Zinenko           parseAttribute(attr.cast<StringAttr>(), elementType));
4455cde5a57SAlex Zinenko       if (!paddingValues.back()) {
44652307109SNicolas Vasilache         auto diag = this->emitOpError("expects a padding that parses to ")
4475cde5a57SAlex Zinenko                     << elementType << ", got " << std::get<0>(it);
4485cde5a57SAlex Zinenko         diag.attachNote(target.getLoc()) << "when applied to this op";
44952307109SNicolas Vasilache         return DiagnosedSilenceableFailure::definiteFailure();
4505cde5a57SAlex Zinenko       }
4515cde5a57SAlex Zinenko       continue;
4525cde5a57SAlex Zinenko     }
4535cde5a57SAlex Zinenko     // Otherwise, add the attribute directly.
4545cde5a57SAlex Zinenko     if (attr.getType() != elementType) {
45552307109SNicolas Vasilache       auto diag = this->emitOpError("expects a padding value of type ")
4565cde5a57SAlex Zinenko                   << elementType << ", got " << attr;
4575cde5a57SAlex Zinenko       diag.attachNote(target.getLoc()) << "when applied to this op";
45852307109SNicolas Vasilache       return DiagnosedSilenceableFailure::definiteFailure();
4595cde5a57SAlex Zinenko     }
4605cde5a57SAlex Zinenko     paddingValues.push_back(attr);
4615cde5a57SAlex Zinenko   }
4625cde5a57SAlex Zinenko 
4635cde5a57SAlex Zinenko   // Extract the transpose vectors.
4645cde5a57SAlex Zinenko   SmallVector<SmallVector<int64_t>> transposePaddings;
4655cde5a57SAlex Zinenko   for (Attribute transposeVector : getTransposePaddings().cast<ArrayAttr>())
4665cde5a57SAlex Zinenko     transposePaddings.push_back(
46718b92c66SNicolas Vasilache         extractFromI64ArrayAttr(transposeVector.cast<ArrayAttr>()));
4685cde5a57SAlex Zinenko 
4695cde5a57SAlex Zinenko   LinalgPaddingOptions paddingOptions;
4705cde5a57SAlex Zinenko   paddingOptions.setPaddingValues(paddingValues);
47118b92c66SNicolas Vasilache   paddingOptions.setPaddingDimensions(
47218b92c66SNicolas Vasilache       extractFromI64ArrayAttr(getPaddingDimensions()));
4735cde5a57SAlex Zinenko   paddingOptions.setPackPaddings(packPaddings);
47418b92c66SNicolas Vasilache   paddingOptions.setHoistPaddings(extractFromI64ArrayAttr(getHoistPaddings()));
4755cde5a57SAlex Zinenko   paddingOptions.setTransposePaddings(transposePaddings);
4765cde5a57SAlex Zinenko 
477ce2e198bSAlex Zinenko   FailureOr<LinalgOp> result =
478ce2e198bSAlex Zinenko       tryApply<LinalgPaddingPattern>(target, paddingOptions);
47952307109SNicolas Vasilache   if (succeeded(result)) {
48052307109SNicolas Vasilache     results.push_back(result->getOperation());
48152307109SNicolas Vasilache     return DiagnosedSilenceableFailure(success());
48252307109SNicolas Vasilache   }
483ce2e198bSAlex Zinenko 
48452307109SNicolas Vasilache   results.assign(1, nullptr);
48552307109SNicolas Vasilache   return emitDefaultSilenceableFailure(target);
4865cde5a57SAlex Zinenko }
4875cde5a57SAlex Zinenko 
4885cde5a57SAlex Zinenko LogicalResult transform::PadOp::verify() {
48918b92c66SNicolas Vasilache   SmallVector<int64_t> packPaddings =
49018b92c66SNicolas Vasilache       extractFromI64ArrayAttr(getPackPaddings());
4915cde5a57SAlex Zinenko   if (any_of(packPaddings, [](int64_t packPadding) {
4925cde5a57SAlex Zinenko         return packPadding != 0 && packPadding != 1;
4935cde5a57SAlex Zinenko       })) {
4945cde5a57SAlex Zinenko     return emitOpError()
4955cde5a57SAlex Zinenko            << "expects pack_paddings to contain booleans (0/1), found "
4965cde5a57SAlex Zinenko            << getPackPaddings();
4975cde5a57SAlex Zinenko   }
4985cde5a57SAlex Zinenko 
4995cde5a57SAlex Zinenko   SmallVector<int64_t> paddingDimensions =
50018b92c66SNicolas Vasilache       extractFromI64ArrayAttr(getPaddingDimensions());
5015cde5a57SAlex Zinenko   if (any_of(paddingDimensions,
5025cde5a57SAlex Zinenko              [](int64_t paddingDimension) { return paddingDimension < 0; })) {
5035cde5a57SAlex Zinenko     return emitOpError()
5045cde5a57SAlex Zinenko            << "expects padding_dimensions to contain positive integers, found "
5055cde5a57SAlex Zinenko            << getPaddingDimensions();
5065cde5a57SAlex Zinenko   }
5075cde5a57SAlex Zinenko 
50818b92c66SNicolas Vasilache   SmallVector<int64_t> hoistPaddings =
50918b92c66SNicolas Vasilache       extractFromI64ArrayAttr(getHoistPaddings());
5105cde5a57SAlex Zinenko   if (any_of(hoistPaddings,
5115cde5a57SAlex Zinenko              [](int64_t hoistPadding) { return hoistPadding < 0; })) {
5125cde5a57SAlex Zinenko     return emitOpError()
5135cde5a57SAlex Zinenko            << "expects hoist_paddings to contain positive integers, found "
5145cde5a57SAlex Zinenko            << getHoistPaddings();
5155cde5a57SAlex Zinenko   }
5165cde5a57SAlex Zinenko 
5175cde5a57SAlex Zinenko   ArrayAttr transposes = getTransposePaddings();
5185cde5a57SAlex Zinenko   for (Attribute attr : transposes) {
5195cde5a57SAlex Zinenko     SmallVector<int64_t> transpose = extractFromI64ArrayAttr(attr);
5205cde5a57SAlex Zinenko     auto sequence = llvm::to_vector(llvm::seq<int64_t>(0, transpose.size()));
5215cde5a57SAlex Zinenko     if (!std::is_permutation(sequence.begin(), sequence.end(),
5225cde5a57SAlex Zinenko                              transpose.begin(), transpose.end())) {
5235cde5a57SAlex Zinenko       return emitOpError()
5245cde5a57SAlex Zinenko              << "expects transpose_paddings to be a permutation, found "
5255cde5a57SAlex Zinenko              << attr;
5265cde5a57SAlex Zinenko     }
5275cde5a57SAlex Zinenko   }
5285cde5a57SAlex Zinenko   return success();
5295cde5a57SAlex Zinenko }
5305cde5a57SAlex Zinenko 
5315cde5a57SAlex Zinenko //===----------------------------------------------------------------------===//
5325a001136SNicolas Vasilache // PromoteOp
5335a001136SNicolas Vasilache //===----------------------------------------------------------------------===//
5345a001136SNicolas Vasilache 
5355a001136SNicolas Vasilache DiagnosedSilenceableFailure
5365a001136SNicolas Vasilache transform::PromoteOp::applyToOne(linalg::LinalgOp target,
5375a001136SNicolas Vasilache                                  SmallVectorImpl<Operation *> &results,
5385a001136SNicolas Vasilache                                  transform::TransformState &state) {
5395a001136SNicolas Vasilache   LinalgPromotionOptions promotionOptions;
5405a001136SNicolas Vasilache   if (!getOperandsToPromote().empty())
5415a001136SNicolas Vasilache     promotionOptions = promotionOptions.setOperandsToPromote(
5425a001136SNicolas Vasilache         extractFromI64ArrayAttr(getOperandsToPromote()));
5435a001136SNicolas Vasilache   if (getUseFullTilesByDefault())
5445a001136SNicolas Vasilache     promotionOptions = promotionOptions.setUseFullTileBuffersByDefault(
5455a001136SNicolas Vasilache         getUseFullTilesByDefault());
5465a001136SNicolas Vasilache   if (getUseAlloca())
5475a001136SNicolas Vasilache     promotionOptions = promotionOptions.setUseAlloca(getUseAlloca());
5485a001136SNicolas Vasilache   if (!getUseFullTileBuffers().empty())
5495a001136SNicolas Vasilache     promotionOptions = promotionOptions.setUseFullTileBuffers(
5505a001136SNicolas Vasilache         llvm::to_vector(getUseFullTileBuffers().getAsValueRange<BoolAttr>()));
5511a5d0076SKazu Hirata   if (getAlignment().has_value())
5525a001136SNicolas Vasilache     promotionOptions = promotionOptions.setAlignment(*getAlignment());
5535a001136SNicolas Vasilache 
5545a001136SNicolas Vasilache   if (failed(promoteSubviewsPrecondition(target, promotionOptions)))
5555a001136SNicolas Vasilache     return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
5565a001136SNicolas Vasilache 
5575a001136SNicolas Vasilache   SimpleRewriter rewriter(target->getContext());
5585a001136SNicolas Vasilache   rewriter.setInsertionPoint(target);
5595a001136SNicolas Vasilache   FailureOr<LinalgOp> res = promoteSubViews(rewriter, target, promotionOptions);
5605a001136SNicolas Vasilache   if (failed(res))
5615a001136SNicolas Vasilache     return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
5625a001136SNicolas Vasilache   results.push_back(target);
5635a001136SNicolas Vasilache   return DiagnosedSilenceableFailure(success());
5645a001136SNicolas Vasilache }
5655a001136SNicolas Vasilache 
5665a001136SNicolas Vasilache //===----------------------------------------------------------------------===//
5675cde5a57SAlex Zinenko // ScalarizeOp
5685cde5a57SAlex Zinenko //===----------------------------------------------------------------------===//
5695cde5a57SAlex Zinenko 
57052307109SNicolas Vasilache DiagnosedSilenceableFailure
57152307109SNicolas Vasilache transform::ScalarizeOp::applyToOne(linalg::LinalgOp target,
57252307109SNicolas Vasilache                                    SmallVectorImpl<Operation *> &results,
57352307109SNicolas Vasilache                                    transform::TransformState &state) {
5745cde5a57SAlex Zinenko   LinalgTilingOptions tilingOptions;
5755cde5a57SAlex Zinenko   tilingOptions.scalarizeDynamicDims();
5765cde5a57SAlex Zinenko   // Tiling with "scalarize_dyn_dims" actually sets the same lambda as the tile
5775cde5a57SAlex Zinenko   // sizes and asserts that it is not already set.
5785cde5a57SAlex Zinenko   SmallVector<int64_t> emptyTileSizes;
5795cde5a57SAlex Zinenko   LinalgTilingPattern pattern(getContext(), tilingOptions);
5805cde5a57SAlex Zinenko   SimpleRewriter rewriter(getContext());
5815cde5a57SAlex Zinenko   rewriter.setInsertionPoint(target);
5825cde5a57SAlex Zinenko   FailureOr<TiledLinalgOp> result =
5835cde5a57SAlex Zinenko       pattern.returningMatchAndRewrite(target, rewriter);
5845cde5a57SAlex Zinenko   if (failed(result))
58552307109SNicolas Vasilache     return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
5865cde5a57SAlex Zinenko 
58752307109SNicolas Vasilache   results.push_back(result->op);
58852307109SNicolas Vasilache   return DiagnosedSilenceableFailure(success());
5895cde5a57SAlex Zinenko }
5905cde5a57SAlex Zinenko 
5915cde5a57SAlex Zinenko //===----------------------------------------------------------------------===//
592ff6e5508SAlex Zinenko // SplitOp
593ff6e5508SAlex Zinenko //===----------------------------------------------------------------------===//
594ff6e5508SAlex Zinenko 
595ff6e5508SAlex Zinenko DiagnosedSilenceableFailure SplitOp::apply(TransformResults &results,
596ff6e5508SAlex Zinenko                                            TransformState &state) {
597ff6e5508SAlex Zinenko   // Collect the dynamic split points if provided.
598ff6e5508SAlex Zinenko   ArrayRef<Operation *> payload = state.getPayloadOps(getTarget());
599ff6e5508SAlex Zinenko   SimpleRewriter rewriter(getContext());
600ff6e5508SAlex Zinenko   SmallVector<OpFoldResult> splitPoints;
601ff6e5508SAlex Zinenko   splitPoints.reserve(payload.size());
602ff6e5508SAlex Zinenko   if (getDynamicSplitPoint()) {
603ff6e5508SAlex Zinenko     auto diag = DiagnosedSilenceableFailure::success();
604ff6e5508SAlex Zinenko     splitPoints = llvm::to_vector(llvm::map_range(
605ff6e5508SAlex Zinenko         state.getPayloadOps(getDynamicSplitPoint()), [&](Operation *op) {
606ff6e5508SAlex Zinenko           if (op->getNumResults() != 1 ||
607ff6e5508SAlex Zinenko               !op->getResult(0).getType().isIndex()) {
608ff6e5508SAlex Zinenko             diag = emitSilenceableError()
609ff6e5508SAlex Zinenko                    << "expected dynamic split point handle to point to a "
610ff6e5508SAlex Zinenko                       "single-result index-typed op";
611ff6e5508SAlex Zinenko             diag.attachNote(op->getLoc()) << "dynamic split point";
612ff6e5508SAlex Zinenko           }
613ff6e5508SAlex Zinenko           return OpFoldResult(op->getResult(0));
614ff6e5508SAlex Zinenko         }));
615ff6e5508SAlex Zinenko     if (!diag.succeeded())
616ff6e5508SAlex Zinenko       return diag;
617ff6e5508SAlex Zinenko 
618ff6e5508SAlex Zinenko     if (splitPoints.size() != payload.size()) {
619ff6e5508SAlex Zinenko       emitError() << "expected the dynamic split point handle to point to as "
620ff6e5508SAlex Zinenko                      "many operations ("
621ff6e5508SAlex Zinenko                   << splitPoints.size() << ") as the target handle ("
622ff6e5508SAlex Zinenko                   << payload.size() << ")";
623ff6e5508SAlex Zinenko       return DiagnosedSilenceableFailure::definiteFailure();
624ff6e5508SAlex Zinenko     }
625ff6e5508SAlex Zinenko   } else {
626ff6e5508SAlex Zinenko     splitPoints.resize(payload.size(),
627ff6e5508SAlex Zinenko                        rewriter.getIndexAttr(getStaticSplitPoint()));
628ff6e5508SAlex Zinenko   }
629ff6e5508SAlex Zinenko 
630ff6e5508SAlex Zinenko   // Split each target operation.
631ff6e5508SAlex Zinenko   SmallVector<Operation *> first, second;
632ff6e5508SAlex Zinenko   for (const auto &pair : llvm::zip(payload, splitPoints)) {
633ff6e5508SAlex Zinenko     Operation *target = std::get<0>(pair);
634ff6e5508SAlex Zinenko     auto linalgOp = dyn_cast<LinalgOp>(target);
635ff6e5508SAlex Zinenko     if (!linalgOp) {
636ff6e5508SAlex Zinenko       auto diag = emitSilenceableError() << "only applies to structured ops";
637ff6e5508SAlex Zinenko       diag.attachNote(target->getLoc()) << "target op";
638ff6e5508SAlex Zinenko       return diag;
639ff6e5508SAlex Zinenko     }
640ff6e5508SAlex Zinenko 
641ff6e5508SAlex Zinenko     if (getDimension() >= linalgOp.getNumLoops()) {
642ff6e5508SAlex Zinenko       auto diag = emitSilenceableError() << "dimension " << getDimension()
643ff6e5508SAlex Zinenko                                          << " does not exist in target op";
644ff6e5508SAlex Zinenko       diag.attachNote(target->getLoc()) << "target op";
645ff6e5508SAlex Zinenko       return diag;
646ff6e5508SAlex Zinenko     }
647ff6e5508SAlex Zinenko 
648ff6e5508SAlex Zinenko     rewriter.setInsertionPoint(linalgOp);
649ff6e5508SAlex Zinenko     std::tie(first.emplace_back(), second.emplace_back()) =
650ff6e5508SAlex Zinenko         linalg::splitOp(rewriter, linalgOp, getDimension(), std::get<1>(pair));
651ff6e5508SAlex Zinenko   }
652ff6e5508SAlex Zinenko 
653ff6e5508SAlex Zinenko   results.set(getFirst().cast<OpResult>(), first);
654ff6e5508SAlex Zinenko   results.set(getSecond().cast<OpResult>(), second);
655ff6e5508SAlex Zinenko   return DiagnosedSilenceableFailure::success();
656ff6e5508SAlex Zinenko }
657ff6e5508SAlex Zinenko 
658ff6e5508SAlex Zinenko void SplitOp::getEffects(
659ff6e5508SAlex Zinenko     SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
660e15b855eSAlex Zinenko   consumesHandle(getTarget(), effects);
661e15b855eSAlex Zinenko   if (getDynamicSplitPoint())
662e15b855eSAlex Zinenko     onlyReadsHandle(getDynamicSplitPoint(), effects);
663e15b855eSAlex Zinenko   producesHandle(getResults(), effects);
664e15b855eSAlex Zinenko   modifiesPayload(effects);
665ff6e5508SAlex Zinenko }
666ff6e5508SAlex Zinenko 
667ff6e5508SAlex Zinenko ParseResult SplitOp::parse(OpAsmParser &parser, OperationState &result) {
668ff6e5508SAlex Zinenko   OpAsmParser::UnresolvedOperand target, dynamicSplitPoint;
669ff6e5508SAlex Zinenko   IntegerAttr staticSplitPoint;
670ff6e5508SAlex Zinenko   auto pdlOperationType =
671ff6e5508SAlex Zinenko       pdl::OperationType::get(parser.getBuilder().getContext());
672ff6e5508SAlex Zinenko   if (parser.parseOperand(target) ||
673ff6e5508SAlex Zinenko       parser.resolveOperand(target, pdlOperationType, result.operands) ||
674ff6e5508SAlex Zinenko       parser.parseKeyword("after"))
675ff6e5508SAlex Zinenko     return failure();
676ff6e5508SAlex Zinenko 
677ff6e5508SAlex Zinenko   OptionalParseResult dynamicPointParseResult =
678ff6e5508SAlex Zinenko       parser.parseOptionalOperand(dynamicSplitPoint);
679ff6e5508SAlex Zinenko   if (!dynamicPointParseResult.hasValue()) {
680ff6e5508SAlex Zinenko     int64_t staticSplitPointValue;
681ff6e5508SAlex Zinenko     if (failed(parser.parseInteger(staticSplitPointValue)))
682ff6e5508SAlex Zinenko       return failure();
683ff6e5508SAlex Zinenko 
684ff6e5508SAlex Zinenko     staticSplitPoint =
685ff6e5508SAlex Zinenko         parser.getBuilder().getI64IntegerAttr(staticSplitPointValue);
686ff6e5508SAlex Zinenko   } else {
687ff6e5508SAlex Zinenko     if (failed(*dynamicPointParseResult) ||
688ff6e5508SAlex Zinenko         parser.resolveOperand(dynamicSplitPoint, pdlOperationType,
689ff6e5508SAlex Zinenko                               result.operands)) {
690ff6e5508SAlex Zinenko       return failure();
691ff6e5508SAlex Zinenko     }
692ff6e5508SAlex Zinenko 
693ff6e5508SAlex Zinenko     staticSplitPoint =
694ff6e5508SAlex Zinenko         parser.getBuilder().getI64IntegerAttr(ShapedType::kDynamicSize);
695ff6e5508SAlex Zinenko   }
696ff6e5508SAlex Zinenko 
697ff6e5508SAlex Zinenko   result.addAttribute(
698ff6e5508SAlex Zinenko       SplitOp::getStaticSplitPointAttrName(result.name).getValue(),
699ff6e5508SAlex Zinenko       staticSplitPoint);
700ff6e5508SAlex Zinenko   if (failed(parser.parseOptionalAttrDict(result.attributes)))
701ff6e5508SAlex Zinenko     return failure();
702ff6e5508SAlex Zinenko 
703ff6e5508SAlex Zinenko   result.addTypes({pdlOperationType, pdlOperationType});
704ff6e5508SAlex Zinenko   return success();
705ff6e5508SAlex Zinenko }
706ff6e5508SAlex Zinenko 
707ff6e5508SAlex Zinenko void SplitOp::print(OpAsmPrinter &printer) {
708ff6e5508SAlex Zinenko   printer << " " << getTarget() << " after ";
709ff6e5508SAlex Zinenko   int64_t staticSplitSize = static_cast<int64_t>(getStaticSplitPoint());
710ff6e5508SAlex Zinenko   if (staticSplitSize != ShapedType::kDynamicSize)
711ff6e5508SAlex Zinenko     printer << staticSplitSize;
712ff6e5508SAlex Zinenko   else
713ff6e5508SAlex Zinenko     printer << getDynamicSplitPoint();
714ff6e5508SAlex Zinenko   printer << " ";
715ff6e5508SAlex Zinenko   printer.printOptionalAttrDict(getOperation()->getAttrs(),
716ff6e5508SAlex Zinenko                                 {getStaticSplitPointAttrName()});
717ff6e5508SAlex Zinenko }
718ff6e5508SAlex Zinenko 
719ff6e5508SAlex Zinenko LogicalResult SplitOp::verify() {
720ff6e5508SAlex Zinenko   if ((static_cast<int64_t>(getStaticSplitPoint()) !=
721ff6e5508SAlex Zinenko        ShapedType::kDynamicSize) ^
722ff6e5508SAlex Zinenko       (getDynamicSplitPoint() == nullptr)) {
723ff6e5508SAlex Zinenko     return emitOpError()
724ff6e5508SAlex Zinenko            << "expects either a dynamic or a static split point to be provided";
725ff6e5508SAlex Zinenko   }
726ff6e5508SAlex Zinenko   return success();
727ff6e5508SAlex Zinenko }
728ff6e5508SAlex Zinenko 
729ff6e5508SAlex Zinenko //===----------------------------------------------------------------------===//
730f439b319SNicolas Vasilache // SplitReductionOp
731f439b319SNicolas Vasilache //===----------------------------------------------------------------------===//
732f439b319SNicolas Vasilache 
73352307109SNicolas Vasilache DiagnosedSilenceableFailure
73452307109SNicolas Vasilache transform::SplitReductionOp::applyToOne(linalg::LinalgOp target,
73552307109SNicolas Vasilache                                         SmallVectorImpl<Operation *> &results,
73652307109SNicolas Vasilache                                         transform::TransformState &state) {
737f439b319SNicolas Vasilache   ControlSplitReductionFn splitFn = [&](LinalgOp) {
738f439b319SNicolas Vasilache     return std::pair<int64_t, unsigned>(getSplitFactor(),
739f439b319SNicolas Vasilache                                         getInsertSplitDimension());
740f439b319SNicolas Vasilache   };
741f439b319SNicolas Vasilache   SimpleRewriter rewriter(getContext());
742f439b319SNicolas Vasilache   rewriter.setInsertionPoint(target);
743f439b319SNicolas Vasilache   FailureOr<SplitReductionResult> splitResult =
744178f9bd6SNicolas Vasilache       (getUseScalingAlgorithm())
745178f9bd6SNicolas Vasilache           ? splitReductionByScaling(rewriter, target, splitFn, getUseAlloc())
746178f9bd6SNicolas Vasilache           : splitReduction(rewriter, target, splitFn, getUseAlloc());
747d5716395SNicolas Vasilache   if (failed(splitResult))
74852307109SNicolas Vasilache     return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
74952307109SNicolas Vasilache 
75052307109SNicolas Vasilache   results.push_back(splitResult->initOrAlloc);
75152307109SNicolas Vasilache   results.push_back(splitResult->fillOp);
75252307109SNicolas Vasilache   results.push_back(splitResult->splitLinalgOp);
75352307109SNicolas Vasilache   results.push_back(splitResult->resultCombiningLinalgOp);
75452307109SNicolas Vasilache   return DiagnosedSilenceableFailure(success());
755d5716395SNicolas Vasilache }
756d5716395SNicolas Vasilache 
757d5716395SNicolas Vasilache //===----------------------------------------------------------------------===//
7583c2a74a3SMatthias Springer // TileOp
7593c2a74a3SMatthias Springer //===----------------------------------------------------------------------===//
7603c2a74a3SMatthias Springer 
7611d45282aSAlex Zinenko DiagnosedSilenceableFailure
762e3890b7fSAlex Zinenko transform::TileOp::apply(TransformResults &transformResults,
7633c2a74a3SMatthias Springer                          TransformState &state) {
7643c2a74a3SMatthias Springer   LinalgTilingOptions tilingOptions;
76518b92c66SNicolas Vasilache   SmallVector<int64_t> tileSizes = extractFromI64ArrayAttr(getStaticSizes());
7663c2a74a3SMatthias Springer 
7674e4a4c05SAlex Zinenko   ArrayRef<Operation *> targets = state.getPayloadOps(getTarget());
7684e4a4c05SAlex Zinenko   SmallVector<ArrayRef<Operation *>> dynamicSizeProducers;
7694e4a4c05SAlex Zinenko   dynamicSizeProducers.reserve(getDynamicSizes().size());
7704e4a4c05SAlex Zinenko   for (Value dynamicSizeProducerHandle : getDynamicSizes()) {
7714e4a4c05SAlex Zinenko     dynamicSizeProducers.push_back(
7724e4a4c05SAlex Zinenko         state.getPayloadOps(dynamicSizeProducerHandle));
7734e4a4c05SAlex Zinenko 
7744e4a4c05SAlex Zinenko     if (dynamicSizeProducers.back().size() != targets.size()) {
7754e4a4c05SAlex Zinenko       DiagnosedSilenceableFailure diag =
7764e4a4c05SAlex Zinenko           emitSilenceableError()
7774e4a4c05SAlex Zinenko           << "expected as many dynamic size-producing operations ("
7784e4a4c05SAlex Zinenko           << dynamicSizeProducers.back().size() << ") as target ops ("
7794e4a4c05SAlex Zinenko           << targets.size() << ")";
7804e4a4c05SAlex Zinenko       diag.attachNote(dynamicSizeProducerHandle.getLoc()) << "for this handle";
7814e4a4c05SAlex Zinenko       return diag;
7824e4a4c05SAlex Zinenko     }
7834e4a4c05SAlex Zinenko 
7844e4a4c05SAlex Zinenko     for (Operation *op : dynamicSizeProducers.back()) {
7854e4a4c05SAlex Zinenko       if (op->getNumResults() == 1 &&
7864e4a4c05SAlex Zinenko           op->getResult(0).getType().isa<IndexType>())
7874e4a4c05SAlex Zinenko         continue;
7884e4a4c05SAlex Zinenko       DiagnosedSilenceableFailure diag =
7894e4a4c05SAlex Zinenko           emitSilenceableError() << "expected sizes to be produced by ops "
7904e4a4c05SAlex Zinenko                                     "with a single index-type result";
7914e4a4c05SAlex Zinenko       diag.attachNote(op->getLoc()) << "size producer op";
7924e4a4c05SAlex Zinenko       diag.attachNote(dynamicSizeProducerHandle.getLoc()) << "for this handle";
7934e4a4c05SAlex Zinenko       return diag;
7944e4a4c05SAlex Zinenko     }
7954e4a4c05SAlex Zinenko   }
7964e4a4c05SAlex Zinenko 
7974e4a4c05SAlex Zinenko   SmallVector<Operation *> tiled;
7984e4a4c05SAlex Zinenko   SmallVector<SmallVector<Operation *, 4>, 4> loops;
7994e4a4c05SAlex Zinenko   loops.resize(getLoops().size());
8004e4a4c05SAlex Zinenko   for (auto &en : llvm::enumerate(targets)) {
8014e4a4c05SAlex Zinenko     auto linalgOp = dyn_cast<LinalgOp>(en.value());
8024e4a4c05SAlex Zinenko     if (!linalgOp) {
8034e4a4c05SAlex Zinenko       DiagnosedSilenceableFailure diag = emitSilenceableError()
8044e4a4c05SAlex Zinenko                                          << "only linalg ops are supported";
8054e4a4c05SAlex Zinenko       diag.attachNote(en.value()->getLoc()) << "target op";
8064e4a4c05SAlex Zinenko       return diag;
8074e4a4c05SAlex Zinenko     }
8084e4a4c05SAlex Zinenko 
8094e4a4c05SAlex Zinenko     unsigned index = en.index();
8104e4a4c05SAlex Zinenko     if (!tileSizes.empty()) {
8114e4a4c05SAlex Zinenko       tilingOptions.setTileSizeComputationFunction(
8124e4a4c05SAlex Zinenko           [&, index](OpBuilder &b, Operation *) {
8134e4a4c05SAlex Zinenko             SmallVector<Value, 4> sizes;
8144e4a4c05SAlex Zinenko             sizes.reserve(tileSizes.size());
8154e4a4c05SAlex Zinenko             unsigned dynamicIdx = 0;
8164e4a4c05SAlex Zinenko             for (OpFoldResult ofr : getMixedSizes()) {
8174e4a4c05SAlex Zinenko               if (auto attr = ofr.dyn_cast<Attribute>()) {
8184e4a4c05SAlex Zinenko                 sizes.push_back(b.create<arith::ConstantIndexOp>(
8194e4a4c05SAlex Zinenko                     getLoc(), attr.cast<IntegerAttr>().getInt()));
8204e4a4c05SAlex Zinenko               } else {
8214e4a4c05SAlex Zinenko                 sizes.push_back(
8224e4a4c05SAlex Zinenko                     dynamicSizeProducers[dynamicIdx++][index]->getResult(0));
8234e4a4c05SAlex Zinenko               }
8244e4a4c05SAlex Zinenko             }
8254e4a4c05SAlex Zinenko             return sizes;
8264e4a4c05SAlex Zinenko           });
8274e4a4c05SAlex Zinenko     }
8284e4a4c05SAlex Zinenko 
8293c2a74a3SMatthias Springer     tilingOptions.setInterchange(extractUIntArray(getInterchange()));
8303c2a74a3SMatthias Springer     LinalgTilingPattern pattern(getContext(), tilingOptions);
8313c2a74a3SMatthias Springer     SimpleRewriter rewriter(linalgOp.getContext());
8324e4a4c05SAlex Zinenko     FailureOr<TiledLinalgOp> tiledOp =
8334e4a4c05SAlex Zinenko         pattern.returningMatchAndRewrite(linalgOp, rewriter);
8344e4a4c05SAlex Zinenko     if (failed(tiledOp))
8354e4a4c05SAlex Zinenko       return DiagnosedSilenceableFailure::definiteFailure();
8364e4a4c05SAlex Zinenko 
8374e4a4c05SAlex Zinenko     tiled.push_back(tiledOp->op);
8384e4a4c05SAlex Zinenko     for (const auto &en2 : llvm::enumerate(tiledOp->loops))
8394e4a4c05SAlex Zinenko       loops[en2.index()].push_back(en2.value());
8404e4a4c05SAlex Zinenko   }
8414e4a4c05SAlex Zinenko 
8424e4a4c05SAlex Zinenko   transformResults.set(getTiledLinalgOp().cast<OpResult>(), tiled);
8434e4a4c05SAlex Zinenko   for (const auto &en : llvm::enumerate(loops))
8444e4a4c05SAlex Zinenko     transformResults.set(getLoops()[en.index()].cast<OpResult>(), en.value());
8454e4a4c05SAlex Zinenko 
8464e4a4c05SAlex Zinenko   return DiagnosedSilenceableFailure::success();
8474e4a4c05SAlex Zinenko }
8484e4a4c05SAlex Zinenko 
8494e4a4c05SAlex Zinenko SmallVector<OpFoldResult> transform::TileOp::getMixedSizes() {
8504e4a4c05SAlex Zinenko   ValueRange dynamic = getDynamicSizes();
85118b92c66SNicolas Vasilache   SmallVector<int64_t> tileSizes = extractFromI64ArrayAttr(getStaticSizes());
8524e4a4c05SAlex Zinenko   SmallVector<OpFoldResult> results;
8534e4a4c05SAlex Zinenko   results.reserve(tileSizes.size());
8544e4a4c05SAlex Zinenko   unsigned dynamicPos = 0;
8554e4a4c05SAlex Zinenko   Builder builder(getContext());
8564e4a4c05SAlex Zinenko   for (int64_t size : tileSizes) {
8574e4a4c05SAlex Zinenko     if (size == ShapedType::kDynamicSize) {
8584e4a4c05SAlex Zinenko       results.push_back(dynamic[dynamicPos++]);
8594e4a4c05SAlex Zinenko     } else {
8604e4a4c05SAlex Zinenko       results.push_back(builder.getIndexAttr(size));
8614e4a4c05SAlex Zinenko     }
8624e4a4c05SAlex Zinenko   }
8634e4a4c05SAlex Zinenko   return results;
8643c2a74a3SMatthias Springer }
8653c2a74a3SMatthias Springer 
8663c2a74a3SMatthias Springer ParseResult transform::TileOp::parse(OpAsmParser &parser,
8673c2a74a3SMatthias Springer                                      OperationState &result) {
8684e4a4c05SAlex Zinenko   OpAsmParser::UnresolvedOperand target;
8694e4a4c05SAlex Zinenko   SmallVector<OpAsmParser::UnresolvedOperand> dynamicSizes;
8704e4a4c05SAlex Zinenko   ArrayAttr staticSizes;
8714e4a4c05SAlex Zinenko   auto pdlOperationType = pdl::OperationType::get(parser.getContext());
8724e4a4c05SAlex Zinenko   if (parser.parseOperand(target) ||
8734e4a4c05SAlex Zinenko       parser.resolveOperand(target, pdlOperationType, result.operands) ||
8744e4a4c05SAlex Zinenko       parseOperandsOrIntegersSizesList(parser, dynamicSizes, staticSizes) ||
8754e4a4c05SAlex Zinenko       parser.resolveOperands(dynamicSizes, pdlOperationType, result.operands) ||
8764e4a4c05SAlex Zinenko       parser.parseOptionalAttrDict(result.attributes))
8774e4a4c05SAlex Zinenko     return ParseResult::failure();
8784e4a4c05SAlex Zinenko 
8794e4a4c05SAlex Zinenko   result.addAttribute(getStaticSizesAttrName(result.name), staticSizes);
8804e4a4c05SAlex Zinenko   size_t numExpectedLoops =
88118b92c66SNicolas Vasilache       staticSizes.size() - llvm::count(extractFromI64ArrayAttr(staticSizes), 0);
8824e4a4c05SAlex Zinenko   result.addTypes(SmallVector<Type>(numExpectedLoops + 1, pdlOperationType));
8834e4a4c05SAlex Zinenko   return success();
8843c2a74a3SMatthias Springer }
8853c2a74a3SMatthias Springer 
8863c2a74a3SMatthias Springer void TileOp::print(OpAsmPrinter &p) {
8874e4a4c05SAlex Zinenko   p << ' ' << getTarget();
8884e4a4c05SAlex Zinenko   printOperandsOrIntegersSizesList(p, getOperation(), getDynamicSizes(),
8894e4a4c05SAlex Zinenko                                    getStaticSizes());
8904e4a4c05SAlex Zinenko   p.printOptionalAttrDict((*this)->getAttrs(), {getStaticSizesAttrName()});
8914e4a4c05SAlex Zinenko }
8924e4a4c05SAlex Zinenko 
8934e4a4c05SAlex Zinenko void transform::TileOp::getEffects(
8944e4a4c05SAlex Zinenko     SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
8954e4a4c05SAlex Zinenko   consumesHandle(getTarget(), effects);
8964e4a4c05SAlex Zinenko   onlyReadsHandle(getDynamicSizes(), effects);
8974e4a4c05SAlex Zinenko   producesHandle(getTiledLinalgOp(), effects);
8984e4a4c05SAlex Zinenko   producesHandle(getLoops(), effects);
8994e4a4c05SAlex Zinenko   modifiesPayload(effects);
9003c2a74a3SMatthias Springer }
9013c2a74a3SMatthias Springer 
9023c2a74a3SMatthias Springer //===----------------------------------------------------------------------===//
90318b92c66SNicolas Vasilache // TileToForeachThreadOp
90418b92c66SNicolas Vasilache //===----------------------------------------------------------------------===//
90518b92c66SNicolas Vasilache 
90618b92c66SNicolas Vasilache DiagnosedSilenceableFailure transform::TileToForeachThreadOp::applyToOne(
90718b92c66SNicolas Vasilache     TilingInterface target, SmallVectorImpl<Operation *> &results,
90818b92c66SNicolas Vasilache     transform::TransformState &state) {
90918b92c66SNicolas Vasilache   IRRewriter rewriter(getContext());
91018b92c66SNicolas Vasilache   rewriter.setInsertionPoint(target);
91118b92c66SNicolas Vasilache   auto maybeThreadDimMappingAttr = getThreadDimMapping();
912*297ba167SChristopher Bate   auto dimMapping =
913*297ba167SChristopher Bate       llvm::to_vector(maybeThreadDimMappingAttr
91418b92c66SNicolas Vasilache                           ? extractFromI64ArrayAttr(*maybeThreadDimMappingAttr)
91518b92c66SNicolas Vasilache                           : ArrayRef<int64_t>{});
916*297ba167SChristopher Bate 
917*297ba167SChristopher Bate   FailureOr<ForeachThreadTilingResult> tilingResult = failure();
918*297ba167SChristopher Bate   if (Optional<ArrayAttr> numThreads = getNumThreads())
919*297ba167SChristopher Bate     tilingResult = linalg::tileToForeachThreadOp(
920*297ba167SChristopher Bate         rewriter, target, getAsOpFoldResult(*numThreads), dimMapping);
921*297ba167SChristopher Bate 
922*297ba167SChristopher Bate   if (Optional<ArrayAttr> tileSizes = getTileSizes())
923*297ba167SChristopher Bate     tilingResult = linalg::tileToForeachThreadOpUsingTileSizes(
924*297ba167SChristopher Bate         rewriter, target, getAsOpFoldResult(*tileSizes), dimMapping);
925*297ba167SChristopher Bate 
92618b92c66SNicolas Vasilache   if (failed(tilingResult))
92718b92c66SNicolas Vasilache     return emitDefaultSilenceableFailure(target);
92818b92c66SNicolas Vasilache   rewriter.replaceOp(target, tilingResult->tileOp->getResults());
92918b92c66SNicolas Vasilache   results.assign({tilingResult->tileOp, tilingResult->tiledOp});
93018b92c66SNicolas Vasilache   return DiagnosedSilenceableFailure(success());
93118b92c66SNicolas Vasilache }
93218b92c66SNicolas Vasilache 
93318b92c66SNicolas Vasilache //===----------------------------------------------------------------------===//
934cc6c1592SAlex Zinenko // VectorizeOp
935cc6c1592SAlex Zinenko //===----------------------------------------------------------------------===//
936cc6c1592SAlex Zinenko 
93752307109SNicolas Vasilache DiagnosedSilenceableFailure
93852307109SNicolas Vasilache transform::VectorizeOp::applyToOne(Operation *target,
93952307109SNicolas Vasilache                                    SmallVectorImpl<Operation *> &results,
94052307109SNicolas Vasilache                                    transform::TransformState &state) {
941cc6c1592SAlex Zinenko   if (!target->hasTrait<OpTrait::IsIsolatedFromAbove>()) {
94252307109SNicolas Vasilache     auto diag = this->emitOpError("requires isolated-from-above targets");
943cc6c1592SAlex Zinenko     diag.attachNote(target->getLoc()) << "non-isolated target";
94452307109SNicolas Vasilache     return DiagnosedSilenceableFailure::definiteFailure();
945cc6c1592SAlex Zinenko   }
946cc6c1592SAlex Zinenko 
947cc6c1592SAlex Zinenko   MLIRContext *ctx = getContext();
948cc6c1592SAlex Zinenko   RewritePatternSet patterns(ctx);
949cc6c1592SAlex Zinenko   patterns.add<LinalgVectorizationPattern>(ctx);
950cc6c1592SAlex Zinenko 
951cc6c1592SAlex Zinenko   vector::populateVectorTransferPermutationMapLoweringPatterns(patterns);
952cc6c1592SAlex Zinenko   vector::populateVectorReductionToContractPatterns(patterns);
953cc6c1592SAlex Zinenko   patterns.add<linalg::LinalgCopyVTRForwardingPattern,
954cc6c1592SAlex Zinenko                linalg::LinalgCopyVTWForwardingPattern>(ctx,
955cc6c1592SAlex Zinenko                                                        /*benefit=*/2);
956cc6c1592SAlex Zinenko   vector::TransferReadOp::getCanonicalizationPatterns(patterns, ctx);
957cc6c1592SAlex Zinenko   vector::TransferWriteOp::getCanonicalizationPatterns(patterns, ctx);
958cc6c1592SAlex Zinenko   if (getVectorizePadding())
959cc6c1592SAlex Zinenko     linalg::populatePadOpVectorizationPatterns(patterns);
960cc6c1592SAlex Zinenko 
9615f0d4f20SAlex Zinenko   if (failed(applyPatternsAndFoldGreedily(target, std::move(patterns))))
96252307109SNicolas Vasilache     return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
96352307109SNicolas Vasilache 
96452307109SNicolas Vasilache   results.push_back(target);
96552307109SNicolas Vasilache   return DiagnosedSilenceableFailure(success());
966cc6c1592SAlex Zinenko }
967cc6c1592SAlex Zinenko 
968cc6c1592SAlex Zinenko //===----------------------------------------------------------------------===//
9693c2a74a3SMatthias Springer // Transform op registration
9703c2a74a3SMatthias Springer //===----------------------------------------------------------------------===//
9713c2a74a3SMatthias Springer 
9723c2a74a3SMatthias Springer namespace {
9733c2a74a3SMatthias Springer /// Registers new ops and declares PDL as dependent dialect since the additional
9743c2a74a3SMatthias Springer /// ops are using PDL types for operands and results.
9753c2a74a3SMatthias Springer class LinalgTransformDialectExtension
9763c2a74a3SMatthias Springer     : public transform::TransformDialectExtension<
9773c2a74a3SMatthias Springer           LinalgTransformDialectExtension> {
9783c2a74a3SMatthias Springer public:
9793c2a74a3SMatthias Springer   LinalgTransformDialectExtension() {
9803963b4d0SAlex Zinenko     declareDependentDialect<AffineDialect>();
9814e4a4c05SAlex Zinenko     declareDependentDialect<arith::ArithmeticDialect>();
9823c2a74a3SMatthias Springer     declareDependentDialect<pdl::PDLDialect>();
9833c2a74a3SMatthias Springer     declareDependentDialect<scf::SCFDialect>();
984cc6c1592SAlex Zinenko     declareDependentDialect<vector::VectorDialect>();
9853c2a74a3SMatthias Springer     registerTransformOps<
9863c2a74a3SMatthias Springer #define GET_OP_LIST
9873c2a74a3SMatthias Springer #include "mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp.inc"
9883c2a74a3SMatthias Springer         >();
9893c2a74a3SMatthias Springer   }
9903c2a74a3SMatthias Springer };
9913c2a74a3SMatthias Springer } // namespace
9923c2a74a3SMatthias Springer 
9931f77f01cSNicolas Vasilache #include "mlir/Dialect/Linalg/TransformOps/LinalgTransformOpsEnums.cpp.inc"
9941f77f01cSNicolas Vasilache 
9953c2a74a3SMatthias Springer #define GET_OP_CLASSES
9963c2a74a3SMatthias Springer #include "mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp.inc"
9973c2a74a3SMatthias Springer 
9983c2a74a3SMatthias Springer void mlir::linalg::registerTransformDialectExtension(
9993c2a74a3SMatthias Springer     DialectRegistry &registry) {
10003c2a74a3SMatthias Springer   registry.addExtensions<LinalgTransformDialectExtension>();
10013c2a74a3SMatthias Springer }
1002