1 //===- LinalgStrategyPasses.cpp - Implementation of Linalg passes ---------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements a configurable pass that can apply patterns liberally
10 // and be plugged in a pass pipeline.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include <utility>
15 
16 #include "PassDetail.h"
17 #include "mlir/Analysis/SliceAnalysis.h"
18 #include "mlir/Dialect/Affine/IR/AffineOps.h"
19 #include "mlir/Dialect/Affine/LoopUtils.h"
20 #include "mlir/Dialect/Affine/Utils.h"
21 #include "mlir/Dialect/Linalg/IR/Linalg.h"
22 #include "mlir/Dialect/Linalg/Passes.h"
23 #include "mlir/Dialect/Linalg/Transforms/Hoisting.h"
24 #include "mlir/Dialect/Linalg/Transforms/Transforms.h"
25 #include "mlir/Dialect/Linalg/Utils/Utils.h"
26 #include "mlir/Dialect/SCF/Transforms/Transforms.h"
27 #include "mlir/Dialect/Tensor/IR/Tensor.h"
28 #include "mlir/Dialect/Vector/Transforms/VectorTransforms.h"
29 #include "mlir/IR/AffineExpr.h"
30 #include "mlir/IR/AffineMap.h"
31 #include "mlir/Pass/PassManager.h"
32 #include "mlir/Support/LLVM.h"
33 #include "mlir/Transforms/GreedyPatternRewriteDriver.h"
34 #include "mlir/Transforms/LoopInvariantCodeMotionUtils.h"
35 #include "mlir/Transforms/Passes.h"
36 
37 using namespace mlir;
38 using namespace mlir::vector;
39 using namespace linalg;
40 
41 namespace {
42 
43 /// Configurable pass to apply pattern-based tiling and fusion.
44 struct LinalgStrategyTileAndFusePass
45     : public LinalgStrategyTileAndFusePassBase<LinalgStrategyTileAndFusePass> {
46 
47   LinalgStrategyTileAndFusePass() = default;
48 
LinalgStrategyTileAndFusePass__anona665729b0111::LinalgStrategyTileAndFusePass49   LinalgStrategyTileAndFusePass(StringRef opName,
50                                 LinalgTilingAndFusionOptions opt,
51                                 LinalgTransformationFilter filt)
52       : options(std::move(opt)), filter(std::move(filt)) {
53     this->anchorOpName.setValue(opName.str());
54   }
55 
runOnOperation__anona665729b0111::LinalgStrategyTileAndFusePass56   void runOnOperation() override {
57     auto funcOp = getOperation();
58     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
59       return;
60 
61     RewritePatternSet tilingAndFusionPattern(funcOp.getContext());
62     if (!anchorOpName.empty()) {
63       tilingAndFusionPattern.add<LinalgTileAndFuseTensorOpsPattern>(
64           anchorOpName, funcOp.getContext(), options, filter);
65     } else {
66       tilingAndFusionPattern.add<LinalgTileAndFuseTensorOpsPattern>(
67           funcOp.getContext(), options, filter);
68     }
69     // Search the root operation using bottom up traversal.
70     GreedyRewriteConfig config;
71     config.useTopDownTraversal = false;
72     (void)applyPatternsAndFoldGreedily(
73         funcOp, std::move(tilingAndFusionPattern), config);
74   }
75 
76   LinalgTilingAndFusionOptions options;
77   LinalgTransformationFilter filter;
78 };
79 
80 /// Configurable pass to apply pattern-based linalg tiling.
81 struct LinalgStrategyTilePass
82     : public LinalgStrategyTilePassBase<LinalgStrategyTilePass> {
83 
84   LinalgStrategyTilePass() = default;
85 
LinalgStrategyTilePass__anona665729b0111::LinalgStrategyTilePass86   LinalgStrategyTilePass(StringRef opName, LinalgTilingOptions opt,
87                          LinalgTransformationFilter filt)
88       : options(std::move(opt)), filter(std::move(filt)) {
89     this->anchorOpName.setValue(opName.str());
90   }
91 
runOnOperation__anona665729b0111::LinalgStrategyTilePass92   void runOnOperation() override {
93     auto funcOp = getOperation();
94     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
95       return;
96 
97     MLIRContext *ctx = funcOp.getContext();
98     RewritePatternSet tilingPattern(ctx);
99     if (!anchorOpName.empty())
100       tilingPattern.add<LinalgTilingPattern>(anchorOpName, ctx, options,
101                                              filter);
102     else
103       tilingPattern.add<LinalgTilingPattern>(ctx, options, filter);
104     if (anchorOpName == tensor::PadOp::getOperationName())
105       populatePadTensorTilingPatterns(tilingPattern, options);
106     (void)applyPatternsAndFoldGreedily(funcOp, std::move(tilingPattern));
107   }
108 
109   LinalgTilingOptions options;
110   LinalgTransformationFilter filter;
111 };
112 
113 /// Configurable pass to apply hoisting and padding.
114 struct LinalgStrategyPadPass
115     : public LinalgStrategyPadPassBase<LinalgStrategyPadPass> {
116 
117   LinalgStrategyPadPass() = default;
118 
LinalgStrategyPadPass__anona665729b0111::LinalgStrategyPadPass119   LinalgStrategyPadPass(StringRef opName, LinalgPaddingOptions opt,
120                         LinalgTransformationFilter filt)
121       : options(std::move(opt)), filter(std::move(filt)) {
122     this->anchorOpName.setValue(opName.str());
123   }
124 
runOnOperation__anona665729b0111::LinalgStrategyPadPass125   void runOnOperation() override {
126     auto funcOp = getOperation();
127     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
128       return;
129 
130     RewritePatternSet paddingPattern(funcOp.getContext());
131     if (!anchorOpName.empty()) {
132       paddingPattern.add<LinalgPaddingPattern>(
133           anchorOpName, funcOp.getContext(), options, filter);
134     } else {
135       paddingPattern.add<LinalgPaddingPattern>(funcOp.getContext(), options,
136                                                filter);
137     }
138     (void)applyPatternsAndFoldGreedily(funcOp, std::move(paddingPattern));
139   }
140 
141   LinalgPaddingOptions options;
142   LinalgTransformationFilter filter;
143 };
144 
145 /// Configurable pass to apply pattern-based linalg generalization.
146 struct LinalgStrategyGeneralizePass
147     : public LinalgStrategyGeneralizePassBase<LinalgStrategyGeneralizePass> {
148 
149   LinalgStrategyGeneralizePass() = default;
150 
LinalgStrategyGeneralizePass__anona665729b0111::LinalgStrategyGeneralizePass151   LinalgStrategyGeneralizePass(StringRef opName,
152                                LinalgTransformationFilter filter)
153       : filter(std::move(filter)) {
154     this->anchorOpName.setValue(opName.str());
155   }
156 
runOnOperation__anona665729b0111::LinalgStrategyGeneralizePass157   void runOnOperation() override {
158     auto funcOp = getOperation();
159     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
160       return;
161 
162     RewritePatternSet generalizationPattern(funcOp.getContext());
163     if (!anchorOpName.empty()) {
164       generalizationPattern.add<LinalgGeneralizationPattern>(
165           anchorOpName, funcOp.getContext(), filter);
166     } else {
167       generalizationPattern.add<LinalgGeneralizationPattern>(
168           funcOp.getContext(), filter);
169     }
170     if (failed(applyPatternsAndFoldGreedily(funcOp,
171                                             std::move(generalizationPattern))))
172       signalPassFailure();
173   }
174 
175   LinalgTransformationFilter filter;
176 };
177 
178 /// Configurable pass to apply lowering of coarser-grained named linalg ops into
179 /// finer-grained named versions.
180 struct LinalgStrategyDecomposePass
181     : public LinalgStrategyDecomposePassBase<LinalgStrategyDecomposePass> {
182 
183   LinalgStrategyDecomposePass() = default;
184 
LinalgStrategyDecomposePass__anona665729b0111::LinalgStrategyDecomposePass185   LinalgStrategyDecomposePass(LinalgTransformationFilter filter)
186       : filter(std::move(filter)) {}
187 
runOnOperation__anona665729b0111::LinalgStrategyDecomposePass188   void runOnOperation() override {
189     auto funcOp = getOperation();
190     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
191       return;
192     RewritePatternSet decompositionPattern(funcOp.getContext());
193     populateDecomposeConvolutionPatterns(decompositionPattern, filter);
194     if (failed(applyPatternsAndFoldGreedily(funcOp,
195                                             std::move(decompositionPattern))))
196       signalPassFailure();
197   }
198 
199   LinalgTransformationFilter filter;
200 };
201 
202 /// Configurable pass to apply pattern-based linalg generalization.
203 struct LinalgStrategyInterchangePass
204     : public LinalgStrategyInterchangePassBase<LinalgStrategyInterchangePass> {
205 
206   LinalgStrategyInterchangePass() = default;
207 
LinalgStrategyInterchangePass__anona665729b0111::LinalgStrategyInterchangePass208   LinalgStrategyInterchangePass(ArrayRef<int64_t> iteratorInterchange,
209                                 LinalgTransformationFilter filter)
210       : iteratorInterchange(iteratorInterchange.begin(),
211                             iteratorInterchange.end()),
212         filter(std::move(filter)) {}
213 
runOnOperation__anona665729b0111::LinalgStrategyInterchangePass214   void runOnOperation() override {
215     auto funcOp = getOperation();
216     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
217       return;
218 
219     SmallVector<unsigned> interchangeVector(iteratorInterchange.begin(),
220                                             iteratorInterchange.end());
221     RewritePatternSet interchangePattern(funcOp.getContext());
222     interchangePattern.add<GenericOpInterchangePattern>(
223         funcOp.getContext(), interchangeVector, filter);
224     if (failed(applyPatternsAndFoldGreedily(funcOp,
225                                             std::move(interchangePattern))))
226       signalPassFailure();
227   }
228 
229   SmallVector<int64_t> iteratorInterchange;
230   LinalgTransformationFilter filter;
231 };
232 
233 /// Configurable pass to apply pattern-based linalg peeling.
234 struct LinalgStrategyPeelPass
235     : public LinalgStrategyPeelPassBase<LinalgStrategyPeelPass> {
236 
237   LinalgStrategyPeelPass() = default;
238 
LinalgStrategyPeelPass__anona665729b0111::LinalgStrategyPeelPass239   LinalgStrategyPeelPass(StringRef opName, LinalgPeelOptions opt,
240                          LinalgTransformationFilter filt)
241       : options(std::move(opt)), filter(std::move(filt)) {
242     this->anchorOpName.setValue(opName.str());
243   }
244 
runOnOperation__anona665729b0111::LinalgStrategyPeelPass245   void runOnOperation() override {
246     auto funcOp = getOperation();
247     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
248       return;
249 
250     RewritePatternSet peelingPatterns(funcOp.getContext());
251     if (!anchorOpName.empty()) {
252       peelingPatterns.add<LinalgPeelingPattern>(
253           anchorOpName, funcOp.getContext(), options, filter);
254     } else {
255       peelingPatterns.add<LinalgPeelingPattern>(funcOp.getContext(), filter,
256                                                 options);
257     }
258     if (failed(
259             applyPatternsAndFoldGreedily(funcOp, std::move(peelingPatterns))))
260       return signalPassFailure();
261   }
262 
263   LinalgPeelOptions options;
264   LinalgTransformationFilter filter;
265 };
266 
267 /// Configurable pass to apply pattern-based linalg vectorization.
268 struct LinalgStrategyVectorizePass
269     : public LinalgStrategyVectorizePassBase<LinalgStrategyVectorizePass> {
270 
271   LinalgStrategyVectorizePass() = default;
272 
LinalgStrategyVectorizePass__anona665729b0111::LinalgStrategyVectorizePass273   LinalgStrategyVectorizePass(StringRef opName, LinalgVectorizationOptions opt,
274                               LinalgTransformationFilter filt,
275                               bool padVectorize = false)
276       : options(opt), filter(std::move(filt)) {
277     this->anchorOpName.setValue(opName.str());
278     this->vectorizePadding.setValue(padVectorize);
279   }
280 
runOnOperation__anona665729b0111::LinalgStrategyVectorizePass281   void runOnOperation() override {
282     auto funcOp = getOperation();
283     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
284       return;
285 
286     RewritePatternSet vectorizationPatterns(funcOp.getContext());
287     if (!anchorOpName.empty()) {
288       vectorizationPatterns.add<LinalgVectorizationPattern>(
289           anchorOpName, funcOp.getContext(), options, filter);
290     } else {
291       vectorizationPatterns.add<LinalgVectorizationPattern>(funcOp.getContext(),
292                                                             filter, options);
293     }
294     vector::populateVectorTransferPermutationMapLoweringPatterns(
295         vectorizationPatterns);
296     vector::populateVectorReductionToContractPatterns(vectorizationPatterns);
297     vectorizationPatterns.add<linalg::LinalgCopyVTRForwardingPattern,
298                               linalg::LinalgCopyVTWForwardingPattern>(
299         funcOp.getContext(), /*benefit=*/2);
300     TransferReadOp::getCanonicalizationPatterns(vectorizationPatterns,
301                                                 funcOp.getContext());
302     TransferWriteOp::getCanonicalizationPatterns(vectorizationPatterns,
303                                                  funcOp.getContext());
304     (void)applyPatternsAndFoldGreedily(funcOp,
305                                        std::move(vectorizationPatterns));
306 
307     // Apply the pad tensor op vectorization separately to avoid running the
308     // GenericPadOpVectorizationPattern too early.
309     // TODO: Improve once we have better infrastructure to control pattern
310     // application.
311     if (vectorizePadding) {
312       RewritePatternSet patterns(funcOp.getContext());
313       linalg::populatePadOpVectorizationPatterns(patterns);
314       (void)applyPatternsAndFoldGreedily(funcOp, std::move(patterns));
315     }
316   }
317 
318   LinalgVectorizationOptions options;
319   LinalgTransformationFilter filter;
320 };
321 
322 /// Configurable pass to enable the application of other pattern-based linalg
323 /// passes.
324 struct LinalgStrategyEnablePass
325     : public LinalgStrategyEnablePassBase<LinalgStrategyEnablePass> {
326 
LinalgStrategyEnablePass__anona665729b0111::LinalgStrategyEnablePass327   LinalgStrategyEnablePass(LinalgEnablingOptions opt,
328                            LinalgTransformationFilter filt)
329       : options(opt), filter(std::move(filt)) {}
330 
runOnOperation__anona665729b0111::LinalgStrategyEnablePass331   void runOnOperation() override {
332     auto funcOp = getOperation();
333     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
334       return;
335 
336     MLIRContext *context = funcOp.getContext();
337     RewritePatternSet patterns =
338         linalg::getLinalgTilingCanonicalizationPatterns(context);
339     scf::populateSCFForLoopCanonicalizationPatterns(patterns);
340     if (failed(applyPatternsAndFoldGreedily(funcOp, std::move(patterns))))
341       return signalPassFailure();
342 
343     if (options.licm) {
344       funcOp->walk([&](LoopLikeOpInterface loopLike) {
345         moveLoopInvariantCode(loopLike);
346       });
347     }
348 
349     // Gathers all innermost loops through a post order pruned walk.
350     funcOp.walk([](Operation *op) {
351       if (auto forOp = dyn_cast<AffineForOp>(op))
352         (void)promoteIfSingleIteration(forOp);
353       else if (auto forOp = dyn_cast<scf::ForOp>(op))
354         (void)promoteIfSingleIteration(forOp);
355     });
356     if (options.hoistRedundantVectorTransfers)
357       hoistRedundantVectorTransfers(funcOp);
358 
359     if (options.hoistRedundantVectorTransfersOnTensor)
360       hoistRedundantVectorTransfersOnTensor(funcOp);
361 
362     // Run CSE to cleanup after canonicalization.
363     OpPassManager dynamicPM("func.func");
364     dynamicPM.addPass(createCSEPass());
365     if (failed(runPipeline(dynamicPM, funcOp)))
366       return signalPassFailure();
367   }
368 
369   LinalgEnablingOptions options;
370   LinalgTransformationFilter filter;
371 };
372 
373 /// Configurable pass to lower vector operations.
374 struct LinalgStrategyLowerVectorsPass
375     : public LinalgStrategyLowerVectorsPassBase<
376           LinalgStrategyLowerVectorsPass> {
377 
LinalgStrategyLowerVectorsPass__anona665729b0111::LinalgStrategyLowerVectorsPass378   LinalgStrategyLowerVectorsPass(LinalgVectorLoweringOptions opt,
379                                  LinalgTransformationFilter filt)
380       : options(opt), filter(std::move(filt)) {}
381 
runOnOperation__anona665729b0111::LinalgStrategyLowerVectorsPass382   void runOnOperation() override {
383     auto funcOp = getOperation();
384     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
385       return;
386 
387     MLIRContext *context = funcOp.getContext();
388     RewritePatternSet patterns(context);
389     vector::populateVectorToVectorCanonicalizationPatterns(patterns);
390     // In a progressive lowering of vectors, this would be the 1st step.
391     if (options.contractionLowering) {
392       patterns.add<ContractionOpToOuterProductOpLowering,
393                    ContractionOpToMatmulOpLowering, ContractionOpLowering>(
394           options.vectorTransformOptions, context);
395       vector::populateVectorTransferPermutationMapLoweringPatterns(patterns);
396     }
397     // In a progressive lowering of vectors, this would be the 2nd step.
398     if (options.multiReductionLowering) {
399       vector::populateVectorMultiReductionLoweringPatterns(
400           patterns,
401           options.vectorTransformOptions.vectorMultiReductionLowering);
402     }
403     // In a progressive lowering of vectors, this would be the 3rd step.
404     if (options.transferPartialRewrite) {
405       patterns.add<vector::VectorTransferFullPartialRewriter>(
406           context, options.vectorTransformOptions);
407     }
408     // In a progressive lowering of vectors, this would be the 4th step.
409     if (options.transferLowering) {
410       vector::populateVectorTransferLoweringPatterns(patterns,
411                                                      options.maxTransferRank);
412     }
413     // In a progressive lowering of vectors, this would be the 5th step.
414     if (options.transferToSCFConversion) {
415       populateVectorToSCFConversionPatterns(
416           patterns, options.vectorTransferToSCFOptions.setTargetRank(
417                         options.maxTransferRank));
418     }
419     // In a progressive lowering of vectors, this would be the 6th step.
420     if (options.shapeCastLowering) {
421       vector::populateVectorShapeCastLoweringPatterns(patterns);
422     }
423     // In a progressive lowering of vectors, this would be the 7th step.
424     if (options.transposeLowering) {
425       vector::populateVectorTransposeLoweringPatterns(
426           patterns, options.vectorTransformOptions);
427       if (options.avx2Lowering)
428         x86vector::avx2::populateSpecializedTransposeLoweringPatterns(
429             patterns, options.avx2LoweringOptions, /*benefit=*/10);
430     }
431     (void)applyPatternsAndFoldGreedily(funcOp, std::move(patterns));
432   }
433 
434   LinalgVectorLoweringOptions options;
435   LinalgTransformationFilter filter;
436 };
437 
438 /// Configurable pass to lower vector operations.
439 struct LinalgStrategyRemoveMarkersPass
440     : public LinalgStrategyRemoveMarkersPassBase<
441           LinalgStrategyRemoveMarkersPass> {
442 
runOnOperation__anona665729b0111::LinalgStrategyRemoveMarkersPass443   void runOnOperation() override {
444     auto funcOp = getOperation();
445     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
446       return;
447     funcOp.walk([](LinalgOp op) {
448       op->removeAttr(LinalgTransforms::kLinalgTransformMarker);
449     });
450   }
451 };
452 } // namespace
453 
454 /// Create a LinalgStrategyTileAndFusePass.
455 std::unique_ptr<OperationPass<func::FuncOp>>
createLinalgStrategyTileAndFusePass(StringRef opName,const LinalgTilingAndFusionOptions & options,const LinalgTransformationFilter & filter)456 mlir::createLinalgStrategyTileAndFusePass(
457     StringRef opName, const LinalgTilingAndFusionOptions &options,
458     const LinalgTransformationFilter &filter) {
459   return std::make_unique<LinalgStrategyTileAndFusePass>(opName, options,
460                                                          filter);
461 }
462 
463 /// Create a LinalgStrategyTilePass.
464 std::unique_ptr<OperationPass<func::FuncOp>>
createLinalgStrategyTilePass(StringRef opName,const LinalgTilingOptions & opt,const LinalgTransformationFilter & filter)465 mlir::createLinalgStrategyTilePass(StringRef opName,
466                                    const LinalgTilingOptions &opt,
467                                    const LinalgTransformationFilter &filter) {
468   return std::make_unique<LinalgStrategyTilePass>(opName, opt, filter);
469 }
470 
471 /// Create a LinalgStrategyPadPass.
472 std::unique_ptr<OperationPass<func::FuncOp>>
createLinalgStrategyPadPass(StringRef opName,const LinalgPaddingOptions & opt,const LinalgTransformationFilter & filter)473 mlir::createLinalgStrategyPadPass(StringRef opName,
474                                   const LinalgPaddingOptions &opt,
475                                   const LinalgTransformationFilter &filter) {
476   return std::make_unique<LinalgStrategyPadPass>(opName, opt, filter);
477 }
478 
479 /// Create a LinalgStrategyGeneralizePass.
480 std::unique_ptr<OperationPass<func::FuncOp>>
createLinalgStrategyGeneralizePass(StringRef opName,const LinalgTransformationFilter & filter)481 mlir::createLinalgStrategyGeneralizePass(
482     StringRef opName, const LinalgTransformationFilter &filter) {
483   return std::make_unique<LinalgStrategyGeneralizePass>(opName, filter);
484 }
485 
486 /// Create a LinalgStrategyDecomposePass.
487 // TODO: if/when we need finer control add an `opName` parameter.
488 std::unique_ptr<OperationPass<func::FuncOp>>
createLinalgStrategyDecomposePass(const LinalgTransformationFilter & filter)489 mlir::createLinalgStrategyDecomposePass(
490     const LinalgTransformationFilter &filter) {
491   return std::make_unique<LinalgStrategyDecomposePass>(filter);
492 }
493 
494 /// Create a LinalgStrategyInterchangePass.
495 std::unique_ptr<OperationPass<func::FuncOp>>
createLinalgStrategyInterchangePass(ArrayRef<int64_t> iteratorInterchange,const LinalgTransformationFilter & filter)496 mlir::createLinalgStrategyInterchangePass(
497     ArrayRef<int64_t> iteratorInterchange,
498     const LinalgTransformationFilter &filter) {
499   return std::make_unique<LinalgStrategyInterchangePass>(iteratorInterchange,
500                                                          filter);
501 }
502 
503 /// Create a LinalgStrategyPeelPass.
504 std::unique_ptr<OperationPass<func::FuncOp>>
createLinalgStrategyPeelPass(StringRef opName,const LinalgPeelOptions & opt,const LinalgTransformationFilter & filter)505 mlir::createLinalgStrategyPeelPass(StringRef opName,
506                                    const LinalgPeelOptions &opt,
507                                    const LinalgTransformationFilter &filter) {
508   return std::make_unique<LinalgStrategyPeelPass>(opName, opt, filter);
509 }
510 
511 /// Create a LinalgStrategyVectorizePass.
512 std::unique_ptr<OperationPass<func::FuncOp>>
createLinalgStrategyVectorizePass(StringRef opName,LinalgVectorizationOptions opt,const LinalgTransformationFilter & filter,bool padVectorize)513 mlir::createLinalgStrategyVectorizePass(
514     StringRef opName, LinalgVectorizationOptions opt,
515     const LinalgTransformationFilter &filter, bool padVectorize) {
516   return std::make_unique<LinalgStrategyVectorizePass>(opName, opt, filter,
517                                                        padVectorize);
518 }
519 
520 /// Create a LinalgStrategyEnablePass.
521 std::unique_ptr<OperationPass<func::FuncOp>>
createLinalgStrategyEnablePass(LinalgEnablingOptions opt,const LinalgTransformationFilter & filter)522 mlir::createLinalgStrategyEnablePass(LinalgEnablingOptions opt,
523                                      const LinalgTransformationFilter &filter) {
524   return std::make_unique<LinalgStrategyEnablePass>(opt, filter);
525 }
526 
527 /// Create a LinalgStrategyLowerVectorsPass.
528 std::unique_ptr<OperationPass<func::FuncOp>>
createLinalgStrategyLowerVectorsPass(LinalgVectorLoweringOptions opt,const LinalgTransformationFilter & filter)529 mlir::createLinalgStrategyLowerVectorsPass(
530     LinalgVectorLoweringOptions opt, const LinalgTransformationFilter &filter) {
531   return std::make_unique<LinalgStrategyLowerVectorsPass>(opt, filter);
532 }
533 
534 /// Create a LinalgStrategyRemoveMarkersPass.
535 std::unique_ptr<OperationPass<func::FuncOp>>
createLinalgStrategyRemoveMarkersPass()536 mlir::createLinalgStrategyRemoveMarkersPass() {
537   return std::make_unique<LinalgStrategyRemoveMarkersPass>();
538 }
539