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 ®istry) { 10003c2a74a3SMatthias Springer registry.addExtensions<LinalgTransformDialectExtension>(); 10013c2a74a3SMatthias Springer } 1002