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