1fec6c5acSUday Bondhugula //===- TestPatterns.cpp - Test dialect pattern driver ---------------------===//
2fec6c5acSUday Bondhugula //
3fec6c5acSUday Bondhugula // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fec6c5acSUday Bondhugula // See https://llvm.org/LICENSE.txt for license information.
5fec6c5acSUday Bondhugula // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fec6c5acSUday Bondhugula //
7fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
8fec6c5acSUday Bondhugula 
9fec6c5acSUday Bondhugula #include "TestDialect.h"
1026f93d9fSAlex Zinenko #include "mlir/Dialect/StandardOps/IR/Ops.h"
11473bdaf2SAlex Zinenko #include "mlir/Dialect/StandardOps/Transforms/FuncConversions.h"
122bf423b0SRob Suderman #include "mlir/IR/Matchers.h"
13fec6c5acSUday Bondhugula #include "mlir/Pass/Pass.h"
14fec6c5acSUday Bondhugula #include "mlir/Transforms/DialectConversion.h"
1526f93d9fSAlex Zinenko #include "mlir/Transforms/FoldUtils.h"
16b6eb26fdSRiver Riddle #include "mlir/Transforms/GreedyPatternRewriteDriver.h"
179ba37b3bSJacques Pienaar 
18fec6c5acSUday Bondhugula using namespace mlir;
1972c65b69SAlexander Belyaev using namespace mlir::test;
20fec6c5acSUday Bondhugula 
21fec6c5acSUday Bondhugula // Native function for testing NativeCodeCall
22fec6c5acSUday Bondhugula static Value chooseOperand(Value input1, Value input2, BoolAttr choice) {
23fec6c5acSUday Bondhugula   return choice.getValue() ? input1 : input2;
24fec6c5acSUday Bondhugula }
25fec6c5acSUday Bondhugula 
2629429d1aSJacques Pienaar static void createOpI(PatternRewriter &rewriter, Location loc, Value input) {
2729429d1aSJacques Pienaar   rewriter.create<OpI>(loc, input);
28fec6c5acSUday Bondhugula }
29fec6c5acSUday Bondhugula 
30fec6c5acSUday Bondhugula static void handleNoResultOp(PatternRewriter &rewriter,
31fec6c5acSUday Bondhugula                              OpSymbolBindingNoResult op) {
32fec6c5acSUday Bondhugula   // Turn the no result op to a one-result op.
33fec6c5acSUday Bondhugula   rewriter.create<OpSymbolBindingB>(op.getLoc(), op.operand().getType(),
34fec6c5acSUday Bondhugula                                     op.operand());
35fec6c5acSUday Bondhugula }
36fec6c5acSUday Bondhugula 
3701641197SAlexEichenberger // Test that natives calls are only called once during rewrites.
3801641197SAlexEichenberger // OpM_Test will return Pi, increased by 1 for each subsequent calls.
3901641197SAlexEichenberger // This let us check the number of times OpM_Test was called by inspecting
4001641197SAlexEichenberger // the returned value in the MLIR output.
4101641197SAlexEichenberger static int64_t opMIncreasingValue = 314159265;
4201641197SAlexEichenberger static Attribute OpMTest(PatternRewriter &rewriter, Value val) {
4301641197SAlexEichenberger   int64_t i = opMIncreasingValue++;
4401641197SAlexEichenberger   return rewriter.getIntegerAttr(rewriter.getIntegerType(32), i);
4501641197SAlexEichenberger }
4601641197SAlexEichenberger 
47fec6c5acSUday Bondhugula namespace {
48fec6c5acSUday Bondhugula #include "TestPatterns.inc"
49fec6c5acSUday Bondhugula } // end anonymous namespace
50fec6c5acSUday Bondhugula 
51fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
52fec6c5acSUday Bondhugula // Canonicalizer Driver.
53fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
54fec6c5acSUday Bondhugula 
55fec6c5acSUday Bondhugula namespace {
5626f93d9fSAlex Zinenko struct FoldingPattern : public RewritePattern {
5726f93d9fSAlex Zinenko public:
5826f93d9fSAlex Zinenko   FoldingPattern(MLIRContext *context)
5926f93d9fSAlex Zinenko       : RewritePattern(TestOpInPlaceFoldAnchor::getOperationName(),
6026f93d9fSAlex Zinenko                        /*benefit=*/1, context) {}
6126f93d9fSAlex Zinenko 
6226f93d9fSAlex Zinenko   LogicalResult matchAndRewrite(Operation *op,
6326f93d9fSAlex Zinenko                                 PatternRewriter &rewriter) const override {
6426f93d9fSAlex Zinenko     // Exercice OperationFolder API for a single-result operation that is folded
6526f93d9fSAlex Zinenko     // upon construction. The operation being created through the folder has an
6626f93d9fSAlex Zinenko     // in-place folder, and it should be still present in the output.
6726f93d9fSAlex Zinenko     // Furthermore, the folder should not crash when attempting to recover the
68a23d0559SKazuaki Ishizaki     // (unchanged) operation result.
6926f93d9fSAlex Zinenko     OperationFolder folder(op->getContext());
7026f93d9fSAlex Zinenko     Value result = folder.create<TestOpInPlaceFold>(
7126f93d9fSAlex Zinenko         rewriter, op->getLoc(), rewriter.getIntegerType(32), op->getOperand(0),
7226f93d9fSAlex Zinenko         rewriter.getI32IntegerAttr(0));
7326f93d9fSAlex Zinenko     assert(result);
7426f93d9fSAlex Zinenko     rewriter.replaceOp(op, result);
7526f93d9fSAlex Zinenko     return success();
7626f93d9fSAlex Zinenko   }
7726f93d9fSAlex Zinenko };
7826f93d9fSAlex Zinenko 
7980aca1eaSRiver Riddle struct TestPatternDriver : public PassWrapper<TestPatternDriver, FunctionPass> {
80fec6c5acSUday Bondhugula   void runOnFunction() override {
81fec6c5acSUday Bondhugula     mlir::OwningRewritePatternList patterns;
82422aaf31SNicolas Vasilache     populateWithGenerated(&getContext(), patterns);
83fec6c5acSUday Bondhugula 
84fec6c5acSUday Bondhugula     // Verify named pattern is generated with expected name.
8526f93d9fSAlex Zinenko     patterns.insert<FoldingPattern, TestNamedPatternRule>(&getContext());
86fec6c5acSUday Bondhugula 
873fffffa8SRiver Riddle     applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
88fec6c5acSUday Bondhugula   }
89fec6c5acSUday Bondhugula };
90fec6c5acSUday Bondhugula } // end anonymous namespace
91fec6c5acSUday Bondhugula 
92fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
93fec6c5acSUday Bondhugula // ReturnType Driver.
94fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
95fec6c5acSUday Bondhugula 
96fec6c5acSUday Bondhugula namespace {
97fec6c5acSUday Bondhugula // Generate ops for each instance where the type can be successfully inferred.
98fec6c5acSUday Bondhugula template <typename OpTy>
99fec6c5acSUday Bondhugula static void invokeCreateWithInferredReturnType(Operation *op) {
100fec6c5acSUday Bondhugula   auto *context = op->getContext();
101fec6c5acSUday Bondhugula   auto fop = op->getParentOfType<FuncOp>();
102fec6c5acSUday Bondhugula   auto location = UnknownLoc::get(context);
103fec6c5acSUday Bondhugula   OpBuilder b(op);
104fec6c5acSUday Bondhugula   b.setInsertionPointAfter(op);
105fec6c5acSUday Bondhugula 
106fec6c5acSUday Bondhugula   // Use permutations of 2 args as operands.
107fec6c5acSUday Bondhugula   assert(fop.getNumArguments() >= 2);
108fec6c5acSUday Bondhugula   for (int i = 0, e = fop.getNumArguments(); i < e; ++i) {
109fec6c5acSUday Bondhugula     for (int j = 0; j < e; ++j) {
110fec6c5acSUday Bondhugula       std::array<Value, 2> values = {{fop.getArgument(i), fop.getArgument(j)}};
111fec6c5acSUday Bondhugula       SmallVector<Type, 2> inferredReturnTypes;
1125eae715aSJacques Pienaar       if (succeeded(OpTy::inferReturnTypes(
1135eae715aSJacques Pienaar               context, llvm::None, values, op->getAttrDictionary(),
1145eae715aSJacques Pienaar               op->getRegions(), inferredReturnTypes))) {
115fec6c5acSUday Bondhugula         OperationState state(location, OpTy::getOperationName());
1169db53a18SRiver Riddle         // TODO: Expand to regions.
117bb1d976fSAlex Zinenko         OpTy::build(b, state, values, op->getAttrs());
118fec6c5acSUday Bondhugula         (void)b.createOperation(state);
119fec6c5acSUday Bondhugula       }
120fec6c5acSUday Bondhugula     }
121fec6c5acSUday Bondhugula   }
122fec6c5acSUday Bondhugula }
123fec6c5acSUday Bondhugula 
124fec6c5acSUday Bondhugula static void reifyReturnShape(Operation *op) {
125fec6c5acSUday Bondhugula   OpBuilder b(op);
126fec6c5acSUday Bondhugula 
127fec6c5acSUday Bondhugula   // Use permutations of 2 args as operands.
128fec6c5acSUday Bondhugula   auto shapedOp = cast<OpWithShapedTypeInferTypeInterfaceOp>(op);
129fec6c5acSUday Bondhugula   SmallVector<Value, 2> shapes;
130fec6c5acSUday Bondhugula   if (failed(shapedOp.reifyReturnTypeShapes(b, shapes)))
131fec6c5acSUday Bondhugula     return;
132fec6c5acSUday Bondhugula   for (auto it : llvm::enumerate(shapes))
133fec6c5acSUday Bondhugula     op->emitRemark() << "value " << it.index() << ": "
134fec6c5acSUday Bondhugula                      << it.value().getDefiningOp();
135fec6c5acSUday Bondhugula }
136fec6c5acSUday Bondhugula 
13780aca1eaSRiver Riddle struct TestReturnTypeDriver
13880aca1eaSRiver Riddle     : public PassWrapper<TestReturnTypeDriver, FunctionPass> {
139fec6c5acSUday Bondhugula   void runOnFunction() override {
140fec6c5acSUday Bondhugula     if (getFunction().getName() == "testCreateFunctions") {
141fec6c5acSUday Bondhugula       std::vector<Operation *> ops;
142fec6c5acSUday Bondhugula       // Collect ops to avoid triggering on inserted ops.
143fec6c5acSUday Bondhugula       for (auto &op : getFunction().getBody().front())
144fec6c5acSUday Bondhugula         ops.push_back(&op);
145fec6c5acSUday Bondhugula       // Generate test patterns for each, but skip terminator.
146fec6c5acSUday Bondhugula       for (auto *op : llvm::makeArrayRef(ops).drop_back()) {
147fec6c5acSUday Bondhugula         // Test create method of each of the Op classes below. The resultant
148fec6c5acSUday Bondhugula         // output would be in reverse order underneath `op` from which
149fec6c5acSUday Bondhugula         // the attributes and regions are used.
150fec6c5acSUday Bondhugula         invokeCreateWithInferredReturnType<OpWithInferTypeInterfaceOp>(op);
151fec6c5acSUday Bondhugula         invokeCreateWithInferredReturnType<
152fec6c5acSUday Bondhugula             OpWithShapedTypeInferTypeInterfaceOp>(op);
153fec6c5acSUday Bondhugula       };
154fec6c5acSUday Bondhugula       return;
155fec6c5acSUday Bondhugula     }
156fec6c5acSUday Bondhugula     if (getFunction().getName() == "testReifyFunctions") {
157fec6c5acSUday Bondhugula       std::vector<Operation *> ops;
158fec6c5acSUday Bondhugula       // Collect ops to avoid triggering on inserted ops.
159fec6c5acSUday Bondhugula       for (auto &op : getFunction().getBody().front())
160fec6c5acSUday Bondhugula         if (isa<OpWithShapedTypeInferTypeInterfaceOp>(op))
161fec6c5acSUday Bondhugula           ops.push_back(&op);
162fec6c5acSUday Bondhugula       // Generate test patterns for each, but skip terminator.
163fec6c5acSUday Bondhugula       for (auto *op : ops)
164fec6c5acSUday Bondhugula         reifyReturnShape(op);
165fec6c5acSUday Bondhugula     }
166fec6c5acSUday Bondhugula   }
167fec6c5acSUday Bondhugula };
168fec6c5acSUday Bondhugula } // end anonymous namespace
169fec6c5acSUday Bondhugula 
1709ba37b3bSJacques Pienaar namespace {
1719ba37b3bSJacques Pienaar struct TestDerivedAttributeDriver
1729ba37b3bSJacques Pienaar     : public PassWrapper<TestDerivedAttributeDriver, FunctionPass> {
1739ba37b3bSJacques Pienaar   void runOnFunction() override;
1749ba37b3bSJacques Pienaar };
1759ba37b3bSJacques Pienaar } // end anonymous namespace
1769ba37b3bSJacques Pienaar 
1779ba37b3bSJacques Pienaar void TestDerivedAttributeDriver::runOnFunction() {
1789ba37b3bSJacques Pienaar   getFunction().walk([](DerivedAttributeOpInterface dOp) {
1799ba37b3bSJacques Pienaar     auto dAttr = dOp.materializeDerivedAttributes();
1809ba37b3bSJacques Pienaar     if (!dAttr)
1819ba37b3bSJacques Pienaar       return;
1829ba37b3bSJacques Pienaar     for (auto d : dAttr)
1839ba37b3bSJacques Pienaar       dOp.emitRemark() << d.first << " = " << d.second;
1849ba37b3bSJacques Pienaar   });
1859ba37b3bSJacques Pienaar }
1869ba37b3bSJacques Pienaar 
187fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
188fec6c5acSUday Bondhugula // Legalization Driver.
189fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
190fec6c5acSUday Bondhugula 
191fec6c5acSUday Bondhugula namespace {
192fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
193fec6c5acSUday Bondhugula // Region-Block Rewrite Testing
194fec6c5acSUday Bondhugula 
195fec6c5acSUday Bondhugula /// This pattern is a simple pattern that inlines the first region of a given
196fec6c5acSUday Bondhugula /// operation into the parent region.
197fec6c5acSUday Bondhugula struct TestRegionRewriteBlockMovement : public ConversionPattern {
198fec6c5acSUday Bondhugula   TestRegionRewriteBlockMovement(MLIRContext *ctx)
199fec6c5acSUday Bondhugula       : ConversionPattern("test.region", 1, ctx) {}
200fec6c5acSUday Bondhugula 
201fec6c5acSUday Bondhugula   LogicalResult
202fec6c5acSUday Bondhugula   matchAndRewrite(Operation *op, ArrayRef<Value> operands,
203fec6c5acSUday Bondhugula                   ConversionPatternRewriter &rewriter) const final {
204fec6c5acSUday Bondhugula     // Inline this region into the parent region.
205fec6c5acSUday Bondhugula     auto &parentRegion = *op->getParentRegion();
206b0750e2dSTres Popp     auto &opRegion = op->getRegion(0);
207fec6c5acSUday Bondhugula     if (op->getAttr("legalizer.should_clone"))
208b0750e2dSTres Popp       rewriter.cloneRegionBefore(opRegion, parentRegion, parentRegion.end());
209fec6c5acSUday Bondhugula     else
210b0750e2dSTres Popp       rewriter.inlineRegionBefore(opRegion, parentRegion, parentRegion.end());
211b0750e2dSTres Popp 
212b0750e2dSTres Popp     if (op->getAttr("legalizer.erase_old_blocks")) {
213b0750e2dSTres Popp       while (!opRegion.empty())
214b0750e2dSTres Popp         rewriter.eraseBlock(&opRegion.front());
215b0750e2dSTres Popp     }
216fec6c5acSUday Bondhugula 
217fec6c5acSUday Bondhugula     // Drop this operation.
218fec6c5acSUday Bondhugula     rewriter.eraseOp(op);
219fec6c5acSUday Bondhugula     return success();
220fec6c5acSUday Bondhugula   }
221fec6c5acSUday Bondhugula };
222fec6c5acSUday Bondhugula /// This pattern is a simple pattern that generates a region containing an
223fec6c5acSUday Bondhugula /// illegal operation.
224fec6c5acSUday Bondhugula struct TestRegionRewriteUndo : public RewritePattern {
225fec6c5acSUday Bondhugula   TestRegionRewriteUndo(MLIRContext *ctx)
226fec6c5acSUday Bondhugula       : RewritePattern("test.region_builder", 1, ctx) {}
227fec6c5acSUday Bondhugula 
228fec6c5acSUday Bondhugula   LogicalResult matchAndRewrite(Operation *op,
229fec6c5acSUday Bondhugula                                 PatternRewriter &rewriter) const final {
230fec6c5acSUday Bondhugula     // Create the region operation with an entry block containing arguments.
231fec6c5acSUday Bondhugula     OperationState newRegion(op->getLoc(), "test.region");
232fec6c5acSUday Bondhugula     newRegion.addRegion();
233fec6c5acSUday Bondhugula     auto *regionOp = rewriter.createOperation(newRegion);
234fec6c5acSUday Bondhugula     auto *entryBlock = rewriter.createBlock(&regionOp->getRegion(0));
235fec6c5acSUday Bondhugula     entryBlock->addArgument(rewriter.getIntegerType(64));
236fec6c5acSUday Bondhugula 
237fec6c5acSUday Bondhugula     // Add an explicitly illegal operation to ensure the conversion fails.
238fec6c5acSUday Bondhugula     rewriter.create<ILLegalOpF>(op->getLoc(), rewriter.getIntegerType(32));
239fec6c5acSUday Bondhugula     rewriter.create<TestValidOp>(op->getLoc(), ArrayRef<Value>());
240fec6c5acSUday Bondhugula 
241fec6c5acSUday Bondhugula     // Drop this operation.
242fec6c5acSUday Bondhugula     rewriter.eraseOp(op);
243fec6c5acSUday Bondhugula     return success();
244fec6c5acSUday Bondhugula   }
245fec6c5acSUday Bondhugula };
246f27f1e8cSAlex Zinenko /// A simple pattern that creates a block at the end of the parent region of the
247f27f1e8cSAlex Zinenko /// matched operation.
248f27f1e8cSAlex Zinenko struct TestCreateBlock : public RewritePattern {
249f27f1e8cSAlex Zinenko   TestCreateBlock(MLIRContext *ctx)
250f27f1e8cSAlex Zinenko       : RewritePattern("test.create_block", /*benefit=*/1, ctx) {}
251f27f1e8cSAlex Zinenko 
252f27f1e8cSAlex Zinenko   LogicalResult matchAndRewrite(Operation *op,
253f27f1e8cSAlex Zinenko                                 PatternRewriter &rewriter) const final {
254f27f1e8cSAlex Zinenko     Region &region = *op->getParentRegion();
255f27f1e8cSAlex Zinenko     Type i32Type = rewriter.getIntegerType(32);
256f27f1e8cSAlex Zinenko     rewriter.createBlock(&region, region.end(), {i32Type, i32Type});
257f27f1e8cSAlex Zinenko     rewriter.create<TerminatorOp>(op->getLoc());
258f27f1e8cSAlex Zinenko     rewriter.replaceOp(op, {});
259f27f1e8cSAlex Zinenko     return success();
260f27f1e8cSAlex Zinenko   }
261f27f1e8cSAlex Zinenko };
262f27f1e8cSAlex Zinenko 
263a23d0559SKazuaki Ishizaki /// A simple pattern that creates a block containing an invalid operation in
264f27f1e8cSAlex Zinenko /// order to trigger the block creation undo mechanism.
265f27f1e8cSAlex Zinenko struct TestCreateIllegalBlock : public RewritePattern {
266f27f1e8cSAlex Zinenko   TestCreateIllegalBlock(MLIRContext *ctx)
267f27f1e8cSAlex Zinenko       : RewritePattern("test.create_illegal_block", /*benefit=*/1, ctx) {}
268f27f1e8cSAlex Zinenko 
269f27f1e8cSAlex Zinenko   LogicalResult matchAndRewrite(Operation *op,
270f27f1e8cSAlex Zinenko                                 PatternRewriter &rewriter) const final {
271f27f1e8cSAlex Zinenko     Region &region = *op->getParentRegion();
272f27f1e8cSAlex Zinenko     Type i32Type = rewriter.getIntegerType(32);
273f27f1e8cSAlex Zinenko     rewriter.createBlock(&region, region.end(), {i32Type, i32Type});
274f27f1e8cSAlex Zinenko     // Create an illegal op to ensure the conversion fails.
275f27f1e8cSAlex Zinenko     rewriter.create<ILLegalOpF>(op->getLoc(), i32Type);
276f27f1e8cSAlex Zinenko     rewriter.create<TerminatorOp>(op->getLoc());
277f27f1e8cSAlex Zinenko     rewriter.replaceOp(op, {});
278f27f1e8cSAlex Zinenko     return success();
279f27f1e8cSAlex Zinenko   }
280f27f1e8cSAlex Zinenko };
281fec6c5acSUday Bondhugula 
2820816de16SRiver Riddle /// A simple pattern that tests the undo mechanism when replacing the uses of a
2830816de16SRiver Riddle /// block argument.
2840816de16SRiver Riddle struct TestUndoBlockArgReplace : public ConversionPattern {
2850816de16SRiver Riddle   TestUndoBlockArgReplace(MLIRContext *ctx)
2860816de16SRiver Riddle       : ConversionPattern("test.undo_block_arg_replace", /*benefit=*/1, ctx) {}
2870816de16SRiver Riddle 
2880816de16SRiver Riddle   LogicalResult
2890816de16SRiver Riddle   matchAndRewrite(Operation *op, ArrayRef<Value> operands,
2900816de16SRiver Riddle                   ConversionPatternRewriter &rewriter) const final {
2910816de16SRiver Riddle     auto illegalOp =
2920816de16SRiver Riddle         rewriter.create<ILLegalOpF>(op->getLoc(), rewriter.getF32Type());
293e2b71610SRahul Joshi     rewriter.replaceUsesOfBlockArgument(op->getRegion(0).getArgument(0),
2940816de16SRiver Riddle                                         illegalOp);
2950816de16SRiver Riddle     rewriter.updateRootInPlace(op, [] {});
2960816de16SRiver Riddle     return success();
2970816de16SRiver Riddle   }
2980816de16SRiver Riddle };
2990816de16SRiver Riddle 
300df48026bSAlex Zinenko /// A rewrite pattern that tests the undo mechanism when erasing a block.
301df48026bSAlex Zinenko struct TestUndoBlockErase : public ConversionPattern {
302df48026bSAlex Zinenko   TestUndoBlockErase(MLIRContext *ctx)
303df48026bSAlex Zinenko       : ConversionPattern("test.undo_block_erase", /*benefit=*/1, ctx) {}
304df48026bSAlex Zinenko 
305df48026bSAlex Zinenko   LogicalResult
306df48026bSAlex Zinenko   matchAndRewrite(Operation *op, ArrayRef<Value> operands,
307df48026bSAlex Zinenko                   ConversionPatternRewriter &rewriter) const final {
308df48026bSAlex Zinenko     Block *secondBlock = &*std::next(op->getRegion(0).begin());
309df48026bSAlex Zinenko     rewriter.setInsertionPointToStart(secondBlock);
310df48026bSAlex Zinenko     rewriter.create<ILLegalOpF>(op->getLoc(), rewriter.getF32Type());
311df48026bSAlex Zinenko     rewriter.eraseBlock(secondBlock);
312df48026bSAlex Zinenko     rewriter.updateRootInPlace(op, [] {});
313df48026bSAlex Zinenko     return success();
314df48026bSAlex Zinenko   }
315df48026bSAlex Zinenko };
316df48026bSAlex Zinenko 
317fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
318fec6c5acSUday Bondhugula // Type-Conversion Rewrite Testing
319fec6c5acSUday Bondhugula 
320fec6c5acSUday Bondhugula /// This patterns erases a region operation that has had a type conversion.
321fec6c5acSUday Bondhugula struct TestDropOpSignatureConversion : public ConversionPattern {
322fec6c5acSUday Bondhugula   TestDropOpSignatureConversion(MLIRContext *ctx, TypeConverter &converter)
3238d67d187SRiver Riddle       : ConversionPattern("test.drop_region_op", 1, converter, ctx) {}
324fec6c5acSUday Bondhugula   LogicalResult
325fec6c5acSUday Bondhugula   matchAndRewrite(Operation *op, ArrayRef<Value> operands,
326fec6c5acSUday Bondhugula                   ConversionPatternRewriter &rewriter) const override {
327fec6c5acSUday Bondhugula     Region &region = op->getRegion(0);
328fec6c5acSUday Bondhugula     Block *entry = &region.front();
329fec6c5acSUday Bondhugula 
330fec6c5acSUday Bondhugula     // Convert the original entry arguments.
3318d67d187SRiver Riddle     TypeConverter &converter = *getTypeConverter();
332fec6c5acSUday Bondhugula     TypeConverter::SignatureConversion result(entry->getNumArguments());
3338d67d187SRiver Riddle     if (failed(converter.convertSignatureArgs(entry->getArgumentTypes(),
3348d67d187SRiver Riddle                                               result)) ||
3358d67d187SRiver Riddle         failed(rewriter.convertRegionTypes(&region, converter, &result)))
336fec6c5acSUday Bondhugula       return failure();
337fec6c5acSUday Bondhugula 
338fec6c5acSUday Bondhugula     // Convert the region signature and just drop the operation.
339fec6c5acSUday Bondhugula     rewriter.eraseOp(op);
340fec6c5acSUday Bondhugula     return success();
341fec6c5acSUday Bondhugula   }
342fec6c5acSUday Bondhugula };
343fec6c5acSUday Bondhugula /// This pattern simply updates the operands of the given operation.
344fec6c5acSUday Bondhugula struct TestPassthroughInvalidOp : public ConversionPattern {
345fec6c5acSUday Bondhugula   TestPassthroughInvalidOp(MLIRContext *ctx)
346fec6c5acSUday Bondhugula       : ConversionPattern("test.invalid", 1, ctx) {}
347fec6c5acSUday Bondhugula   LogicalResult
348fec6c5acSUday Bondhugula   matchAndRewrite(Operation *op, ArrayRef<Value> operands,
349fec6c5acSUday Bondhugula                   ConversionPatternRewriter &rewriter) const final {
350fec6c5acSUday Bondhugula     rewriter.replaceOpWithNewOp<TestValidOp>(op, llvm::None, operands,
351fec6c5acSUday Bondhugula                                              llvm::None);
352fec6c5acSUday Bondhugula     return success();
353fec6c5acSUday Bondhugula   }
354fec6c5acSUday Bondhugula };
355fec6c5acSUday Bondhugula /// This pattern handles the case of a split return value.
356fec6c5acSUday Bondhugula struct TestSplitReturnType : public ConversionPattern {
357fec6c5acSUday Bondhugula   TestSplitReturnType(MLIRContext *ctx)
358fec6c5acSUday Bondhugula       : ConversionPattern("test.return", 1, ctx) {}
359fec6c5acSUday Bondhugula   LogicalResult
360fec6c5acSUday Bondhugula   matchAndRewrite(Operation *op, ArrayRef<Value> operands,
361fec6c5acSUday Bondhugula                   ConversionPatternRewriter &rewriter) const final {
362fec6c5acSUday Bondhugula     // Check for a return of F32.
363fec6c5acSUday Bondhugula     if (op->getNumOperands() != 1 || !op->getOperand(0).getType().isF32())
364fec6c5acSUday Bondhugula       return failure();
365fec6c5acSUday Bondhugula 
366fec6c5acSUday Bondhugula     // Check if the first operation is a cast operation, if it is we use the
367fec6c5acSUday Bondhugula     // results directly.
368fec6c5acSUday Bondhugula     auto *defOp = operands[0].getDefiningOp();
369fec6c5acSUday Bondhugula     if (auto packerOp = llvm::dyn_cast_or_null<TestCastOp>(defOp)) {
370fec6c5acSUday Bondhugula       rewriter.replaceOpWithNewOp<TestReturnOp>(op, packerOp.getOperands());
371fec6c5acSUday Bondhugula       return success();
372fec6c5acSUday Bondhugula     }
373fec6c5acSUday Bondhugula 
374fec6c5acSUday Bondhugula     // Otherwise, fail to match.
375fec6c5acSUday Bondhugula     return failure();
376fec6c5acSUday Bondhugula   }
377fec6c5acSUday Bondhugula };
378fec6c5acSUday Bondhugula 
379fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
380fec6c5acSUday Bondhugula // Multi-Level Type-Conversion Rewrite Testing
381fec6c5acSUday Bondhugula struct TestChangeProducerTypeI32ToF32 : public ConversionPattern {
382fec6c5acSUday Bondhugula   TestChangeProducerTypeI32ToF32(MLIRContext *ctx)
383fec6c5acSUday Bondhugula       : ConversionPattern("test.type_producer", 1, ctx) {}
384fec6c5acSUday Bondhugula   LogicalResult
385fec6c5acSUday Bondhugula   matchAndRewrite(Operation *op, ArrayRef<Value> operands,
386fec6c5acSUday Bondhugula                   ConversionPatternRewriter &rewriter) const final {
387fec6c5acSUday Bondhugula     // If the type is I32, change the type to F32.
388fec6c5acSUday Bondhugula     if (!Type(*op->result_type_begin()).isSignlessInteger(32))
389fec6c5acSUday Bondhugula       return failure();
390fec6c5acSUday Bondhugula     rewriter.replaceOpWithNewOp<TestTypeProducerOp>(op, rewriter.getF32Type());
391fec6c5acSUday Bondhugula     return success();
392fec6c5acSUday Bondhugula   }
393fec6c5acSUday Bondhugula };
394fec6c5acSUday Bondhugula struct TestChangeProducerTypeF32ToF64 : public ConversionPattern {
395fec6c5acSUday Bondhugula   TestChangeProducerTypeF32ToF64(MLIRContext *ctx)
396fec6c5acSUday Bondhugula       : ConversionPattern("test.type_producer", 1, ctx) {}
397fec6c5acSUday Bondhugula   LogicalResult
398fec6c5acSUday Bondhugula   matchAndRewrite(Operation *op, ArrayRef<Value> operands,
399fec6c5acSUday Bondhugula                   ConversionPatternRewriter &rewriter) const final {
400fec6c5acSUday Bondhugula     // If the type is F32, change the type to F64.
401fec6c5acSUday Bondhugula     if (!Type(*op->result_type_begin()).isF32())
402fec6c5acSUday Bondhugula       return rewriter.notifyMatchFailure(op, "expected single f32 operand");
403fec6c5acSUday Bondhugula     rewriter.replaceOpWithNewOp<TestTypeProducerOp>(op, rewriter.getF64Type());
404fec6c5acSUday Bondhugula     return success();
405fec6c5acSUday Bondhugula   }
406fec6c5acSUday Bondhugula };
407fec6c5acSUday Bondhugula struct TestChangeProducerTypeF32ToInvalid : public ConversionPattern {
408fec6c5acSUday Bondhugula   TestChangeProducerTypeF32ToInvalid(MLIRContext *ctx)
409fec6c5acSUday Bondhugula       : ConversionPattern("test.type_producer", 10, ctx) {}
410fec6c5acSUday Bondhugula   LogicalResult
411fec6c5acSUday Bondhugula   matchAndRewrite(Operation *op, ArrayRef<Value> operands,
412fec6c5acSUday Bondhugula                   ConversionPatternRewriter &rewriter) const final {
413fec6c5acSUday Bondhugula     // Always convert to B16, even though it is not a legal type. This tests
414fec6c5acSUday Bondhugula     // that values are unmapped correctly.
415fec6c5acSUday Bondhugula     rewriter.replaceOpWithNewOp<TestTypeProducerOp>(op, rewriter.getBF16Type());
416fec6c5acSUday Bondhugula     return success();
417fec6c5acSUday Bondhugula   }
418fec6c5acSUday Bondhugula };
419fec6c5acSUday Bondhugula struct TestUpdateConsumerType : public ConversionPattern {
420fec6c5acSUday Bondhugula   TestUpdateConsumerType(MLIRContext *ctx)
421fec6c5acSUday Bondhugula       : ConversionPattern("test.type_consumer", 1, ctx) {}
422fec6c5acSUday Bondhugula   LogicalResult
423fec6c5acSUday Bondhugula   matchAndRewrite(Operation *op, ArrayRef<Value> operands,
424fec6c5acSUday Bondhugula                   ConversionPatternRewriter &rewriter) const final {
425fec6c5acSUday Bondhugula     // Verify that the incoming operand has been successfully remapped to F64.
426fec6c5acSUday Bondhugula     if (!operands[0].getType().isF64())
427fec6c5acSUday Bondhugula       return failure();
428fec6c5acSUday Bondhugula     rewriter.replaceOpWithNewOp<TestTypeConsumerOp>(op, operands[0]);
429fec6c5acSUday Bondhugula     return success();
430fec6c5acSUday Bondhugula   }
431fec6c5acSUday Bondhugula };
432fec6c5acSUday Bondhugula 
433fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
434fec6c5acSUday Bondhugula // Non-Root Replacement Rewrite Testing
435fec6c5acSUday Bondhugula /// This pattern generates an invalid operation, but replaces it before the
436fec6c5acSUday Bondhugula /// pattern is finished. This checks that we don't need to legalize the
437fec6c5acSUday Bondhugula /// temporary op.
438fec6c5acSUday Bondhugula struct TestNonRootReplacement : public RewritePattern {
439fec6c5acSUday Bondhugula   TestNonRootReplacement(MLIRContext *ctx)
440fec6c5acSUday Bondhugula       : RewritePattern("test.replace_non_root", 1, ctx) {}
441fec6c5acSUday Bondhugula 
442fec6c5acSUday Bondhugula   LogicalResult matchAndRewrite(Operation *op,
443fec6c5acSUday Bondhugula                                 PatternRewriter &rewriter) const final {
444fec6c5acSUday Bondhugula     auto resultType = *op->result_type_begin();
445fec6c5acSUday Bondhugula     auto illegalOp = rewriter.create<ILLegalOpF>(op->getLoc(), resultType);
446fec6c5acSUday Bondhugula     auto legalOp = rewriter.create<LegalOpB>(op->getLoc(), resultType);
447fec6c5acSUday Bondhugula 
448fec6c5acSUday Bondhugula     rewriter.replaceOp(illegalOp, {legalOp});
449fec6c5acSUday Bondhugula     rewriter.replaceOp(op, {illegalOp});
450fec6c5acSUday Bondhugula     return success();
451fec6c5acSUday Bondhugula   }
452fec6c5acSUday Bondhugula };
453bd1ccfe6SRiver Riddle 
454bd1ccfe6SRiver Riddle //===----------------------------------------------------------------------===//
455bd1ccfe6SRiver Riddle // Recursive Rewrite Testing
456bd1ccfe6SRiver Riddle /// This pattern is applied to the same operation multiple times, but has a
457bd1ccfe6SRiver Riddle /// bounded recursion.
458bd1ccfe6SRiver Riddle struct TestBoundedRecursiveRewrite
459bd1ccfe6SRiver Riddle     : public OpRewritePattern<TestRecursiveRewriteOp> {
460b99bd771SRiver Riddle   TestBoundedRecursiveRewrite(MLIRContext *ctx)
461b99bd771SRiver Riddle       : OpRewritePattern<TestRecursiveRewriteOp>(ctx) {
462b99bd771SRiver Riddle     // The conversion target handles bounding the recursion of this pattern.
463b99bd771SRiver Riddle     setHasBoundedRewriteRecursion();
464b99bd771SRiver Riddle   }
465bd1ccfe6SRiver Riddle 
466bd1ccfe6SRiver Riddle   LogicalResult matchAndRewrite(TestRecursiveRewriteOp op,
467bd1ccfe6SRiver Riddle                                 PatternRewriter &rewriter) const final {
468bd1ccfe6SRiver Riddle     // Decrement the depth of the op in-place.
469bd1ccfe6SRiver Riddle     rewriter.updateRootInPlace(op, [&] {
470*1ffc1aaaSChristian Sigg       op->setAttr("depth", rewriter.getI64IntegerAttr(op.depth() - 1));
471bd1ccfe6SRiver Riddle     });
472bd1ccfe6SRiver Riddle     return success();
473bd1ccfe6SRiver Riddle   }
474bd1ccfe6SRiver Riddle };
4755d5df06aSAlex Zinenko 
4765d5df06aSAlex Zinenko struct TestNestedOpCreationUndoRewrite
4775d5df06aSAlex Zinenko     : public OpRewritePattern<IllegalOpWithRegionAnchor> {
4785d5df06aSAlex Zinenko   using OpRewritePattern<IllegalOpWithRegionAnchor>::OpRewritePattern;
4795d5df06aSAlex Zinenko 
4805d5df06aSAlex Zinenko   LogicalResult matchAndRewrite(IllegalOpWithRegionAnchor op,
4815d5df06aSAlex Zinenko                                 PatternRewriter &rewriter) const final {
4825d5df06aSAlex Zinenko     // rewriter.replaceOpWithNewOp<IllegalOpWithRegion>(op);
4835d5df06aSAlex Zinenko     rewriter.replaceOpWithNewOp<IllegalOpWithRegion>(op);
4845d5df06aSAlex Zinenko     return success();
4855d5df06aSAlex Zinenko   };
4865d5df06aSAlex Zinenko };
487fec6c5acSUday Bondhugula } // namespace
488fec6c5acSUday Bondhugula 
489fec6c5acSUday Bondhugula namespace {
490fec6c5acSUday Bondhugula struct TestTypeConverter : public TypeConverter {
491fec6c5acSUday Bondhugula   using TypeConverter::TypeConverter;
4925c5dafc5SAlex Zinenko   TestTypeConverter() {
4935c5dafc5SAlex Zinenko     addConversion(convertType);
4944589dd92SRiver Riddle     addArgumentMaterialization(materializeCast);
4954589dd92SRiver Riddle     addArgumentMaterialization(materializeOneToOneCast);
4964589dd92SRiver Riddle     addSourceMaterialization(materializeCast);
4975c5dafc5SAlex Zinenko   }
498fec6c5acSUday Bondhugula 
499fec6c5acSUday Bondhugula   static LogicalResult convertType(Type t, SmallVectorImpl<Type> &results) {
500fec6c5acSUday Bondhugula     // Drop I16 types.
501fec6c5acSUday Bondhugula     if (t.isSignlessInteger(16))
502fec6c5acSUday Bondhugula       return success();
503fec6c5acSUday Bondhugula 
504fec6c5acSUday Bondhugula     // Convert I64 to F64.
505fec6c5acSUday Bondhugula     if (t.isSignlessInteger(64)) {
506fec6c5acSUday Bondhugula       results.push_back(FloatType::getF64(t.getContext()));
507fec6c5acSUday Bondhugula       return success();
508fec6c5acSUday Bondhugula     }
509fec6c5acSUday Bondhugula 
5105c5dafc5SAlex Zinenko     // Convert I42 to I43.
5115c5dafc5SAlex Zinenko     if (t.isInteger(42)) {
5125c5dafc5SAlex Zinenko       results.push_back(IntegerType::get(43, t.getContext()));
5135c5dafc5SAlex Zinenko       return success();
5145c5dafc5SAlex Zinenko     }
5155c5dafc5SAlex Zinenko 
516fec6c5acSUday Bondhugula     // Split F32 into F16,F16.
517fec6c5acSUday Bondhugula     if (t.isF32()) {
518fec6c5acSUday Bondhugula       results.assign(2, FloatType::getF16(t.getContext()));
519fec6c5acSUday Bondhugula       return success();
520fec6c5acSUday Bondhugula     }
521fec6c5acSUday Bondhugula 
522fec6c5acSUday Bondhugula     // Otherwise, convert the type directly.
523fec6c5acSUday Bondhugula     results.push_back(t);
524fec6c5acSUday Bondhugula     return success();
525fec6c5acSUday Bondhugula   }
526fec6c5acSUday Bondhugula 
5275c5dafc5SAlex Zinenko   /// Hook for materializing a conversion. This is necessary because we generate
5285c5dafc5SAlex Zinenko   /// 1->N type mappings.
5294589dd92SRiver Riddle   static Optional<Value> materializeCast(OpBuilder &builder, Type resultType,
5304589dd92SRiver Riddle                                          ValueRange inputs, Location loc) {
5315c5dafc5SAlex Zinenko     if (inputs.size() == 1)
5325c5dafc5SAlex Zinenko       return inputs[0];
5334589dd92SRiver Riddle     return builder.create<TestCastOp>(loc, resultType, inputs).getResult();
5345c5dafc5SAlex Zinenko   }
5355c5dafc5SAlex Zinenko 
5365c5dafc5SAlex Zinenko   /// Materialize the cast for one-to-one conversion from i64 to f64.
5374589dd92SRiver Riddle   static Optional<Value> materializeOneToOneCast(OpBuilder &builder,
5385c5dafc5SAlex Zinenko                                                  IntegerType resultType,
5395c5dafc5SAlex Zinenko                                                  ValueRange inputs,
5405c5dafc5SAlex Zinenko                                                  Location loc) {
5415c5dafc5SAlex Zinenko     if (resultType.getWidth() == 42 && inputs.size() == 1)
5424589dd92SRiver Riddle       return builder.create<TestCastOp>(loc, resultType, inputs).getResult();
5435c5dafc5SAlex Zinenko     return llvm::None;
544fec6c5acSUday Bondhugula   }
545fec6c5acSUday Bondhugula };
546fec6c5acSUday Bondhugula 
547fec6c5acSUday Bondhugula struct TestLegalizePatternDriver
54880aca1eaSRiver Riddle     : public PassWrapper<TestLegalizePatternDriver, OperationPass<ModuleOp>> {
549fec6c5acSUday Bondhugula   /// The mode of conversion to use with the driver.
550fec6c5acSUday Bondhugula   enum class ConversionMode { Analysis, Full, Partial };
551fec6c5acSUday Bondhugula 
552fec6c5acSUday Bondhugula   TestLegalizePatternDriver(ConversionMode mode) : mode(mode) {}
553fec6c5acSUday Bondhugula 
554722f909fSRiver Riddle   void runOnOperation() override {
555fec6c5acSUday Bondhugula     TestTypeConverter converter;
556fec6c5acSUday Bondhugula     mlir::OwningRewritePatternList patterns;
557422aaf31SNicolas Vasilache     populateWithGenerated(&getContext(), patterns);
558df48026bSAlex Zinenko     patterns.insert<
559df48026bSAlex Zinenko         TestRegionRewriteBlockMovement, TestRegionRewriteUndo, TestCreateBlock,
560df48026bSAlex Zinenko         TestCreateIllegalBlock, TestUndoBlockArgReplace, TestUndoBlockErase,
561df48026bSAlex Zinenko         TestPassthroughInvalidOp, TestSplitReturnType,
562df48026bSAlex Zinenko         TestChangeProducerTypeI32ToF32, TestChangeProducerTypeF32ToF64,
563fec6c5acSUday Bondhugula         TestChangeProducerTypeF32ToInvalid, TestUpdateConsumerType,
5645d5df06aSAlex Zinenko         TestNonRootReplacement, TestBoundedRecursiveRewrite,
5655d5df06aSAlex Zinenko         TestNestedOpCreationUndoRewrite>(&getContext());
566fec6c5acSUday Bondhugula     patterns.insert<TestDropOpSignatureConversion>(&getContext(), converter);
567fec6c5acSUday Bondhugula     mlir::populateFuncOpTypeConversionPattern(patterns, &getContext(),
568fec6c5acSUday Bondhugula                                               converter);
569fec6c5acSUday Bondhugula     mlir::populateCallOpTypeConversionPattern(patterns, &getContext(),
570fec6c5acSUday Bondhugula                                               converter);
571fec6c5acSUday Bondhugula 
572fec6c5acSUday Bondhugula     // Define the conversion target used for the test.
573fec6c5acSUday Bondhugula     ConversionTarget target(getContext());
574fec6c5acSUday Bondhugula     target.addLegalOp<ModuleOp, ModuleTerminatorOp>();
575f27f1e8cSAlex Zinenko     target.addLegalOp<LegalOpA, LegalOpB, TestCastOp, TestValidOp,
576f27f1e8cSAlex Zinenko                       TerminatorOp>();
577fec6c5acSUday Bondhugula     target
578fec6c5acSUday Bondhugula         .addIllegalOp<ILLegalOpF, TestRegionBuilderOp, TestOpWithRegionFold>();
579fec6c5acSUday Bondhugula     target.addDynamicallyLegalOp<TestReturnOp>([](TestReturnOp op) {
580fec6c5acSUday Bondhugula       // Don't allow F32 operands.
581fec6c5acSUday Bondhugula       return llvm::none_of(op.getOperandTypes(),
582fec6c5acSUday Bondhugula                            [](Type type) { return type.isF32(); });
583fec6c5acSUday Bondhugula     });
5848d67d187SRiver Riddle     target.addDynamicallyLegalOp<FuncOp>([&](FuncOp op) {
5858d67d187SRiver Riddle       return converter.isSignatureLegal(op.getType()) &&
5868d67d187SRiver Riddle              converter.isLegal(&op.getBody());
5878d67d187SRiver Riddle     });
588fec6c5acSUday Bondhugula 
589fec6c5acSUday Bondhugula     // Expect the type_producer/type_consumer operations to only operate on f64.
590fec6c5acSUday Bondhugula     target.addDynamicallyLegalOp<TestTypeProducerOp>(
591fec6c5acSUday Bondhugula         [](TestTypeProducerOp op) { return op.getType().isF64(); });
592fec6c5acSUday Bondhugula     target.addDynamicallyLegalOp<TestTypeConsumerOp>([](TestTypeConsumerOp op) {
593fec6c5acSUday Bondhugula       return op.getOperand().getType().isF64();
594fec6c5acSUday Bondhugula     });
595fec6c5acSUday Bondhugula 
596fec6c5acSUday Bondhugula     // Check support for marking certain operations as recursively legal.
597fec6c5acSUday Bondhugula     target.markOpRecursivelyLegal<FuncOp, ModuleOp>([](Operation *op) {
598fec6c5acSUday Bondhugula       return static_cast<bool>(
599fec6c5acSUday Bondhugula           op->getAttrOfType<UnitAttr>("test.recursively_legal"));
600fec6c5acSUday Bondhugula     });
601fec6c5acSUday Bondhugula 
602bd1ccfe6SRiver Riddle     // Mark the bound recursion operation as dynamically legal.
603bd1ccfe6SRiver Riddle     target.addDynamicallyLegalOp<TestRecursiveRewriteOp>(
604bd1ccfe6SRiver Riddle         [](TestRecursiveRewriteOp op) { return op.depth() == 0; });
605bd1ccfe6SRiver Riddle 
606fec6c5acSUday Bondhugula     // Handle a partial conversion.
607fec6c5acSUday Bondhugula     if (mode == ConversionMode::Partial) {
6088de482eaSLucy Fox       DenseSet<Operation *> unlegalizedOps;
6093fffffa8SRiver Riddle       (void)applyPartialConversion(getOperation(), target, std::move(patterns),
6108de482eaSLucy Fox                                    &unlegalizedOps);
6118de482eaSLucy Fox       // Emit remarks for each legalizable operation.
6128de482eaSLucy Fox       for (auto *op : unlegalizedOps)
6138de482eaSLucy Fox         op->emitRemark() << "op '" << op->getName() << "' is not legalizable";
614fec6c5acSUday Bondhugula       return;
615fec6c5acSUday Bondhugula     }
616fec6c5acSUday Bondhugula 
617fec6c5acSUday Bondhugula     // Handle a full conversion.
618fec6c5acSUday Bondhugula     if (mode == ConversionMode::Full) {
619fec6c5acSUday Bondhugula       // Check support for marking unknown operations as dynamically legal.
620fec6c5acSUday Bondhugula       target.markUnknownOpDynamicallyLegal([](Operation *op) {
621fec6c5acSUday Bondhugula         return (bool)op->getAttrOfType<UnitAttr>("test.dynamically_legal");
622fec6c5acSUday Bondhugula       });
623fec6c5acSUday Bondhugula 
6243fffffa8SRiver Riddle       (void)applyFullConversion(getOperation(), target, std::move(patterns));
625fec6c5acSUday Bondhugula       return;
626fec6c5acSUday Bondhugula     }
627fec6c5acSUday Bondhugula 
628fec6c5acSUday Bondhugula     // Otherwise, handle an analysis conversion.
629fec6c5acSUday Bondhugula     assert(mode == ConversionMode::Analysis);
630fec6c5acSUday Bondhugula 
631fec6c5acSUday Bondhugula     // Analyze the convertible operations.
632fec6c5acSUday Bondhugula     DenseSet<Operation *> legalizedOps;
6333fffffa8SRiver Riddle     if (failed(applyAnalysisConversion(getOperation(), target,
6343fffffa8SRiver Riddle                                        std::move(patterns), legalizedOps)))
635fec6c5acSUday Bondhugula       return signalPassFailure();
636fec6c5acSUday Bondhugula 
637fec6c5acSUday Bondhugula     // Emit remarks for each legalizable operation.
638fec6c5acSUday Bondhugula     for (auto *op : legalizedOps)
639fec6c5acSUday Bondhugula       op->emitRemark() << "op '" << op->getName() << "' is legalizable";
640fec6c5acSUday Bondhugula   }
641fec6c5acSUday Bondhugula 
642fec6c5acSUday Bondhugula   /// The mode of conversion to use.
643fec6c5acSUday Bondhugula   ConversionMode mode;
644fec6c5acSUday Bondhugula };
645fec6c5acSUday Bondhugula } // end anonymous namespace
646fec6c5acSUday Bondhugula 
647fec6c5acSUday Bondhugula static llvm::cl::opt<TestLegalizePatternDriver::ConversionMode>
648fec6c5acSUday Bondhugula     legalizerConversionMode(
649fec6c5acSUday Bondhugula         "test-legalize-mode",
650fec6c5acSUday Bondhugula         llvm::cl::desc("The legalization mode to use with the test driver"),
651fec6c5acSUday Bondhugula         llvm::cl::init(TestLegalizePatternDriver::ConversionMode::Partial),
652fec6c5acSUday Bondhugula         llvm::cl::values(
653fec6c5acSUday Bondhugula             clEnumValN(TestLegalizePatternDriver::ConversionMode::Analysis,
654fec6c5acSUday Bondhugula                        "analysis", "Perform an analysis conversion"),
655fec6c5acSUday Bondhugula             clEnumValN(TestLegalizePatternDriver::ConversionMode::Full, "full",
656fec6c5acSUday Bondhugula                        "Perform a full conversion"),
657fec6c5acSUday Bondhugula             clEnumValN(TestLegalizePatternDriver::ConversionMode::Partial,
658fec6c5acSUday Bondhugula                        "partial", "Perform a partial conversion")));
659fec6c5acSUday Bondhugula 
660fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
661fec6c5acSUday Bondhugula // ConversionPatternRewriter::getRemappedValue testing. This method is used
6625aacce3dSKazuaki Ishizaki // to get the remapped value of an original value that was replaced using
663fec6c5acSUday Bondhugula // ConversionPatternRewriter.
664fec6c5acSUday Bondhugula namespace {
665fec6c5acSUday Bondhugula /// Converter that replaces a one-result one-operand OneVResOneVOperandOp1 with
666fec6c5acSUday Bondhugula /// a one-operand two-result OneVResOneVOperandOp1 by replicating its original
667fec6c5acSUday Bondhugula /// operand twice.
668fec6c5acSUday Bondhugula ///
669fec6c5acSUday Bondhugula /// Example:
670fec6c5acSUday Bondhugula ///   %1 = test.one_variadic_out_one_variadic_in1"(%0)
671fec6c5acSUday Bondhugula /// is replaced with:
672fec6c5acSUday Bondhugula ///   %1 = test.one_variadic_out_one_variadic_in1"(%0, %0)
673fec6c5acSUday Bondhugula struct OneVResOneVOperandOp1Converter
674fec6c5acSUday Bondhugula     : public OpConversionPattern<OneVResOneVOperandOp1> {
675fec6c5acSUday Bondhugula   using OpConversionPattern<OneVResOneVOperandOp1>::OpConversionPattern;
676fec6c5acSUday Bondhugula 
677fec6c5acSUday Bondhugula   LogicalResult
678fec6c5acSUday Bondhugula   matchAndRewrite(OneVResOneVOperandOp1 op, ArrayRef<Value> operands,
679fec6c5acSUday Bondhugula                   ConversionPatternRewriter &rewriter) const override {
680fec6c5acSUday Bondhugula     auto origOps = op.getOperands();
681fec6c5acSUday Bondhugula     assert(std::distance(origOps.begin(), origOps.end()) == 1 &&
682fec6c5acSUday Bondhugula            "One operand expected");
683fec6c5acSUday Bondhugula     Value origOp = *origOps.begin();
684fec6c5acSUday Bondhugula     SmallVector<Value, 2> remappedOperands;
685fec6c5acSUday Bondhugula     // Replicate the remapped original operand twice. Note that we don't used
686fec6c5acSUday Bondhugula     // the remapped 'operand' since the goal is testing 'getRemappedValue'.
687fec6c5acSUday Bondhugula     remappedOperands.push_back(rewriter.getRemappedValue(origOp));
688fec6c5acSUday Bondhugula     remappedOperands.push_back(rewriter.getRemappedValue(origOp));
689fec6c5acSUday Bondhugula 
690fec6c5acSUday Bondhugula     rewriter.replaceOpWithNewOp<OneVResOneVOperandOp1>(op, op.getResultTypes(),
691fec6c5acSUday Bondhugula                                                        remappedOperands);
692fec6c5acSUday Bondhugula     return success();
693fec6c5acSUday Bondhugula   }
694fec6c5acSUday Bondhugula };
695fec6c5acSUday Bondhugula 
69680aca1eaSRiver Riddle struct TestRemappedValue
69780aca1eaSRiver Riddle     : public mlir::PassWrapper<TestRemappedValue, FunctionPass> {
698fec6c5acSUday Bondhugula   void runOnFunction() override {
699fec6c5acSUday Bondhugula     mlir::OwningRewritePatternList patterns;
700fec6c5acSUday Bondhugula     patterns.insert<OneVResOneVOperandOp1Converter>(&getContext());
701fec6c5acSUday Bondhugula 
702fec6c5acSUday Bondhugula     mlir::ConversionTarget target(getContext());
703fec6c5acSUday Bondhugula     target.addLegalOp<ModuleOp, ModuleTerminatorOp, FuncOp, TestReturnOp>();
704fec6c5acSUday Bondhugula     // We make OneVResOneVOperandOp1 legal only when it has more that one
705fec6c5acSUday Bondhugula     // operand. This will trigger the conversion that will replace one-operand
706fec6c5acSUday Bondhugula     // OneVResOneVOperandOp1 with two-operand OneVResOneVOperandOp1.
707fec6c5acSUday Bondhugula     target.addDynamicallyLegalOp<OneVResOneVOperandOp1>(
708fec6c5acSUday Bondhugula         [](Operation *op) -> bool {
709fec6c5acSUday Bondhugula           return std::distance(op->operand_begin(), op->operand_end()) > 1;
710fec6c5acSUday Bondhugula         });
711fec6c5acSUday Bondhugula 
7123fffffa8SRiver Riddle     if (failed(mlir::applyFullConversion(getFunction(), target,
7133fffffa8SRiver Riddle                                          std::move(patterns)))) {
714fec6c5acSUday Bondhugula       signalPassFailure();
715fec6c5acSUday Bondhugula     }
716fec6c5acSUday Bondhugula   }
717fec6c5acSUday Bondhugula };
718fec6c5acSUday Bondhugula } // end anonymous namespace
719fec6c5acSUday Bondhugula 
72080d7ac3bSRiver Riddle //===----------------------------------------------------------------------===//
72180d7ac3bSRiver Riddle // Test patterns without a specific root operation kind
72280d7ac3bSRiver Riddle //===----------------------------------------------------------------------===//
72380d7ac3bSRiver Riddle 
72480d7ac3bSRiver Riddle namespace {
72580d7ac3bSRiver Riddle /// This pattern matches and removes any operation in the test dialect.
72680d7ac3bSRiver Riddle struct RemoveTestDialectOps : public RewritePattern {
72780d7ac3bSRiver Riddle   RemoveTestDialectOps() : RewritePattern(/*benefit=*/1, MatchAnyOpTypeTag()) {}
72880d7ac3bSRiver Riddle 
72980d7ac3bSRiver Riddle   LogicalResult matchAndRewrite(Operation *op,
73080d7ac3bSRiver Riddle                                 PatternRewriter &rewriter) const override {
73180d7ac3bSRiver Riddle     if (!isa<TestDialect>(op->getDialect()))
73280d7ac3bSRiver Riddle       return failure();
73380d7ac3bSRiver Riddle     rewriter.eraseOp(op);
73480d7ac3bSRiver Riddle     return success();
73580d7ac3bSRiver Riddle   }
73680d7ac3bSRiver Riddle };
73780d7ac3bSRiver Riddle 
73880d7ac3bSRiver Riddle struct TestUnknownRootOpDriver
73980d7ac3bSRiver Riddle     : public mlir::PassWrapper<TestUnknownRootOpDriver, FunctionPass> {
74080d7ac3bSRiver Riddle   void runOnFunction() override {
74180d7ac3bSRiver Riddle     mlir::OwningRewritePatternList patterns;
74280d7ac3bSRiver Riddle     patterns.insert<RemoveTestDialectOps>();
74380d7ac3bSRiver Riddle 
74480d7ac3bSRiver Riddle     mlir::ConversionTarget target(getContext());
74580d7ac3bSRiver Riddle     target.addIllegalDialect<TestDialect>();
7463fffffa8SRiver Riddle     if (failed(
7473fffffa8SRiver Riddle             applyPartialConversion(getFunction(), target, std::move(patterns))))
74880d7ac3bSRiver Riddle       signalPassFailure();
74980d7ac3bSRiver Riddle   }
75080d7ac3bSRiver Riddle };
75180d7ac3bSRiver Riddle } // end anonymous namespace
75280d7ac3bSRiver Riddle 
7534589dd92SRiver Riddle //===----------------------------------------------------------------------===//
7544589dd92SRiver Riddle // Test type conversions
7554589dd92SRiver Riddle //===----------------------------------------------------------------------===//
7564589dd92SRiver Riddle 
7574589dd92SRiver Riddle namespace {
7584589dd92SRiver Riddle struct TestTypeConversionProducer
7594589dd92SRiver Riddle     : public OpConversionPattern<TestTypeProducerOp> {
7604589dd92SRiver Riddle   using OpConversionPattern<TestTypeProducerOp>::OpConversionPattern;
7614589dd92SRiver Riddle   LogicalResult
7624589dd92SRiver Riddle   matchAndRewrite(TestTypeProducerOp op, ArrayRef<Value> operands,
7634589dd92SRiver Riddle                   ConversionPatternRewriter &rewriter) const final {
7644589dd92SRiver Riddle     Type resultType = op.getType();
7654589dd92SRiver Riddle     if (resultType.isa<FloatType>())
7664589dd92SRiver Riddle       resultType = rewriter.getF64Type();
7674589dd92SRiver Riddle     else if (resultType.isInteger(16))
7684589dd92SRiver Riddle       resultType = rewriter.getIntegerType(64);
7694589dd92SRiver Riddle     else
7704589dd92SRiver Riddle       return failure();
7714589dd92SRiver Riddle 
7724589dd92SRiver Riddle     rewriter.replaceOpWithNewOp<TestTypeProducerOp>(op, resultType);
7734589dd92SRiver Riddle     return success();
7744589dd92SRiver Riddle   }
7754589dd92SRiver Riddle };
7764589dd92SRiver Riddle 
7774589dd92SRiver Riddle struct TestTypeConversionDriver
7784589dd92SRiver Riddle     : public PassWrapper<TestTypeConversionDriver, OperationPass<ModuleOp>> {
779f9dc2b70SMehdi Amini   void getDependentDialects(DialectRegistry &registry) const override {
780f9dc2b70SMehdi Amini     registry.insert<TestDialect>();
781f9dc2b70SMehdi Amini   }
782f9dc2b70SMehdi Amini 
7834589dd92SRiver Riddle   void runOnOperation() override {
7844589dd92SRiver Riddle     // Initialize the type converter.
7854589dd92SRiver Riddle     TypeConverter converter;
7864589dd92SRiver Riddle 
7874589dd92SRiver Riddle     /// Add the legal set of type conversions.
7884589dd92SRiver Riddle     converter.addConversion([](Type type) -> Type {
7894589dd92SRiver Riddle       // Treat F64 as legal.
7904589dd92SRiver Riddle       if (type.isF64())
7914589dd92SRiver Riddle         return type;
7924589dd92SRiver Riddle       // Allow converting BF16/F16/F32 to F64.
7934589dd92SRiver Riddle       if (type.isBF16() || type.isF16() || type.isF32())
7944589dd92SRiver Riddle         return FloatType::getF64(type.getContext());
7954589dd92SRiver Riddle       // Otherwise, the type is illegal.
7964589dd92SRiver Riddle       return nullptr;
7974589dd92SRiver Riddle     });
7984589dd92SRiver Riddle     converter.addConversion([](IntegerType type, SmallVectorImpl<Type> &) {
7994589dd92SRiver Riddle       // Drop all integer types.
8004589dd92SRiver Riddle       return success();
8014589dd92SRiver Riddle     });
8024589dd92SRiver Riddle 
8034589dd92SRiver Riddle     /// Add the legal set of type materializations.
8044589dd92SRiver Riddle     converter.addSourceMaterialization([](OpBuilder &builder, Type resultType,
8054589dd92SRiver Riddle                                           ValueRange inputs,
8064589dd92SRiver Riddle                                           Location loc) -> Value {
8074589dd92SRiver Riddle       // Allow casting from F64 back to F32.
8084589dd92SRiver Riddle       if (!resultType.isF16() && inputs.size() == 1 &&
8094589dd92SRiver Riddle           inputs[0].getType().isF64())
8104589dd92SRiver Riddle         return builder.create<TestCastOp>(loc, resultType, inputs).getResult();
8114589dd92SRiver Riddle       // Allow producing an i32 or i64 from nothing.
8124589dd92SRiver Riddle       if ((resultType.isInteger(32) || resultType.isInteger(64)) &&
8134589dd92SRiver Riddle           inputs.empty())
8144589dd92SRiver Riddle         return builder.create<TestTypeProducerOp>(loc, resultType);
8154589dd92SRiver Riddle       // Allow producing an i64 from an integer.
8164589dd92SRiver Riddle       if (resultType.isa<IntegerType>() && inputs.size() == 1 &&
8174589dd92SRiver Riddle           inputs[0].getType().isa<IntegerType>())
8184589dd92SRiver Riddle         return builder.create<TestCastOp>(loc, resultType, inputs).getResult();
8194589dd92SRiver Riddle       // Otherwise, fail.
8204589dd92SRiver Riddle       return nullptr;
8214589dd92SRiver Riddle     });
8224589dd92SRiver Riddle 
8234589dd92SRiver Riddle     // Initialize the conversion target.
8244589dd92SRiver Riddle     mlir::ConversionTarget target(getContext());
8254589dd92SRiver Riddle     target.addDynamicallyLegalOp<TestTypeProducerOp>([](TestTypeProducerOp op) {
8264589dd92SRiver Riddle       return op.getType().isF64() || op.getType().isInteger(64);
8274589dd92SRiver Riddle     });
8284589dd92SRiver Riddle     target.addDynamicallyLegalOp<FuncOp>([&](FuncOp op) {
8294589dd92SRiver Riddle       return converter.isSignatureLegal(op.getType()) &&
8304589dd92SRiver Riddle              converter.isLegal(&op.getBody());
8314589dd92SRiver Riddle     });
8324589dd92SRiver Riddle     target.addDynamicallyLegalOp<TestCastOp>([&](TestCastOp op) {
8334589dd92SRiver Riddle       // Allow casts from F64 to F32.
8344589dd92SRiver Riddle       return (*op.operand_type_begin()).isF64() && op.getType().isF32();
8354589dd92SRiver Riddle     });
8364589dd92SRiver Riddle 
8374589dd92SRiver Riddle     // Initialize the set of rewrite patterns.
8384589dd92SRiver Riddle     OwningRewritePatternList patterns;
8394589dd92SRiver Riddle     patterns.insert<TestTypeConversionProducer>(converter, &getContext());
8404589dd92SRiver Riddle     mlir::populateFuncOpTypeConversionPattern(patterns, &getContext(),
8414589dd92SRiver Riddle                                               converter);
8424589dd92SRiver Riddle 
8433fffffa8SRiver Riddle     if (failed(applyPartialConversion(getOperation(), target,
8443fffffa8SRiver Riddle                                       std::move(patterns))))
8454589dd92SRiver Riddle       signalPassFailure();
8464589dd92SRiver Riddle   }
8474589dd92SRiver Riddle };
8484589dd92SRiver Riddle } // end anonymous namespace
8494589dd92SRiver Riddle 
850e888886cSMaheshRavishankar namespace {
851e888886cSMaheshRavishankar /// A rewriter pattern that tests that blocks can be merged.
852e888886cSMaheshRavishankar struct TestMergeBlock : public OpConversionPattern<TestMergeBlocksOp> {
853e888886cSMaheshRavishankar   using OpConversionPattern<TestMergeBlocksOp>::OpConversionPattern;
854e888886cSMaheshRavishankar 
855e888886cSMaheshRavishankar   LogicalResult
856e888886cSMaheshRavishankar   matchAndRewrite(TestMergeBlocksOp op, ArrayRef<Value> operands,
857e888886cSMaheshRavishankar                   ConversionPatternRewriter &rewriter) const final {
858e888886cSMaheshRavishankar     Block &firstBlock = op.body().front();
859e888886cSMaheshRavishankar     Operation *branchOp = firstBlock.getTerminator();
860e888886cSMaheshRavishankar     Block *secondBlock = &*(std::next(op.body().begin()));
861e888886cSMaheshRavishankar     auto succOperands = branchOp->getOperands();
862e888886cSMaheshRavishankar     SmallVector<Value, 2> replacements(succOperands);
863e888886cSMaheshRavishankar     rewriter.eraseOp(branchOp);
864e888886cSMaheshRavishankar     rewriter.mergeBlocks(secondBlock, &firstBlock, replacements);
865e888886cSMaheshRavishankar     rewriter.updateRootInPlace(op, [] {});
866e888886cSMaheshRavishankar     return success();
867e888886cSMaheshRavishankar   }
868e888886cSMaheshRavishankar };
869e888886cSMaheshRavishankar 
870e888886cSMaheshRavishankar /// A rewrite pattern to tests the undo mechanism of blocks being merged.
871e888886cSMaheshRavishankar struct TestUndoBlocksMerge : public ConversionPattern {
872e888886cSMaheshRavishankar   TestUndoBlocksMerge(MLIRContext *ctx)
873e888886cSMaheshRavishankar       : ConversionPattern("test.undo_blocks_merge", /*benefit=*/1, ctx) {}
874e888886cSMaheshRavishankar   LogicalResult
875e888886cSMaheshRavishankar   matchAndRewrite(Operation *op, ArrayRef<Value> operands,
876e888886cSMaheshRavishankar                   ConversionPatternRewriter &rewriter) const final {
877e888886cSMaheshRavishankar     Block &firstBlock = op->getRegion(0).front();
878e888886cSMaheshRavishankar     Operation *branchOp = firstBlock.getTerminator();
879e888886cSMaheshRavishankar     Block *secondBlock = &*(std::next(op->getRegion(0).begin()));
880e888886cSMaheshRavishankar     rewriter.setInsertionPointToStart(secondBlock);
881e888886cSMaheshRavishankar     rewriter.create<ILLegalOpF>(op->getLoc(), rewriter.getF32Type());
882e888886cSMaheshRavishankar     auto succOperands = branchOp->getOperands();
883e888886cSMaheshRavishankar     SmallVector<Value, 2> replacements(succOperands);
884e888886cSMaheshRavishankar     rewriter.eraseOp(branchOp);
885e888886cSMaheshRavishankar     rewriter.mergeBlocks(secondBlock, &firstBlock, replacements);
886e888886cSMaheshRavishankar     rewriter.updateRootInPlace(op, [] {});
887e888886cSMaheshRavishankar     return success();
888e888886cSMaheshRavishankar   }
889e888886cSMaheshRavishankar };
890e888886cSMaheshRavishankar 
891e888886cSMaheshRavishankar /// A rewrite mechanism to inline the body of the op into its parent, when both
892e888886cSMaheshRavishankar /// ops can have a single block.
893e888886cSMaheshRavishankar struct TestMergeSingleBlockOps
894e888886cSMaheshRavishankar     : public OpConversionPattern<SingleBlockImplicitTerminatorOp> {
895e888886cSMaheshRavishankar   using OpConversionPattern<
896e888886cSMaheshRavishankar       SingleBlockImplicitTerminatorOp>::OpConversionPattern;
897e888886cSMaheshRavishankar 
898e888886cSMaheshRavishankar   LogicalResult
899e888886cSMaheshRavishankar   matchAndRewrite(SingleBlockImplicitTerminatorOp op, ArrayRef<Value> operands,
900e888886cSMaheshRavishankar                   ConversionPatternRewriter &rewriter) const final {
901e888886cSMaheshRavishankar     SingleBlockImplicitTerminatorOp parentOp =
9020bf4a82aSChristian Sigg         op->getParentOfType<SingleBlockImplicitTerminatorOp>();
903e888886cSMaheshRavishankar     if (!parentOp)
904e888886cSMaheshRavishankar       return failure();
905e888886cSMaheshRavishankar     Block &innerBlock = op.region().front();
906e888886cSMaheshRavishankar     TerminatorOp innerTerminator =
907e888886cSMaheshRavishankar         cast<TerminatorOp>(innerBlock.getTerminator());
9089c7b0c4aSRahul Joshi     rewriter.mergeBlockBefore(&innerBlock, op);
909e888886cSMaheshRavishankar     rewriter.eraseOp(innerTerminator);
910e888886cSMaheshRavishankar     rewriter.eraseOp(op);
911e888886cSMaheshRavishankar     rewriter.updateRootInPlace(op, [] {});
912e888886cSMaheshRavishankar     return success();
913e888886cSMaheshRavishankar   }
914e888886cSMaheshRavishankar };
915e888886cSMaheshRavishankar 
916e888886cSMaheshRavishankar struct TestMergeBlocksPatternDriver
917e888886cSMaheshRavishankar     : public PassWrapper<TestMergeBlocksPatternDriver,
918e888886cSMaheshRavishankar                          OperationPass<ModuleOp>> {
919e888886cSMaheshRavishankar   void runOnOperation() override {
920e888886cSMaheshRavishankar     mlir::OwningRewritePatternList patterns;
921e888886cSMaheshRavishankar     MLIRContext *context = &getContext();
922e888886cSMaheshRavishankar     patterns
923e888886cSMaheshRavishankar         .insert<TestMergeBlock, TestUndoBlocksMerge, TestMergeSingleBlockOps>(
924e888886cSMaheshRavishankar             context);
925e888886cSMaheshRavishankar     ConversionTarget target(*context);
926e888886cSMaheshRavishankar     target.addLegalOp<FuncOp, ModuleOp, ModuleTerminatorOp, TerminatorOp,
927e888886cSMaheshRavishankar                       TestBranchOp, TestTypeConsumerOp, TestTypeProducerOp,
928e888886cSMaheshRavishankar                       TestReturnOp>();
929e888886cSMaheshRavishankar     target.addIllegalOp<ILLegalOpF>();
930e888886cSMaheshRavishankar 
931e888886cSMaheshRavishankar     /// Expect the op to have a single block after legalization.
932e888886cSMaheshRavishankar     target.addDynamicallyLegalOp<TestMergeBlocksOp>(
933e888886cSMaheshRavishankar         [&](TestMergeBlocksOp op) -> bool {
934e888886cSMaheshRavishankar           return llvm::hasSingleElement(op.body());
935e888886cSMaheshRavishankar         });
936e888886cSMaheshRavishankar 
937e888886cSMaheshRavishankar     /// Only allow `test.br` within test.merge_blocks op.
938e888886cSMaheshRavishankar     target.addDynamicallyLegalOp<TestBranchOp>([&](TestBranchOp op) -> bool {
9390bf4a82aSChristian Sigg       return op->getParentOfType<TestMergeBlocksOp>();
940e888886cSMaheshRavishankar     });
941e888886cSMaheshRavishankar 
942e888886cSMaheshRavishankar     /// Expect that all nested test.SingleBlockImplicitTerminator ops are
943e888886cSMaheshRavishankar     /// inlined.
944e888886cSMaheshRavishankar     target.addDynamicallyLegalOp<SingleBlockImplicitTerminatorOp>(
945e888886cSMaheshRavishankar         [&](SingleBlockImplicitTerminatorOp op) -> bool {
9460bf4a82aSChristian Sigg           return !op->getParentOfType<SingleBlockImplicitTerminatorOp>();
947e888886cSMaheshRavishankar         });
948e888886cSMaheshRavishankar 
949e888886cSMaheshRavishankar     DenseSet<Operation *> unlegalizedOps;
9503fffffa8SRiver Riddle     (void)applyPartialConversion(getOperation(), target, std::move(patterns),
951e888886cSMaheshRavishankar                                  &unlegalizedOps);
952e888886cSMaheshRavishankar     for (auto *op : unlegalizedOps)
953e888886cSMaheshRavishankar       op->emitRemark() << "op '" << op->getName() << "' is not legalizable";
954e888886cSMaheshRavishankar   }
955e888886cSMaheshRavishankar };
956e888886cSMaheshRavishankar } // namespace
957e888886cSMaheshRavishankar 
9584589dd92SRiver Riddle //===----------------------------------------------------------------------===//
9594589dd92SRiver Riddle // PassRegistration
9604589dd92SRiver Riddle //===----------------------------------------------------------------------===//
9614589dd92SRiver Riddle 
962fec6c5acSUday Bondhugula namespace mlir {
96372c65b69SAlexander Belyaev namespace test {
964fec6c5acSUday Bondhugula void registerPatternsTestPass() {
96580d7ac3bSRiver Riddle   PassRegistration<TestReturnTypeDriver>("test-return-type",
966fec6c5acSUday Bondhugula                                          "Run return type functions");
967fec6c5acSUday Bondhugula 
96880d7ac3bSRiver Riddle   PassRegistration<TestDerivedAttributeDriver>("test-derived-attr",
96980d7ac3bSRiver Riddle                                                "Run test derived attributes");
9709ba37b3bSJacques Pienaar 
97180d7ac3bSRiver Riddle   PassRegistration<TestPatternDriver>("test-patterns",
972fec6c5acSUday Bondhugula                                       "Run test dialect patterns");
973fec6c5acSUday Bondhugula 
97480d7ac3bSRiver Riddle   PassRegistration<TestLegalizePatternDriver>(
975fec6c5acSUday Bondhugula       "test-legalize-patterns", "Run test dialect legalization patterns", [] {
976fec6c5acSUday Bondhugula         return std::make_unique<TestLegalizePatternDriver>(
977fec6c5acSUday Bondhugula             legalizerConversionMode);
978fec6c5acSUday Bondhugula       });
979fec6c5acSUday Bondhugula 
980fec6c5acSUday Bondhugula   PassRegistration<TestRemappedValue>(
981fec6c5acSUday Bondhugula       "test-remapped-value",
982fec6c5acSUday Bondhugula       "Test public remapped value mechanism in ConversionPatternRewriter");
98380d7ac3bSRiver Riddle 
98480d7ac3bSRiver Riddle   PassRegistration<TestUnknownRootOpDriver>(
98580d7ac3bSRiver Riddle       "test-legalize-unknown-root-patterns",
98680d7ac3bSRiver Riddle       "Test public remapped value mechanism in ConversionPatternRewriter");
9874589dd92SRiver Riddle 
9884589dd92SRiver Riddle   PassRegistration<TestTypeConversionDriver>(
9894589dd92SRiver Riddle       "test-legalize-type-conversion",
9904589dd92SRiver Riddle       "Test various type conversion functionalities in DialectConversion");
991e888886cSMaheshRavishankar 
992e888886cSMaheshRavishankar   PassRegistration<TestMergeBlocksPatternDriver>{
993e888886cSMaheshRavishankar       "test-merge-blocks",
994e888886cSMaheshRavishankar       "Test Merging operation in ConversionPatternRewriter"};
995fec6c5acSUday Bondhugula }
99672c65b69SAlexander Belyaev } // namespace test
997fec6c5acSUday Bondhugula } // namespace mlir
998