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(®ionOp->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 ®ion = *op->getParentRegion(); 255f27f1e8cSAlex Zinenko Type i32Type = rewriter.getIntegerType(32); 256f27f1e8cSAlex Zinenko rewriter.createBlock(®ion, 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 ®ion = *op->getParentRegion(); 272f27f1e8cSAlex Zinenko Type i32Type = rewriter.getIntegerType(32); 273f27f1e8cSAlex Zinenko rewriter.createBlock(®ion, 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 ®ion = op->getRegion(0); 328fec6c5acSUday Bondhugula Block *entry = ®ion.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(®ion, 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 ®istry) 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