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" 18*cc6c1592SAlex Zinenko #include "mlir/Transforms/GreedyPatternRewriteDriver.h" 193c2a74a3SMatthias Springer #include "llvm/Support/FormatVariadic.h" 203c2a74a3SMatthias Springer 213c2a74a3SMatthias Springer using namespace mlir; 223c2a74a3SMatthias Springer using namespace mlir::linalg; 233c2a74a3SMatthias Springer using namespace mlir::transform; 243c2a74a3SMatthias Springer 253c2a74a3SMatthias Springer /// Extracts a vector of int64_t from an array attribute. Asserts if the 263c2a74a3SMatthias Springer /// attribute contains values other than integers. 273c2a74a3SMatthias Springer static SmallVector<int64_t> extractI64Array(ArrayAttr attr) { 283c2a74a3SMatthias Springer SmallVector<int64_t> result; 293c2a74a3SMatthias Springer result.reserve(attr.size()); 303c2a74a3SMatthias Springer for (APInt value : attr.getAsValueRange<IntegerAttr>()) 313c2a74a3SMatthias Springer result.push_back(value.getSExtValue()); 323c2a74a3SMatthias Springer return result; 333c2a74a3SMatthias Springer } 343c2a74a3SMatthias Springer 353c2a74a3SMatthias Springer /// Extracts a vector of unsigned from an array attribute. Asserts if the 363c2a74a3SMatthias Springer /// attribute contains values other than intergers. May truncate. 373c2a74a3SMatthias Springer static SmallVector<unsigned> extractUIntArray(ArrayAttr attr) { 383c2a74a3SMatthias Springer SmallVector<unsigned> result; 393c2a74a3SMatthias Springer result.reserve(attr.size()); 403c2a74a3SMatthias Springer for (APInt value : attr.getAsValueRange<IntegerAttr>()) 413c2a74a3SMatthias Springer result.push_back(value.getZExtValue()); 423c2a74a3SMatthias Springer return result; 433c2a74a3SMatthias Springer } 443c2a74a3SMatthias Springer 453c2a74a3SMatthias Springer namespace { 463c2a74a3SMatthias Springer /// A simple pattern rewriter that implements no special logic. 473c2a74a3SMatthias Springer class SimpleRewriter : public PatternRewriter { 483c2a74a3SMatthias Springer public: 493c2a74a3SMatthias Springer SimpleRewriter(MLIRContext *context) : PatternRewriter(context) {} 503c2a74a3SMatthias Springer }; 513c2a74a3SMatthias Springer } // namespace 523c2a74a3SMatthias Springer 533c2a74a3SMatthias Springer //===----------------------------------------------------------------------===// 545cde5a57SAlex Zinenko // InterchangeOp 555cde5a57SAlex Zinenko //===----------------------------------------------------------------------===// 565cde5a57SAlex Zinenko 575cde5a57SAlex Zinenko FailureOr<LinalgOp> transform::InterchangeOp::applyToOne(LinalgOp target) { 585cde5a57SAlex Zinenko SmallVector<unsigned> interchangeVector = 595cde5a57SAlex Zinenko extractUIntArray(getIteratorInterchange()); 605cde5a57SAlex Zinenko // Exit early if no transformation is needed. 615cde5a57SAlex Zinenko if (interchangeVector.empty()) 625cde5a57SAlex Zinenko return target; 635cde5a57SAlex Zinenko 645cde5a57SAlex Zinenko auto genericTarget = dyn_cast<GenericOp>(target.getOperation()); 655cde5a57SAlex Zinenko if (!genericTarget) { 665cde5a57SAlex Zinenko InFlightDiagnostic diag = emitOpError() 675cde5a57SAlex Zinenko << "applies to " << GenericOp::getOperationName() 685cde5a57SAlex Zinenko << " ops"; 695cde5a57SAlex Zinenko diag.attachNote(target.getLoc()) << "attempted to apply to this op"; 705cde5a57SAlex Zinenko return diag; 715cde5a57SAlex Zinenko } 725cde5a57SAlex Zinenko 735cde5a57SAlex Zinenko GenericOpInterchangePattern pattern(getContext(), interchangeVector); 745cde5a57SAlex Zinenko SimpleRewriter rewriter(getContext()); 755cde5a57SAlex Zinenko rewriter.setInsertionPoint(target); 765cde5a57SAlex Zinenko FailureOr<GenericOp> result = 775cde5a57SAlex Zinenko pattern.returningMatchAndRewrite(genericTarget, rewriter); 785cde5a57SAlex Zinenko if (failed(result)) 795cde5a57SAlex Zinenko return failure(); 805cde5a57SAlex Zinenko 815cde5a57SAlex Zinenko return cast<LinalgOp>(result->getOperation()); 825cde5a57SAlex Zinenko } 835cde5a57SAlex Zinenko 845cde5a57SAlex Zinenko LogicalResult transform::InterchangeOp::verify() { 855cde5a57SAlex Zinenko SmallVector<unsigned> permutation = 865cde5a57SAlex Zinenko extractUIntArray(getIteratorInterchange()); 875cde5a57SAlex Zinenko auto sequence = llvm::to_vector(llvm::seq<unsigned>(0, permutation.size())); 885cde5a57SAlex Zinenko if (!std::is_permutation(sequence.begin(), sequence.end(), 895cde5a57SAlex Zinenko permutation.begin(), permutation.end())) { 905cde5a57SAlex Zinenko return emitOpError() 915cde5a57SAlex Zinenko << "expects iterator_interchange to be a permutation, found " 925cde5a57SAlex Zinenko << getIteratorInterchange(); 935cde5a57SAlex Zinenko } 945cde5a57SAlex Zinenko return success(); 955cde5a57SAlex Zinenko } 965cde5a57SAlex Zinenko 975cde5a57SAlex Zinenko //===---------------------------------------------------------------------===// 985cde5a57SAlex Zinenko // PadOp 995cde5a57SAlex Zinenko //===---------------------------------------------------------------------===// 1005cde5a57SAlex Zinenko 1015cde5a57SAlex Zinenko FailureOr<LinalgOp> transform::PadOp::applyToOne(LinalgOp target) { 1025cde5a57SAlex Zinenko // Convert the integer packing flags to booleans. 1035cde5a57SAlex Zinenko SmallVector<bool> packPaddings; 1045cde5a57SAlex Zinenko for (int64_t packPadding : extractI64Array(getPackPaddings())) 1055cde5a57SAlex Zinenko packPaddings.push_back(static_cast<bool>(packPadding)); 1065cde5a57SAlex Zinenko 1075cde5a57SAlex Zinenko // Convert the padding values to attributes. 1085cde5a57SAlex Zinenko SmallVector<Attribute> paddingValues; 1095cde5a57SAlex Zinenko for (auto const &it : 1105cde5a57SAlex Zinenko llvm::zip(getPaddingValues(), target->getOperandTypes())) { 1115cde5a57SAlex Zinenko Attribute attr = std::get<0>(it); 1125cde5a57SAlex Zinenko Type elementType = getElementTypeOrSelf(std::get<1>(it)); 1135cde5a57SAlex Zinenko // Try to parse string attributes to obtain an attribute of element type. 1145cde5a57SAlex Zinenko if (auto stringAttr = attr.dyn_cast<StringAttr>()) { 1155cde5a57SAlex Zinenko paddingValues.push_back( 1165cde5a57SAlex Zinenko parseAttribute(attr.cast<StringAttr>(), elementType)); 1175cde5a57SAlex Zinenko if (!paddingValues.back()) { 1185cde5a57SAlex Zinenko InFlightDiagnostic diag = emitOpError() 1195cde5a57SAlex Zinenko << "expects a padding value that parses to " 1205cde5a57SAlex Zinenko << elementType << ", got " << std::get<0>(it); 1215cde5a57SAlex Zinenko diag.attachNote(target.getLoc()) << "when applied to this op"; 1225cde5a57SAlex Zinenko return diag; 1235cde5a57SAlex Zinenko } 1245cde5a57SAlex Zinenko continue; 1255cde5a57SAlex Zinenko } 1265cde5a57SAlex Zinenko // Otherwise, add the attribute directly. 1275cde5a57SAlex Zinenko if (attr.getType() != elementType) { 1285cde5a57SAlex Zinenko InFlightDiagnostic diag = emitOpError() 1295cde5a57SAlex Zinenko << "expects a padding value of type " 1305cde5a57SAlex Zinenko << elementType << ", got " << attr; 1315cde5a57SAlex Zinenko diag.attachNote(target.getLoc()) << "when applied to this op"; 1325cde5a57SAlex Zinenko return diag; 1335cde5a57SAlex Zinenko } 1345cde5a57SAlex Zinenko paddingValues.push_back(attr); 1355cde5a57SAlex Zinenko } 1365cde5a57SAlex Zinenko 1375cde5a57SAlex Zinenko // Extract the transpose vectors. 1385cde5a57SAlex Zinenko SmallVector<SmallVector<int64_t>> transposePaddings; 1395cde5a57SAlex Zinenko for (Attribute transposeVector : getTransposePaddings().cast<ArrayAttr>()) 1405cde5a57SAlex Zinenko transposePaddings.push_back( 1415cde5a57SAlex Zinenko extractI64Array(transposeVector.cast<ArrayAttr>())); 1425cde5a57SAlex Zinenko 1435cde5a57SAlex Zinenko LinalgPaddingOptions paddingOptions; 1445cde5a57SAlex Zinenko paddingOptions.setPaddingValues(paddingValues); 1455cde5a57SAlex Zinenko paddingOptions.setPaddingDimensions(extractI64Array(getPaddingDimensions())); 1465cde5a57SAlex Zinenko paddingOptions.setPackPaddings(packPaddings); 1475cde5a57SAlex Zinenko paddingOptions.setHoistPaddings(extractI64Array(getHoistPaddings())); 1485cde5a57SAlex Zinenko paddingOptions.setTransposePaddings(transposePaddings); 1495cde5a57SAlex Zinenko 1505cde5a57SAlex Zinenko LinalgPaddingPattern pattern(getContext(), paddingOptions); 1515cde5a57SAlex Zinenko SimpleRewriter rewriter(getContext()); 1525cde5a57SAlex Zinenko rewriter.setInsertionPoint(target); 1535cde5a57SAlex Zinenko FailureOr<LinalgOp> patternResult = 1545cde5a57SAlex Zinenko pattern.returningMatchAndRewrite(target, rewriter); 1555cde5a57SAlex Zinenko if (failed(patternResult)) { 1565cde5a57SAlex Zinenko InFlightDiagnostic diag = emitError() 1575cde5a57SAlex Zinenko << "failed to apply pattern to target op"; 1585cde5a57SAlex Zinenko diag.attachNote(target.getLoc()) << "target op"; 1595cde5a57SAlex Zinenko return diag; 1605cde5a57SAlex Zinenko } 1615cde5a57SAlex Zinenko return patternResult; 1625cde5a57SAlex Zinenko } 1635cde5a57SAlex Zinenko 1645cde5a57SAlex Zinenko LogicalResult transform::PadOp::verify() { 1655cde5a57SAlex Zinenko SmallVector<int64_t> packPaddings = extractI64Array(getPackPaddings()); 1665cde5a57SAlex Zinenko if (any_of(packPaddings, [](int64_t packPadding) { 1675cde5a57SAlex Zinenko return packPadding != 0 && packPadding != 1; 1685cde5a57SAlex Zinenko })) { 1695cde5a57SAlex Zinenko return emitOpError() 1705cde5a57SAlex Zinenko << "expects pack_paddings to contain booleans (0/1), found " 1715cde5a57SAlex Zinenko << getPackPaddings(); 1725cde5a57SAlex Zinenko } 1735cde5a57SAlex Zinenko 1745cde5a57SAlex Zinenko SmallVector<int64_t> paddingDimensions = 1755cde5a57SAlex Zinenko extractI64Array(getPaddingDimensions()); 1765cde5a57SAlex Zinenko if (any_of(paddingDimensions, 1775cde5a57SAlex Zinenko [](int64_t paddingDimension) { return paddingDimension < 0; })) { 1785cde5a57SAlex Zinenko return emitOpError() 1795cde5a57SAlex Zinenko << "expects padding_dimensions to contain positive integers, found " 1805cde5a57SAlex Zinenko << getPaddingDimensions(); 1815cde5a57SAlex Zinenko } 1825cde5a57SAlex Zinenko 1835cde5a57SAlex Zinenko SmallVector<int64_t> hoistPaddings = extractI64Array(getHoistPaddings()); 1845cde5a57SAlex Zinenko if (any_of(hoistPaddings, 1855cde5a57SAlex Zinenko [](int64_t hoistPadding) { return hoistPadding < 0; })) { 1865cde5a57SAlex Zinenko return emitOpError() 1875cde5a57SAlex Zinenko << "expects hoist_paddings to contain positive integers, found " 1885cde5a57SAlex Zinenko << getHoistPaddings(); 1895cde5a57SAlex Zinenko } 1905cde5a57SAlex Zinenko 1915cde5a57SAlex Zinenko ArrayAttr transposes = getTransposePaddings(); 1925cde5a57SAlex Zinenko for (Attribute attr : transposes) { 1935cde5a57SAlex Zinenko SmallVector<int64_t> transpose = extractFromI64ArrayAttr(attr); 1945cde5a57SAlex Zinenko auto sequence = llvm::to_vector(llvm::seq<int64_t>(0, transpose.size())); 1955cde5a57SAlex Zinenko if (!std::is_permutation(sequence.begin(), sequence.end(), 1965cde5a57SAlex Zinenko transpose.begin(), transpose.end())) { 1975cde5a57SAlex Zinenko return emitOpError() 1985cde5a57SAlex Zinenko << "expects transpose_paddings to be a permutation, found " 1995cde5a57SAlex Zinenko << attr; 2005cde5a57SAlex Zinenko } 2015cde5a57SAlex Zinenko } 2025cde5a57SAlex Zinenko return success(); 2035cde5a57SAlex Zinenko } 2045cde5a57SAlex Zinenko 2055cde5a57SAlex Zinenko //===----------------------------------------------------------------------===// 2065cde5a57SAlex Zinenko // ScalarizeOp 2075cde5a57SAlex Zinenko //===----------------------------------------------------------------------===// 2085cde5a57SAlex Zinenko 2095cde5a57SAlex Zinenko FailureOr<LinalgOp> transform::ScalarizeOp::applyToOne(LinalgOp target) { 2105cde5a57SAlex Zinenko LinalgTilingOptions tilingOptions; 2115cde5a57SAlex Zinenko tilingOptions.scalarizeDynamicDims(); 2125cde5a57SAlex Zinenko // Tiling with "scalarize_dyn_dims" actually sets the same lambda as the tile 2135cde5a57SAlex Zinenko // sizes and asserts that it is not already set. 2145cde5a57SAlex Zinenko SmallVector<int64_t> emptyTileSizes; 2155cde5a57SAlex Zinenko LinalgTilingPattern pattern(getContext(), tilingOptions); 2165cde5a57SAlex Zinenko SimpleRewriter rewriter(getContext()); 2175cde5a57SAlex Zinenko rewriter.setInsertionPoint(target); 2185cde5a57SAlex Zinenko FailureOr<TiledLinalgOp> result = 2195cde5a57SAlex Zinenko pattern.returningMatchAndRewrite(target, rewriter); 2205cde5a57SAlex Zinenko if (failed(result)) 2215cde5a57SAlex Zinenko return failure(); 2225cde5a57SAlex Zinenko 2235cde5a57SAlex Zinenko return result->op; 2245cde5a57SAlex Zinenko } 2255cde5a57SAlex Zinenko 2265cde5a57SAlex Zinenko //===----------------------------------------------------------------------===// 2273c2a74a3SMatthias Springer // TileOp 2283c2a74a3SMatthias Springer //===----------------------------------------------------------------------===// 2293c2a74a3SMatthias Springer 2303c2a74a3SMatthias Springer /// Apply a tiling transformation to all payload ops and store both the 2313c2a74a3SMatthias Springer /// tiled operation as well as the created tile loops. 2323c2a74a3SMatthias Springer static LogicalResult 2333c2a74a3SMatthias Springer applyTilingToAll(Operation *transformOp, Value target, 2343c2a74a3SMatthias Springer ArrayRef<int64_t> tileSizes, 2353c2a74a3SMatthias Springer transform::TransformResults &transformResults, 2363c2a74a3SMatthias Springer transform::TransformState &state, 2373c2a74a3SMatthias Springer function_ref<FailureOr<TiledLinalgOp>(LinalgOp)> applyFn) { 2383c2a74a3SMatthias Springer // Number of loops: Number of tiles sizes that are not zero. 2393c2a74a3SMatthias Springer size_t numLoops = tileSizes.size() - llvm::count(tileSizes, 0); 2403c2a74a3SMatthias Springer // All payload ops. These should all be LinalgOps for now. 2413c2a74a3SMatthias Springer ArrayRef<Operation *> payloadOps = state.getPayloadOps(target); 2423c2a74a3SMatthias Springer 2433c2a74a3SMatthias Springer SmallVector<Operation *> tiledLinalgOps; 2443c2a74a3SMatthias Springer SmallVector<SmallVector<Operation *>> loopOps(numLoops); 2453c2a74a3SMatthias Springer for (unsigned int i = 0; i < numLoops; ++i) 2463c2a74a3SMatthias Springer loopOps[i].reserve(payloadOps.size()); 2473c2a74a3SMatthias Springer 2483c2a74a3SMatthias Springer for (Operation *target : payloadOps) { 2493c2a74a3SMatthias Springer auto linalgOp = dyn_cast<linalg::LinalgOp>(target); 2503c2a74a3SMatthias Springer if (!linalgOp) 2513c2a74a3SMatthias Springer return transformOp->emitError("only LinalgOps are supported"); 2523c2a74a3SMatthias Springer 2533c2a74a3SMatthias Springer FailureOr<TiledLinalgOp> tiled = applyFn(linalgOp); 2543c2a74a3SMatthias Springer if (failed(tiled)) 2553c2a74a3SMatthias Springer return failure(); 2563c2a74a3SMatthias Springer 2573c2a74a3SMatthias Springer tiledLinalgOps.push_back(tiled->op); 2583c2a74a3SMatthias Springer if (tiled->loops.size() != numLoops) 2593c2a74a3SMatthias Springer // Not enough loops were generated. This usually means that the input size 2603c2a74a3SMatthias Springer // was smaller than the tiling size. 2613c2a74a3SMatthias Springer // TODO: LinalgTilingPattern should return failure(). 2623c2a74a3SMatthias Springer return failure(); 2633c2a74a3SMatthias Springer for (unsigned int i = 0; i < numLoops; ++i) 2643c2a74a3SMatthias Springer loopOps[i].push_back(tiled->loops[i]); 2653c2a74a3SMatthias Springer } 2663c2a74a3SMatthias Springer 2673c2a74a3SMatthias Springer transformResults.set(transformOp->getOpResult(0), tiledLinalgOps); 2683c2a74a3SMatthias Springer for (unsigned int i = 0; i < numLoops; ++i) 2693c2a74a3SMatthias Springer transformResults.set(transformOp->getOpResult(i + 1), loopOps[i]); 2703c2a74a3SMatthias Springer return success(); 2713c2a74a3SMatthias Springer } 2723c2a74a3SMatthias Springer 2733c2a74a3SMatthias Springer LogicalResult transform::TileOp::apply(TransformResults &transformResults, 2743c2a74a3SMatthias Springer TransformState &state) { 2753c2a74a3SMatthias Springer LinalgTilingOptions tilingOptions; 2763c2a74a3SMatthias Springer SmallVector<int64_t> tileSizes = extractI64Array(getSizes()); 2773c2a74a3SMatthias Springer 2783c2a74a3SMatthias Springer if (!tileSizes.empty()) 2793c2a74a3SMatthias Springer tilingOptions.setTileSizes(tileSizes); 2803c2a74a3SMatthias Springer tilingOptions.setInterchange(extractUIntArray(getInterchange())); 2813c2a74a3SMatthias Springer LinalgTilingPattern pattern(getContext(), tilingOptions); 2823c2a74a3SMatthias Springer 2833c2a74a3SMatthias Springer return applyTilingToAll(getOperation(), getTarget(), tileSizes, 2843c2a74a3SMatthias Springer transformResults, state, [&](LinalgOp linalgOp) { 2853c2a74a3SMatthias Springer SimpleRewriter rewriter(linalgOp.getContext()); 2863c2a74a3SMatthias Springer return pattern.returningMatchAndRewrite(linalgOp, 2873c2a74a3SMatthias Springer rewriter); 2883c2a74a3SMatthias Springer }); 2893c2a74a3SMatthias Springer } 2903c2a74a3SMatthias Springer 2913c2a74a3SMatthias Springer ParseResult transform::TileOp::parse(OpAsmParser &parser, 2923c2a74a3SMatthias Springer OperationState &result) { 2933c2a74a3SMatthias Springer StringRef sizesAttrName = TileOp::getSizesAttrName(result.name).getValue(); 2943c2a74a3SMatthias Springer OpAsmParser::UnresolvedOperand targetOperand; 2951d7b5cd5SChris Lattner SMLoc opLoc = parser.getCurrentLocation(); 2961d7b5cd5SChris Lattner if (parser.parseOperand(targetOperand) || 2971d7b5cd5SChris Lattner parser.parseOptionalAttrDict(result.attributes)) 2983c2a74a3SMatthias Springer return failure(); 2993c2a74a3SMatthias Springer Attribute sizesAttr = result.attributes.get(sizesAttrName); 3003c2a74a3SMatthias Springer if (!sizesAttr) 3013c2a74a3SMatthias Springer return parser.emitError(opLoc) 3023c2a74a3SMatthias Springer << "expected '" << sizesAttrName << "' attribute"; 3033c2a74a3SMatthias Springer auto sizesArrayAttr = sizesAttr.dyn_cast<ArrayAttr>(); 3043c2a74a3SMatthias Springer if (!sizesArrayAttr) 3053c2a74a3SMatthias Springer return parser.emitError(opLoc) 3063c2a74a3SMatthias Springer << "'" << sizesAttrName << "' attribute must be an array"; 3073c2a74a3SMatthias Springer Type pdlOpType = parser.getBuilder().getType<pdl::OperationType>(); 3083c2a74a3SMatthias Springer size_t numExpectedLoops = 3093c2a74a3SMatthias Springer sizesArrayAttr.size() - llvm::count(extractI64Array(sizesArrayAttr), 0); 3103c2a74a3SMatthias Springer result.addTypes(SmallVector<Type>(numExpectedLoops + 1, pdlOpType)); 3113c2a74a3SMatthias Springer if (parser.resolveOperand(targetOperand, pdlOpType, result.operands)) 3123c2a74a3SMatthias Springer return failure(); 3133c2a74a3SMatthias Springer return success(); 3143c2a74a3SMatthias Springer } 3153c2a74a3SMatthias Springer 3163c2a74a3SMatthias Springer void TileOp::print(OpAsmPrinter &p) { 3173c2a74a3SMatthias Springer p << ' '; 3183c2a74a3SMatthias Springer p << getTarget(); 3193c2a74a3SMatthias Springer p.printOptionalAttrDict((*this)->getAttrs()); 3203c2a74a3SMatthias Springer } 3213c2a74a3SMatthias Springer 3223c2a74a3SMatthias Springer void TileOp::getEffects( 3233c2a74a3SMatthias Springer SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>> 3243c2a74a3SMatthias Springer &effects) { 3253c2a74a3SMatthias Springer // `target` arg is consumed and can no longer be used. 3263c2a74a3SMatthias Springer effects.emplace_back(MemoryEffects::Read::get(), getTarget(), 3273c2a74a3SMatthias Springer TransformMappingResource::get()); 3283c2a74a3SMatthias Springer effects.emplace_back(MemoryEffects::Free::get(), getTarget(), 3293c2a74a3SMatthias Springer TransformMappingResource::get()); 3303c2a74a3SMatthias Springer 3313c2a74a3SMatthias Springer for (Value r : getResults()) { 3323c2a74a3SMatthias Springer effects.emplace_back(MemoryEffects::Write::get(), r, 3333c2a74a3SMatthias Springer TransformMappingResource::get()); 3343c2a74a3SMatthias Springer effects.emplace_back(MemoryEffects::Allocate::get(), r, 3353c2a74a3SMatthias Springer TransformMappingResource::get()); 3363c2a74a3SMatthias Springer } 3373c2a74a3SMatthias Springer 3383c2a74a3SMatthias Springer effects.emplace_back(MemoryEffects::Read::get(), PayloadIRResource::get()); 3393c2a74a3SMatthias Springer effects.emplace_back(MemoryEffects::Write::get(), PayloadIRResource::get()); 3403c2a74a3SMatthias Springer } 3413c2a74a3SMatthias Springer 3423c2a74a3SMatthias Springer //===----------------------------------------------------------------------===// 343*cc6c1592SAlex Zinenko // VectorizeOp 344*cc6c1592SAlex Zinenko //===----------------------------------------------------------------------===// 345*cc6c1592SAlex Zinenko 346*cc6c1592SAlex Zinenko FailureOr<Operation *> VectorizeOp::applyToOne(Operation *target) { 347*cc6c1592SAlex Zinenko if (!target->hasTrait<OpTrait::IsIsolatedFromAbove>()) { 348*cc6c1592SAlex Zinenko InFlightDiagnostic diag = emitOpError() 349*cc6c1592SAlex Zinenko << "applies only to isolated-from-above targets"; 350*cc6c1592SAlex Zinenko diag.attachNote(target->getLoc()) << "non-isolated target"; 351*cc6c1592SAlex Zinenko return diag; 352*cc6c1592SAlex Zinenko } 353*cc6c1592SAlex Zinenko 354*cc6c1592SAlex Zinenko MLIRContext *ctx = getContext(); 355*cc6c1592SAlex Zinenko RewritePatternSet patterns(ctx); 356*cc6c1592SAlex Zinenko patterns.add<LinalgVectorizationPattern>(ctx); 357*cc6c1592SAlex Zinenko 358*cc6c1592SAlex Zinenko vector::populateVectorTransferPermutationMapLoweringPatterns(patterns); 359*cc6c1592SAlex Zinenko vector::populateVectorReductionToContractPatterns(patterns); 360*cc6c1592SAlex Zinenko patterns.add<linalg::LinalgCopyVTRForwardingPattern, 361*cc6c1592SAlex Zinenko linalg::LinalgCopyVTWForwardingPattern>(ctx, 362*cc6c1592SAlex Zinenko /*benefit=*/2); 363*cc6c1592SAlex Zinenko vector::TransferReadOp::getCanonicalizationPatterns(patterns, ctx); 364*cc6c1592SAlex Zinenko vector::TransferWriteOp::getCanonicalizationPatterns(patterns, ctx); 365*cc6c1592SAlex Zinenko if (getVectorizePadding()) 366*cc6c1592SAlex Zinenko linalg::populatePadOpVectorizationPatterns(patterns); 367*cc6c1592SAlex Zinenko 368*cc6c1592SAlex Zinenko if (failed(applyPatternsAndFoldGreedily(target, std::move(patterns)))) { 369*cc6c1592SAlex Zinenko InFlightDiagnostic diag = emitError() << "failed to apply"; 370*cc6c1592SAlex Zinenko diag.attachNote(target->getLoc()) << "target op"; 371*cc6c1592SAlex Zinenko return diag; 372*cc6c1592SAlex Zinenko } 373*cc6c1592SAlex Zinenko return target; 374*cc6c1592SAlex Zinenko } 375*cc6c1592SAlex Zinenko 376*cc6c1592SAlex Zinenko //===----------------------------------------------------------------------===// 3773c2a74a3SMatthias Springer // Transform op registration 3783c2a74a3SMatthias Springer //===----------------------------------------------------------------------===// 3793c2a74a3SMatthias Springer 3803c2a74a3SMatthias Springer namespace { 3813c2a74a3SMatthias Springer /// Registers new ops and declares PDL as dependent dialect since the additional 3823c2a74a3SMatthias Springer /// ops are using PDL types for operands and results. 3833c2a74a3SMatthias Springer class LinalgTransformDialectExtension 3843c2a74a3SMatthias Springer : public transform::TransformDialectExtension< 3853c2a74a3SMatthias Springer LinalgTransformDialectExtension> { 3863c2a74a3SMatthias Springer public: 3873c2a74a3SMatthias Springer LinalgTransformDialectExtension() { 3883c2a74a3SMatthias Springer declareDependentDialect<pdl::PDLDialect>(); 3893c2a74a3SMatthias Springer declareDependentDialect<scf::SCFDialect>(); 390*cc6c1592SAlex Zinenko declareDependentDialect<vector::VectorDialect>(); 3913c2a74a3SMatthias Springer registerTransformOps< 3923c2a74a3SMatthias Springer #define GET_OP_LIST 3933c2a74a3SMatthias Springer #include "mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp.inc" 3943c2a74a3SMatthias Springer >(); 3953c2a74a3SMatthias Springer } 3963c2a74a3SMatthias Springer }; 3973c2a74a3SMatthias Springer } // namespace 3983c2a74a3SMatthias Springer 3993c2a74a3SMatthias Springer #define GET_OP_CLASSES 4003c2a74a3SMatthias Springer #include "mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp.inc" 4013c2a74a3SMatthias Springer 4023c2a74a3SMatthias Springer void mlir::linalg::registerTransformDialectExtension( 4033c2a74a3SMatthias Springer DialectRegistry ®istry) { 4043c2a74a3SMatthias Springer registry.addExtensions<LinalgTransformDialectExtension>(); 4053c2a74a3SMatthias Springer } 406