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" 10fec6c5acSUday Bondhugula #include "mlir/Conversion/StandardToStandard/StandardToStandard.h" 11fec6c5acSUday Bondhugula #include "mlir/IR/PatternMatch.h" 12fec6c5acSUday Bondhugula #include "mlir/Pass/Pass.h" 13fec6c5acSUday Bondhugula #include "mlir/Transforms/DialectConversion.h" 149ba37b3bSJacques Pienaar 15fec6c5acSUday Bondhugula using namespace mlir; 16fec6c5acSUday Bondhugula 17fec6c5acSUday Bondhugula // Native function for testing NativeCodeCall 18fec6c5acSUday Bondhugula static Value chooseOperand(Value input1, Value input2, BoolAttr choice) { 19fec6c5acSUday Bondhugula return choice.getValue() ? input1 : input2; 20fec6c5acSUday Bondhugula } 21fec6c5acSUday Bondhugula 22fec6c5acSUday Bondhugula static void createOpI(PatternRewriter &rewriter, Value input) { 23fec6c5acSUday Bondhugula rewriter.create<OpI>(rewriter.getUnknownLoc(), input); 24fec6c5acSUday Bondhugula } 25fec6c5acSUday Bondhugula 26fec6c5acSUday Bondhugula static void handleNoResultOp(PatternRewriter &rewriter, 27fec6c5acSUday Bondhugula OpSymbolBindingNoResult op) { 28fec6c5acSUday Bondhugula // Turn the no result op to a one-result op. 29fec6c5acSUday Bondhugula rewriter.create<OpSymbolBindingB>(op.getLoc(), op.operand().getType(), 30fec6c5acSUday Bondhugula op.operand()); 31fec6c5acSUday Bondhugula } 32fec6c5acSUday Bondhugula 33fec6c5acSUday Bondhugula namespace { 34fec6c5acSUday Bondhugula #include "TestPatterns.inc" 35fec6c5acSUday Bondhugula } // end anonymous namespace 36fec6c5acSUday Bondhugula 37fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===// 38fec6c5acSUday Bondhugula // Canonicalizer Driver. 39fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===// 40fec6c5acSUday Bondhugula 41fec6c5acSUday Bondhugula namespace { 4280aca1eaSRiver Riddle struct TestPatternDriver : public PassWrapper<TestPatternDriver, FunctionPass> { 43fec6c5acSUday Bondhugula void runOnFunction() override { 44fec6c5acSUday Bondhugula mlir::OwningRewritePatternList patterns; 45fec6c5acSUday Bondhugula populateWithGenerated(&getContext(), &patterns); 46fec6c5acSUday Bondhugula 47fec6c5acSUday Bondhugula // Verify named pattern is generated with expected name. 48fec6c5acSUday Bondhugula patterns.insert<TestNamedPatternRule>(&getContext()); 49fec6c5acSUday Bondhugula 50a5b9316bSUday Bondhugula applyPatternsAndFoldGreedily(getFunction(), patterns); 51fec6c5acSUday Bondhugula } 52fec6c5acSUday Bondhugula }; 53fec6c5acSUday Bondhugula } // end anonymous namespace 54fec6c5acSUday Bondhugula 55fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===// 56fec6c5acSUday Bondhugula // ReturnType Driver. 57fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===// 58fec6c5acSUday Bondhugula 59fec6c5acSUday Bondhugula namespace { 60fec6c5acSUday Bondhugula // Generate ops for each instance where the type can be successfully inferred. 61fec6c5acSUday Bondhugula template <typename OpTy> 62fec6c5acSUday Bondhugula static void invokeCreateWithInferredReturnType(Operation *op) { 63fec6c5acSUday Bondhugula auto *context = op->getContext(); 64fec6c5acSUday Bondhugula auto fop = op->getParentOfType<FuncOp>(); 65fec6c5acSUday Bondhugula auto location = UnknownLoc::get(context); 66fec6c5acSUday Bondhugula OpBuilder b(op); 67fec6c5acSUday Bondhugula b.setInsertionPointAfter(op); 68fec6c5acSUday Bondhugula 69fec6c5acSUday Bondhugula // Use permutations of 2 args as operands. 70fec6c5acSUday Bondhugula assert(fop.getNumArguments() >= 2); 71fec6c5acSUday Bondhugula for (int i = 0, e = fop.getNumArguments(); i < e; ++i) { 72fec6c5acSUday Bondhugula for (int j = 0; j < e; ++j) { 73fec6c5acSUday Bondhugula std::array<Value, 2> values = {{fop.getArgument(i), fop.getArgument(j)}}; 74fec6c5acSUday Bondhugula SmallVector<Type, 2> inferredReturnTypes; 75fec6c5acSUday Bondhugula if (succeeded(OpTy::inferReturnTypes(context, llvm::None, values, 76fec6c5acSUday Bondhugula op->getAttrs(), op->getRegions(), 77fec6c5acSUday Bondhugula inferredReturnTypes))) { 78fec6c5acSUday Bondhugula OperationState state(location, OpTy::getOperationName()); 79fec6c5acSUday Bondhugula // TODO(jpienaar): Expand to regions. 80*bb1d976fSAlex Zinenko OpTy::build(b, state, values, op->getAttrs()); 81fec6c5acSUday Bondhugula (void)b.createOperation(state); 82fec6c5acSUday Bondhugula } 83fec6c5acSUday Bondhugula } 84fec6c5acSUday Bondhugula } 85fec6c5acSUday Bondhugula } 86fec6c5acSUday Bondhugula 87fec6c5acSUday Bondhugula static void reifyReturnShape(Operation *op) { 88fec6c5acSUday Bondhugula OpBuilder b(op); 89fec6c5acSUday Bondhugula 90fec6c5acSUday Bondhugula // Use permutations of 2 args as operands. 91fec6c5acSUday Bondhugula auto shapedOp = cast<OpWithShapedTypeInferTypeInterfaceOp>(op); 92fec6c5acSUday Bondhugula SmallVector<Value, 2> shapes; 93fec6c5acSUday Bondhugula if (failed(shapedOp.reifyReturnTypeShapes(b, shapes))) 94fec6c5acSUday Bondhugula return; 95fec6c5acSUday Bondhugula for (auto it : llvm::enumerate(shapes)) 96fec6c5acSUday Bondhugula op->emitRemark() << "value " << it.index() << ": " 97fec6c5acSUday Bondhugula << it.value().getDefiningOp(); 98fec6c5acSUday Bondhugula } 99fec6c5acSUday Bondhugula 10080aca1eaSRiver Riddle struct TestReturnTypeDriver 10180aca1eaSRiver Riddle : public PassWrapper<TestReturnTypeDriver, FunctionPass> { 102fec6c5acSUday Bondhugula void runOnFunction() override { 103fec6c5acSUday Bondhugula if (getFunction().getName() == "testCreateFunctions") { 104fec6c5acSUday Bondhugula std::vector<Operation *> ops; 105fec6c5acSUday Bondhugula // Collect ops to avoid triggering on inserted ops. 106fec6c5acSUday Bondhugula for (auto &op : getFunction().getBody().front()) 107fec6c5acSUday Bondhugula ops.push_back(&op); 108fec6c5acSUday Bondhugula // Generate test patterns for each, but skip terminator. 109fec6c5acSUday Bondhugula for (auto *op : llvm::makeArrayRef(ops).drop_back()) { 110fec6c5acSUday Bondhugula // Test create method of each of the Op classes below. The resultant 111fec6c5acSUday Bondhugula // output would be in reverse order underneath `op` from which 112fec6c5acSUday Bondhugula // the attributes and regions are used. 113fec6c5acSUday Bondhugula invokeCreateWithInferredReturnType<OpWithInferTypeInterfaceOp>(op); 114fec6c5acSUday Bondhugula invokeCreateWithInferredReturnType< 115fec6c5acSUday Bondhugula OpWithShapedTypeInferTypeInterfaceOp>(op); 116fec6c5acSUday Bondhugula }; 117fec6c5acSUday Bondhugula return; 118fec6c5acSUday Bondhugula } 119fec6c5acSUday Bondhugula if (getFunction().getName() == "testReifyFunctions") { 120fec6c5acSUday Bondhugula std::vector<Operation *> ops; 121fec6c5acSUday Bondhugula // Collect ops to avoid triggering on inserted ops. 122fec6c5acSUday Bondhugula for (auto &op : getFunction().getBody().front()) 123fec6c5acSUday Bondhugula if (isa<OpWithShapedTypeInferTypeInterfaceOp>(op)) 124fec6c5acSUday Bondhugula ops.push_back(&op); 125fec6c5acSUday Bondhugula // Generate test patterns for each, but skip terminator. 126fec6c5acSUday Bondhugula for (auto *op : ops) 127fec6c5acSUday Bondhugula reifyReturnShape(op); 128fec6c5acSUday Bondhugula } 129fec6c5acSUday Bondhugula } 130fec6c5acSUday Bondhugula }; 131fec6c5acSUday Bondhugula } // end anonymous namespace 132fec6c5acSUday Bondhugula 1339ba37b3bSJacques Pienaar namespace { 1349ba37b3bSJacques Pienaar struct TestDerivedAttributeDriver 1359ba37b3bSJacques Pienaar : public PassWrapper<TestDerivedAttributeDriver, FunctionPass> { 1369ba37b3bSJacques Pienaar void runOnFunction() override; 1379ba37b3bSJacques Pienaar }; 1389ba37b3bSJacques Pienaar } // end anonymous namespace 1399ba37b3bSJacques Pienaar 1409ba37b3bSJacques Pienaar void TestDerivedAttributeDriver::runOnFunction() { 1419ba37b3bSJacques Pienaar getFunction().walk([](DerivedAttributeOpInterface dOp) { 1429ba37b3bSJacques Pienaar auto dAttr = dOp.materializeDerivedAttributes(); 1439ba37b3bSJacques Pienaar if (!dAttr) 1449ba37b3bSJacques Pienaar return; 1459ba37b3bSJacques Pienaar for (auto d : dAttr) 1469ba37b3bSJacques Pienaar dOp.emitRemark() << d.first << " = " << d.second; 1479ba37b3bSJacques Pienaar }); 1489ba37b3bSJacques Pienaar } 1499ba37b3bSJacques Pienaar 150fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===// 151fec6c5acSUday Bondhugula // Legalization Driver. 152fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===// 153fec6c5acSUday Bondhugula 154fec6c5acSUday Bondhugula namespace { 155fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===// 156fec6c5acSUday Bondhugula // Region-Block Rewrite Testing 157fec6c5acSUday Bondhugula 158fec6c5acSUday Bondhugula /// This pattern is a simple pattern that inlines the first region of a given 159fec6c5acSUday Bondhugula /// operation into the parent region. 160fec6c5acSUday Bondhugula struct TestRegionRewriteBlockMovement : public ConversionPattern { 161fec6c5acSUday Bondhugula TestRegionRewriteBlockMovement(MLIRContext *ctx) 162fec6c5acSUday Bondhugula : ConversionPattern("test.region", 1, ctx) {} 163fec6c5acSUday Bondhugula 164fec6c5acSUday Bondhugula LogicalResult 165fec6c5acSUday Bondhugula matchAndRewrite(Operation *op, ArrayRef<Value> operands, 166fec6c5acSUday Bondhugula ConversionPatternRewriter &rewriter) const final { 167fec6c5acSUday Bondhugula // Inline this region into the parent region. 168fec6c5acSUday Bondhugula auto &parentRegion = *op->getParentRegion(); 169fec6c5acSUday Bondhugula if (op->getAttr("legalizer.should_clone")) 170fec6c5acSUday Bondhugula rewriter.cloneRegionBefore(op->getRegion(0), parentRegion, 171fec6c5acSUday Bondhugula parentRegion.end()); 172fec6c5acSUday Bondhugula else 173fec6c5acSUday Bondhugula rewriter.inlineRegionBefore(op->getRegion(0), parentRegion, 174fec6c5acSUday Bondhugula parentRegion.end()); 175fec6c5acSUday Bondhugula 176fec6c5acSUday Bondhugula // Drop this operation. 177fec6c5acSUday Bondhugula rewriter.eraseOp(op); 178fec6c5acSUday Bondhugula return success(); 179fec6c5acSUday Bondhugula } 180fec6c5acSUday Bondhugula }; 181fec6c5acSUday Bondhugula /// This pattern is a simple pattern that generates a region containing an 182fec6c5acSUday Bondhugula /// illegal operation. 183fec6c5acSUday Bondhugula struct TestRegionRewriteUndo : public RewritePattern { 184fec6c5acSUday Bondhugula TestRegionRewriteUndo(MLIRContext *ctx) 185fec6c5acSUday Bondhugula : RewritePattern("test.region_builder", 1, ctx) {} 186fec6c5acSUday Bondhugula 187fec6c5acSUday Bondhugula LogicalResult matchAndRewrite(Operation *op, 188fec6c5acSUday Bondhugula PatternRewriter &rewriter) const final { 189fec6c5acSUday Bondhugula // Create the region operation with an entry block containing arguments. 190fec6c5acSUday Bondhugula OperationState newRegion(op->getLoc(), "test.region"); 191fec6c5acSUday Bondhugula newRegion.addRegion(); 192fec6c5acSUday Bondhugula auto *regionOp = rewriter.createOperation(newRegion); 193fec6c5acSUday Bondhugula auto *entryBlock = rewriter.createBlock(®ionOp->getRegion(0)); 194fec6c5acSUday Bondhugula entryBlock->addArgument(rewriter.getIntegerType(64)); 195fec6c5acSUday Bondhugula 196fec6c5acSUday Bondhugula // Add an explicitly illegal operation to ensure the conversion fails. 197fec6c5acSUday Bondhugula rewriter.create<ILLegalOpF>(op->getLoc(), rewriter.getIntegerType(32)); 198fec6c5acSUday Bondhugula rewriter.create<TestValidOp>(op->getLoc(), ArrayRef<Value>()); 199fec6c5acSUday Bondhugula 200fec6c5acSUday Bondhugula // Drop this operation. 201fec6c5acSUday Bondhugula rewriter.eraseOp(op); 202fec6c5acSUday Bondhugula return success(); 203fec6c5acSUday Bondhugula } 204fec6c5acSUday Bondhugula }; 205f27f1e8cSAlex Zinenko /// A simple pattern that creates a block at the end of the parent region of the 206f27f1e8cSAlex Zinenko /// matched operation. 207f27f1e8cSAlex Zinenko struct TestCreateBlock : public RewritePattern { 208f27f1e8cSAlex Zinenko TestCreateBlock(MLIRContext *ctx) 209f27f1e8cSAlex Zinenko : RewritePattern("test.create_block", /*benefit=*/1, ctx) {} 210f27f1e8cSAlex Zinenko 211f27f1e8cSAlex Zinenko LogicalResult matchAndRewrite(Operation *op, 212f27f1e8cSAlex Zinenko PatternRewriter &rewriter) const final { 213f27f1e8cSAlex Zinenko Region ®ion = *op->getParentRegion(); 214f27f1e8cSAlex Zinenko Type i32Type = rewriter.getIntegerType(32); 215f27f1e8cSAlex Zinenko rewriter.createBlock(®ion, region.end(), {i32Type, i32Type}); 216f27f1e8cSAlex Zinenko rewriter.create<TerminatorOp>(op->getLoc()); 217f27f1e8cSAlex Zinenko rewriter.replaceOp(op, {}); 218f27f1e8cSAlex Zinenko return success(); 219f27f1e8cSAlex Zinenko } 220f27f1e8cSAlex Zinenko }; 221f27f1e8cSAlex Zinenko 222f27f1e8cSAlex Zinenko /// A simple pattern that creates a block containing an invalid operaiton in 223f27f1e8cSAlex Zinenko /// order to trigger the block creation undo mechanism. 224f27f1e8cSAlex Zinenko struct TestCreateIllegalBlock : public RewritePattern { 225f27f1e8cSAlex Zinenko TestCreateIllegalBlock(MLIRContext *ctx) 226f27f1e8cSAlex Zinenko : RewritePattern("test.create_illegal_block", /*benefit=*/1, ctx) {} 227f27f1e8cSAlex Zinenko 228f27f1e8cSAlex Zinenko LogicalResult matchAndRewrite(Operation *op, 229f27f1e8cSAlex Zinenko PatternRewriter &rewriter) const final { 230f27f1e8cSAlex Zinenko Region ®ion = *op->getParentRegion(); 231f27f1e8cSAlex Zinenko Type i32Type = rewriter.getIntegerType(32); 232f27f1e8cSAlex Zinenko rewriter.createBlock(®ion, region.end(), {i32Type, i32Type}); 233f27f1e8cSAlex Zinenko // Create an illegal op to ensure the conversion fails. 234f27f1e8cSAlex Zinenko rewriter.create<ILLegalOpF>(op->getLoc(), i32Type); 235f27f1e8cSAlex Zinenko rewriter.create<TerminatorOp>(op->getLoc()); 236f27f1e8cSAlex Zinenko rewriter.replaceOp(op, {}); 237f27f1e8cSAlex Zinenko return success(); 238f27f1e8cSAlex Zinenko } 239f27f1e8cSAlex Zinenko }; 240fec6c5acSUday Bondhugula 2410816de16SRiver Riddle /// A simple pattern that tests the undo mechanism when replacing the uses of a 2420816de16SRiver Riddle /// block argument. 2430816de16SRiver Riddle struct TestUndoBlockArgReplace : public ConversionPattern { 2440816de16SRiver Riddle TestUndoBlockArgReplace(MLIRContext *ctx) 2450816de16SRiver Riddle : ConversionPattern("test.undo_block_arg_replace", /*benefit=*/1, ctx) {} 2460816de16SRiver Riddle 2470816de16SRiver Riddle LogicalResult 2480816de16SRiver Riddle matchAndRewrite(Operation *op, ArrayRef<Value> operands, 2490816de16SRiver Riddle ConversionPatternRewriter &rewriter) const final { 2500816de16SRiver Riddle auto illegalOp = 2510816de16SRiver Riddle rewriter.create<ILLegalOpF>(op->getLoc(), rewriter.getF32Type()); 2520816de16SRiver Riddle rewriter.replaceUsesOfBlockArgument(op->getRegion(0).front().getArgument(0), 2530816de16SRiver Riddle illegalOp); 2540816de16SRiver Riddle rewriter.updateRootInPlace(op, [] {}); 2550816de16SRiver Riddle return success(); 2560816de16SRiver Riddle } 2570816de16SRiver Riddle }; 2580816de16SRiver Riddle 259fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===// 260fec6c5acSUday Bondhugula // Type-Conversion Rewrite Testing 261fec6c5acSUday Bondhugula 262fec6c5acSUday Bondhugula /// This patterns erases a region operation that has had a type conversion. 263fec6c5acSUday Bondhugula struct TestDropOpSignatureConversion : public ConversionPattern { 264fec6c5acSUday Bondhugula TestDropOpSignatureConversion(MLIRContext *ctx, TypeConverter &converter) 265fec6c5acSUday Bondhugula : ConversionPattern("test.drop_region_op", 1, ctx), converter(converter) { 266fec6c5acSUday Bondhugula } 267fec6c5acSUday Bondhugula LogicalResult 268fec6c5acSUday Bondhugula matchAndRewrite(Operation *op, ArrayRef<Value> operands, 269fec6c5acSUday Bondhugula ConversionPatternRewriter &rewriter) const override { 270fec6c5acSUday Bondhugula Region ®ion = op->getRegion(0); 271fec6c5acSUday Bondhugula Block *entry = ®ion.front(); 272fec6c5acSUday Bondhugula 273fec6c5acSUday Bondhugula // Convert the original entry arguments. 274fec6c5acSUday Bondhugula TypeConverter::SignatureConversion result(entry->getNumArguments()); 275fec6c5acSUday Bondhugula for (unsigned i = 0, e = entry->getNumArguments(); i != e; ++i) 276fec6c5acSUday Bondhugula if (failed(converter.convertSignatureArg( 277fec6c5acSUday Bondhugula i, entry->getArgument(i).getType(), result))) 278fec6c5acSUday Bondhugula return failure(); 279fec6c5acSUday Bondhugula 280fec6c5acSUday Bondhugula // Convert the region signature and just drop the operation. 281fec6c5acSUday Bondhugula rewriter.applySignatureConversion(®ion, result); 282fec6c5acSUday Bondhugula rewriter.eraseOp(op); 283fec6c5acSUday Bondhugula return success(); 284fec6c5acSUday Bondhugula } 285fec6c5acSUday Bondhugula 286fec6c5acSUday Bondhugula /// The type converter to use when rewriting the signature. 287fec6c5acSUday Bondhugula TypeConverter &converter; 288fec6c5acSUday Bondhugula }; 289fec6c5acSUday Bondhugula /// This pattern simply updates the operands of the given operation. 290fec6c5acSUday Bondhugula struct TestPassthroughInvalidOp : public ConversionPattern { 291fec6c5acSUday Bondhugula TestPassthroughInvalidOp(MLIRContext *ctx) 292fec6c5acSUday Bondhugula : ConversionPattern("test.invalid", 1, ctx) {} 293fec6c5acSUday Bondhugula LogicalResult 294fec6c5acSUday Bondhugula matchAndRewrite(Operation *op, ArrayRef<Value> operands, 295fec6c5acSUday Bondhugula ConversionPatternRewriter &rewriter) const final { 296fec6c5acSUday Bondhugula rewriter.replaceOpWithNewOp<TestValidOp>(op, llvm::None, operands, 297fec6c5acSUday Bondhugula llvm::None); 298fec6c5acSUday Bondhugula return success(); 299fec6c5acSUday Bondhugula } 300fec6c5acSUday Bondhugula }; 301fec6c5acSUday Bondhugula /// This pattern handles the case of a split return value. 302fec6c5acSUday Bondhugula struct TestSplitReturnType : public ConversionPattern { 303fec6c5acSUday Bondhugula TestSplitReturnType(MLIRContext *ctx) 304fec6c5acSUday Bondhugula : ConversionPattern("test.return", 1, ctx) {} 305fec6c5acSUday Bondhugula LogicalResult 306fec6c5acSUday Bondhugula matchAndRewrite(Operation *op, ArrayRef<Value> operands, 307fec6c5acSUday Bondhugula ConversionPatternRewriter &rewriter) const final { 308fec6c5acSUday Bondhugula // Check for a return of F32. 309fec6c5acSUday Bondhugula if (op->getNumOperands() != 1 || !op->getOperand(0).getType().isF32()) 310fec6c5acSUday Bondhugula return failure(); 311fec6c5acSUday Bondhugula 312fec6c5acSUday Bondhugula // Check if the first operation is a cast operation, if it is we use the 313fec6c5acSUday Bondhugula // results directly. 314fec6c5acSUday Bondhugula auto *defOp = operands[0].getDefiningOp(); 315fec6c5acSUday Bondhugula if (auto packerOp = llvm::dyn_cast_or_null<TestCastOp>(defOp)) { 316fec6c5acSUday Bondhugula rewriter.replaceOpWithNewOp<TestReturnOp>(op, packerOp.getOperands()); 317fec6c5acSUday Bondhugula return success(); 318fec6c5acSUday Bondhugula } 319fec6c5acSUday Bondhugula 320fec6c5acSUday Bondhugula // Otherwise, fail to match. 321fec6c5acSUday Bondhugula return failure(); 322fec6c5acSUday Bondhugula } 323fec6c5acSUday Bondhugula }; 324fec6c5acSUday Bondhugula 325fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===// 326fec6c5acSUday Bondhugula // Multi-Level Type-Conversion Rewrite Testing 327fec6c5acSUday Bondhugula struct TestChangeProducerTypeI32ToF32 : public ConversionPattern { 328fec6c5acSUday Bondhugula TestChangeProducerTypeI32ToF32(MLIRContext *ctx) 329fec6c5acSUday Bondhugula : ConversionPattern("test.type_producer", 1, ctx) {} 330fec6c5acSUday Bondhugula LogicalResult 331fec6c5acSUday Bondhugula matchAndRewrite(Operation *op, ArrayRef<Value> operands, 332fec6c5acSUday Bondhugula ConversionPatternRewriter &rewriter) const final { 333fec6c5acSUday Bondhugula // If the type is I32, change the type to F32. 334fec6c5acSUday Bondhugula if (!Type(*op->result_type_begin()).isSignlessInteger(32)) 335fec6c5acSUday Bondhugula return failure(); 336fec6c5acSUday Bondhugula rewriter.replaceOpWithNewOp<TestTypeProducerOp>(op, rewriter.getF32Type()); 337fec6c5acSUday Bondhugula return success(); 338fec6c5acSUday Bondhugula } 339fec6c5acSUday Bondhugula }; 340fec6c5acSUday Bondhugula struct TestChangeProducerTypeF32ToF64 : public ConversionPattern { 341fec6c5acSUday Bondhugula TestChangeProducerTypeF32ToF64(MLIRContext *ctx) 342fec6c5acSUday Bondhugula : ConversionPattern("test.type_producer", 1, ctx) {} 343fec6c5acSUday Bondhugula LogicalResult 344fec6c5acSUday Bondhugula matchAndRewrite(Operation *op, ArrayRef<Value> operands, 345fec6c5acSUday Bondhugula ConversionPatternRewriter &rewriter) const final { 346fec6c5acSUday Bondhugula // If the type is F32, change the type to F64. 347fec6c5acSUday Bondhugula if (!Type(*op->result_type_begin()).isF32()) 348fec6c5acSUday Bondhugula return rewriter.notifyMatchFailure(op, "expected single f32 operand"); 349fec6c5acSUday Bondhugula rewriter.replaceOpWithNewOp<TestTypeProducerOp>(op, rewriter.getF64Type()); 350fec6c5acSUday Bondhugula return success(); 351fec6c5acSUday Bondhugula } 352fec6c5acSUday Bondhugula }; 353fec6c5acSUday Bondhugula struct TestChangeProducerTypeF32ToInvalid : public ConversionPattern { 354fec6c5acSUday Bondhugula TestChangeProducerTypeF32ToInvalid(MLIRContext *ctx) 355fec6c5acSUday Bondhugula : ConversionPattern("test.type_producer", 10, ctx) {} 356fec6c5acSUday Bondhugula LogicalResult 357fec6c5acSUday Bondhugula matchAndRewrite(Operation *op, ArrayRef<Value> operands, 358fec6c5acSUday Bondhugula ConversionPatternRewriter &rewriter) const final { 359fec6c5acSUday Bondhugula // Always convert to B16, even though it is not a legal type. This tests 360fec6c5acSUday Bondhugula // that values are unmapped correctly. 361fec6c5acSUday Bondhugula rewriter.replaceOpWithNewOp<TestTypeProducerOp>(op, rewriter.getBF16Type()); 362fec6c5acSUday Bondhugula return success(); 363fec6c5acSUday Bondhugula } 364fec6c5acSUday Bondhugula }; 365fec6c5acSUday Bondhugula struct TestUpdateConsumerType : public ConversionPattern { 366fec6c5acSUday Bondhugula TestUpdateConsumerType(MLIRContext *ctx) 367fec6c5acSUday Bondhugula : ConversionPattern("test.type_consumer", 1, ctx) {} 368fec6c5acSUday Bondhugula LogicalResult 369fec6c5acSUday Bondhugula matchAndRewrite(Operation *op, ArrayRef<Value> operands, 370fec6c5acSUday Bondhugula ConversionPatternRewriter &rewriter) const final { 371fec6c5acSUday Bondhugula // Verify that the incoming operand has been successfully remapped to F64. 372fec6c5acSUday Bondhugula if (!operands[0].getType().isF64()) 373fec6c5acSUday Bondhugula return failure(); 374fec6c5acSUday Bondhugula rewriter.replaceOpWithNewOp<TestTypeConsumerOp>(op, operands[0]); 375fec6c5acSUday Bondhugula return success(); 376fec6c5acSUday Bondhugula } 377fec6c5acSUday Bondhugula }; 378fec6c5acSUday Bondhugula 379fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===// 380fec6c5acSUday Bondhugula // Non-Root Replacement Rewrite Testing 381fec6c5acSUday Bondhugula /// This pattern generates an invalid operation, but replaces it before the 382fec6c5acSUday Bondhugula /// pattern is finished. This checks that we don't need to legalize the 383fec6c5acSUday Bondhugula /// temporary op. 384fec6c5acSUday Bondhugula struct TestNonRootReplacement : public RewritePattern { 385fec6c5acSUday Bondhugula TestNonRootReplacement(MLIRContext *ctx) 386fec6c5acSUday Bondhugula : RewritePattern("test.replace_non_root", 1, ctx) {} 387fec6c5acSUday Bondhugula 388fec6c5acSUday Bondhugula LogicalResult matchAndRewrite(Operation *op, 389fec6c5acSUday Bondhugula PatternRewriter &rewriter) const final { 390fec6c5acSUday Bondhugula auto resultType = *op->result_type_begin(); 391fec6c5acSUday Bondhugula auto illegalOp = rewriter.create<ILLegalOpF>(op->getLoc(), resultType); 392fec6c5acSUday Bondhugula auto legalOp = rewriter.create<LegalOpB>(op->getLoc(), resultType); 393fec6c5acSUday Bondhugula 394fec6c5acSUday Bondhugula rewriter.replaceOp(illegalOp, {legalOp}); 395fec6c5acSUday Bondhugula rewriter.replaceOp(op, {illegalOp}); 396fec6c5acSUday Bondhugula return success(); 397fec6c5acSUday Bondhugula } 398fec6c5acSUday Bondhugula }; 399bd1ccfe6SRiver Riddle 400bd1ccfe6SRiver Riddle //===----------------------------------------------------------------------===// 401bd1ccfe6SRiver Riddle // Recursive Rewrite Testing 402bd1ccfe6SRiver Riddle /// This pattern is applied to the same operation multiple times, but has a 403bd1ccfe6SRiver Riddle /// bounded recursion. 404bd1ccfe6SRiver Riddle struct TestBoundedRecursiveRewrite 405bd1ccfe6SRiver Riddle : public OpRewritePattern<TestRecursiveRewriteOp> { 406bd1ccfe6SRiver Riddle using OpRewritePattern<TestRecursiveRewriteOp>::OpRewritePattern; 407bd1ccfe6SRiver Riddle 408bd1ccfe6SRiver Riddle LogicalResult matchAndRewrite(TestRecursiveRewriteOp op, 409bd1ccfe6SRiver Riddle PatternRewriter &rewriter) const final { 410bd1ccfe6SRiver Riddle // Decrement the depth of the op in-place. 411bd1ccfe6SRiver Riddle rewriter.updateRootInPlace(op, [&] { 412bd1ccfe6SRiver Riddle op.setAttr("depth", 413bd1ccfe6SRiver Riddle rewriter.getI64IntegerAttr(op.depth().getSExtValue() - 1)); 414bd1ccfe6SRiver Riddle }); 415bd1ccfe6SRiver Riddle return success(); 416bd1ccfe6SRiver Riddle } 417bd1ccfe6SRiver Riddle 418bd1ccfe6SRiver Riddle /// The conversion target handles bounding the recursion of this pattern. 419bd1ccfe6SRiver Riddle bool hasBoundedRewriteRecursion() const final { return true; } 420bd1ccfe6SRiver Riddle }; 421fec6c5acSUday Bondhugula } // namespace 422fec6c5acSUday Bondhugula 423fec6c5acSUday Bondhugula namespace { 424fec6c5acSUday Bondhugula struct TestTypeConverter : public TypeConverter { 425fec6c5acSUday Bondhugula using TypeConverter::TypeConverter; 426fec6c5acSUday Bondhugula TestTypeConverter() { addConversion(convertType); } 427fec6c5acSUday Bondhugula 428fec6c5acSUday Bondhugula static LogicalResult convertType(Type t, SmallVectorImpl<Type> &results) { 429fec6c5acSUday Bondhugula // Drop I16 types. 430fec6c5acSUday Bondhugula if (t.isSignlessInteger(16)) 431fec6c5acSUday Bondhugula return success(); 432fec6c5acSUday Bondhugula 433fec6c5acSUday Bondhugula // Convert I64 to F64. 434fec6c5acSUday Bondhugula if (t.isSignlessInteger(64)) { 435fec6c5acSUday Bondhugula results.push_back(FloatType::getF64(t.getContext())); 436fec6c5acSUday Bondhugula return success(); 437fec6c5acSUday Bondhugula } 438fec6c5acSUday Bondhugula 439fec6c5acSUday Bondhugula // Split F32 into F16,F16. 440fec6c5acSUday Bondhugula if (t.isF32()) { 441fec6c5acSUday Bondhugula results.assign(2, FloatType::getF16(t.getContext())); 442fec6c5acSUday Bondhugula return success(); 443fec6c5acSUday Bondhugula } 444fec6c5acSUday Bondhugula 445fec6c5acSUday Bondhugula // Otherwise, convert the type directly. 446fec6c5acSUday Bondhugula results.push_back(t); 447fec6c5acSUday Bondhugula return success(); 448fec6c5acSUday Bondhugula } 449fec6c5acSUday Bondhugula 450fec6c5acSUday Bondhugula /// Override the hook to materialize a conversion. This is necessary because 451fec6c5acSUday Bondhugula /// we generate 1->N type mappings. 452fec6c5acSUday Bondhugula Operation *materializeConversion(PatternRewriter &rewriter, Type resultType, 453fec6c5acSUday Bondhugula ArrayRef<Value> inputs, 454fec6c5acSUday Bondhugula Location loc) override { 455fec6c5acSUday Bondhugula return rewriter.create<TestCastOp>(loc, resultType, inputs); 456fec6c5acSUday Bondhugula } 457fec6c5acSUday Bondhugula }; 458fec6c5acSUday Bondhugula 459fec6c5acSUday Bondhugula struct TestLegalizePatternDriver 46080aca1eaSRiver Riddle : public PassWrapper<TestLegalizePatternDriver, OperationPass<ModuleOp>> { 461fec6c5acSUday Bondhugula /// The mode of conversion to use with the driver. 462fec6c5acSUday Bondhugula enum class ConversionMode { Analysis, Full, Partial }; 463fec6c5acSUday Bondhugula 464fec6c5acSUday Bondhugula TestLegalizePatternDriver(ConversionMode mode) : mode(mode) {} 465fec6c5acSUday Bondhugula 466722f909fSRiver Riddle void runOnOperation() override { 467fec6c5acSUday Bondhugula TestTypeConverter converter; 468fec6c5acSUday Bondhugula mlir::OwningRewritePatternList patterns; 469fec6c5acSUday Bondhugula populateWithGenerated(&getContext(), &patterns); 4700816de16SRiver Riddle patterns.insert<TestRegionRewriteBlockMovement, TestRegionRewriteUndo, 4710816de16SRiver Riddle TestCreateBlock, TestCreateIllegalBlock, 4720816de16SRiver Riddle TestUndoBlockArgReplace, TestPassthroughInvalidOp, 4730816de16SRiver Riddle TestSplitReturnType, TestChangeProducerTypeI32ToF32, 4740816de16SRiver Riddle TestChangeProducerTypeF32ToF64, 475fec6c5acSUday Bondhugula TestChangeProducerTypeF32ToInvalid, TestUpdateConsumerType, 4760816de16SRiver Riddle TestNonRootReplacement, TestBoundedRecursiveRewrite>( 4770816de16SRiver Riddle &getContext()); 478fec6c5acSUday Bondhugula patterns.insert<TestDropOpSignatureConversion>(&getContext(), converter); 479fec6c5acSUday Bondhugula mlir::populateFuncOpTypeConversionPattern(patterns, &getContext(), 480fec6c5acSUday Bondhugula converter); 481fec6c5acSUday Bondhugula mlir::populateCallOpTypeConversionPattern(patterns, &getContext(), 482fec6c5acSUday Bondhugula converter); 483fec6c5acSUday Bondhugula 484fec6c5acSUday Bondhugula // Define the conversion target used for the test. 485fec6c5acSUday Bondhugula ConversionTarget target(getContext()); 486fec6c5acSUday Bondhugula target.addLegalOp<ModuleOp, ModuleTerminatorOp>(); 487f27f1e8cSAlex Zinenko target.addLegalOp<LegalOpA, LegalOpB, TestCastOp, TestValidOp, 488f27f1e8cSAlex Zinenko TerminatorOp>(); 489fec6c5acSUday Bondhugula target 490fec6c5acSUday Bondhugula .addIllegalOp<ILLegalOpF, TestRegionBuilderOp, TestOpWithRegionFold>(); 491fec6c5acSUday Bondhugula target.addDynamicallyLegalOp<TestReturnOp>([](TestReturnOp op) { 492fec6c5acSUday Bondhugula // Don't allow F32 operands. 493fec6c5acSUday Bondhugula return llvm::none_of(op.getOperandTypes(), 494fec6c5acSUday Bondhugula [](Type type) { return type.isF32(); }); 495fec6c5acSUday Bondhugula }); 496fec6c5acSUday Bondhugula target.addDynamicallyLegalOp<FuncOp>( 497fec6c5acSUday Bondhugula [&](FuncOp op) { return converter.isSignatureLegal(op.getType()); }); 498fec6c5acSUday Bondhugula 499fec6c5acSUday Bondhugula // Expect the type_producer/type_consumer operations to only operate on f64. 500fec6c5acSUday Bondhugula target.addDynamicallyLegalOp<TestTypeProducerOp>( 501fec6c5acSUday Bondhugula [](TestTypeProducerOp op) { return op.getType().isF64(); }); 502fec6c5acSUday Bondhugula target.addDynamicallyLegalOp<TestTypeConsumerOp>([](TestTypeConsumerOp op) { 503fec6c5acSUday Bondhugula return op.getOperand().getType().isF64(); 504fec6c5acSUday Bondhugula }); 505fec6c5acSUday Bondhugula 506fec6c5acSUday Bondhugula // Check support for marking certain operations as recursively legal. 507fec6c5acSUday Bondhugula target.markOpRecursivelyLegal<FuncOp, ModuleOp>([](Operation *op) { 508fec6c5acSUday Bondhugula return static_cast<bool>( 509fec6c5acSUday Bondhugula op->getAttrOfType<UnitAttr>("test.recursively_legal")); 510fec6c5acSUday Bondhugula }); 511fec6c5acSUday Bondhugula 512bd1ccfe6SRiver Riddle // Mark the bound recursion operation as dynamically legal. 513bd1ccfe6SRiver Riddle target.addDynamicallyLegalOp<TestRecursiveRewriteOp>( 514bd1ccfe6SRiver Riddle [](TestRecursiveRewriteOp op) { return op.depth() == 0; }); 515bd1ccfe6SRiver Riddle 516fec6c5acSUday Bondhugula // Handle a partial conversion. 517fec6c5acSUday Bondhugula if (mode == ConversionMode::Partial) { 518722f909fSRiver Riddle (void)applyPartialConversion(getOperation(), target, patterns, 519722f909fSRiver Riddle &converter); 520fec6c5acSUday Bondhugula return; 521fec6c5acSUday Bondhugula } 522fec6c5acSUday Bondhugula 523fec6c5acSUday Bondhugula // Handle a full conversion. 524fec6c5acSUday Bondhugula if (mode == ConversionMode::Full) { 525fec6c5acSUday Bondhugula // Check support for marking unknown operations as dynamically legal. 526fec6c5acSUday Bondhugula target.markUnknownOpDynamicallyLegal([](Operation *op) { 527fec6c5acSUday Bondhugula return (bool)op->getAttrOfType<UnitAttr>("test.dynamically_legal"); 528fec6c5acSUday Bondhugula }); 529fec6c5acSUday Bondhugula 530722f909fSRiver Riddle (void)applyFullConversion(getOperation(), target, patterns, &converter); 531fec6c5acSUday Bondhugula return; 532fec6c5acSUday Bondhugula } 533fec6c5acSUday Bondhugula 534fec6c5acSUday Bondhugula // Otherwise, handle an analysis conversion. 535fec6c5acSUday Bondhugula assert(mode == ConversionMode::Analysis); 536fec6c5acSUday Bondhugula 537fec6c5acSUday Bondhugula // Analyze the convertible operations. 538fec6c5acSUday Bondhugula DenseSet<Operation *> legalizedOps; 539722f909fSRiver Riddle if (failed(applyAnalysisConversion(getOperation(), target, patterns, 540fec6c5acSUday Bondhugula legalizedOps, &converter))) 541fec6c5acSUday Bondhugula return signalPassFailure(); 542fec6c5acSUday Bondhugula 543fec6c5acSUday Bondhugula // Emit remarks for each legalizable operation. 544fec6c5acSUday Bondhugula for (auto *op : legalizedOps) 545fec6c5acSUday Bondhugula op->emitRemark() << "op '" << op->getName() << "' is legalizable"; 546fec6c5acSUday Bondhugula } 547fec6c5acSUday Bondhugula 548fec6c5acSUday Bondhugula /// The mode of conversion to use. 549fec6c5acSUday Bondhugula ConversionMode mode; 550fec6c5acSUday Bondhugula }; 551fec6c5acSUday Bondhugula } // end anonymous namespace 552fec6c5acSUday Bondhugula 553fec6c5acSUday Bondhugula static llvm::cl::opt<TestLegalizePatternDriver::ConversionMode> 554fec6c5acSUday Bondhugula legalizerConversionMode( 555fec6c5acSUday Bondhugula "test-legalize-mode", 556fec6c5acSUday Bondhugula llvm::cl::desc("The legalization mode to use with the test driver"), 557fec6c5acSUday Bondhugula llvm::cl::init(TestLegalizePatternDriver::ConversionMode::Partial), 558fec6c5acSUday Bondhugula llvm::cl::values( 559fec6c5acSUday Bondhugula clEnumValN(TestLegalizePatternDriver::ConversionMode::Analysis, 560fec6c5acSUday Bondhugula "analysis", "Perform an analysis conversion"), 561fec6c5acSUday Bondhugula clEnumValN(TestLegalizePatternDriver::ConversionMode::Full, "full", 562fec6c5acSUday Bondhugula "Perform a full conversion"), 563fec6c5acSUday Bondhugula clEnumValN(TestLegalizePatternDriver::ConversionMode::Partial, 564fec6c5acSUday Bondhugula "partial", "Perform a partial conversion"))); 565fec6c5acSUday Bondhugula 566fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===// 567fec6c5acSUday Bondhugula // ConversionPatternRewriter::getRemappedValue testing. This method is used 5685aacce3dSKazuaki Ishizaki // to get the remapped value of an original value that was replaced using 569fec6c5acSUday Bondhugula // ConversionPatternRewriter. 570fec6c5acSUday Bondhugula namespace { 571fec6c5acSUday Bondhugula /// Converter that replaces a one-result one-operand OneVResOneVOperandOp1 with 572fec6c5acSUday Bondhugula /// a one-operand two-result OneVResOneVOperandOp1 by replicating its original 573fec6c5acSUday Bondhugula /// operand twice. 574fec6c5acSUday Bondhugula /// 575fec6c5acSUday Bondhugula /// Example: 576fec6c5acSUday Bondhugula /// %1 = test.one_variadic_out_one_variadic_in1"(%0) 577fec6c5acSUday Bondhugula /// is replaced with: 578fec6c5acSUday Bondhugula /// %1 = test.one_variadic_out_one_variadic_in1"(%0, %0) 579fec6c5acSUday Bondhugula struct OneVResOneVOperandOp1Converter 580fec6c5acSUday Bondhugula : public OpConversionPattern<OneVResOneVOperandOp1> { 581fec6c5acSUday Bondhugula using OpConversionPattern<OneVResOneVOperandOp1>::OpConversionPattern; 582fec6c5acSUday Bondhugula 583fec6c5acSUday Bondhugula LogicalResult 584fec6c5acSUday Bondhugula matchAndRewrite(OneVResOneVOperandOp1 op, ArrayRef<Value> operands, 585fec6c5acSUday Bondhugula ConversionPatternRewriter &rewriter) const override { 586fec6c5acSUday Bondhugula auto origOps = op.getOperands(); 587fec6c5acSUday Bondhugula assert(std::distance(origOps.begin(), origOps.end()) == 1 && 588fec6c5acSUday Bondhugula "One operand expected"); 589fec6c5acSUday Bondhugula Value origOp = *origOps.begin(); 590fec6c5acSUday Bondhugula SmallVector<Value, 2> remappedOperands; 591fec6c5acSUday Bondhugula // Replicate the remapped original operand twice. Note that we don't used 592fec6c5acSUday Bondhugula // the remapped 'operand' since the goal is testing 'getRemappedValue'. 593fec6c5acSUday Bondhugula remappedOperands.push_back(rewriter.getRemappedValue(origOp)); 594fec6c5acSUday Bondhugula remappedOperands.push_back(rewriter.getRemappedValue(origOp)); 595fec6c5acSUday Bondhugula 596fec6c5acSUday Bondhugula rewriter.replaceOpWithNewOp<OneVResOneVOperandOp1>(op, op.getResultTypes(), 597fec6c5acSUday Bondhugula remappedOperands); 598fec6c5acSUday Bondhugula return success(); 599fec6c5acSUday Bondhugula } 600fec6c5acSUday Bondhugula }; 601fec6c5acSUday Bondhugula 60280aca1eaSRiver Riddle struct TestRemappedValue 60380aca1eaSRiver Riddle : public mlir::PassWrapper<TestRemappedValue, FunctionPass> { 604fec6c5acSUday Bondhugula void runOnFunction() override { 605fec6c5acSUday Bondhugula mlir::OwningRewritePatternList patterns; 606fec6c5acSUday Bondhugula patterns.insert<OneVResOneVOperandOp1Converter>(&getContext()); 607fec6c5acSUday Bondhugula 608fec6c5acSUday Bondhugula mlir::ConversionTarget target(getContext()); 609fec6c5acSUday Bondhugula target.addLegalOp<ModuleOp, ModuleTerminatorOp, FuncOp, TestReturnOp>(); 610fec6c5acSUday Bondhugula // We make OneVResOneVOperandOp1 legal only when it has more that one 611fec6c5acSUday Bondhugula // operand. This will trigger the conversion that will replace one-operand 612fec6c5acSUday Bondhugula // OneVResOneVOperandOp1 with two-operand OneVResOneVOperandOp1. 613fec6c5acSUday Bondhugula target.addDynamicallyLegalOp<OneVResOneVOperandOp1>( 614fec6c5acSUday Bondhugula [](Operation *op) -> bool { 615fec6c5acSUday Bondhugula return std::distance(op->operand_begin(), op->operand_end()) > 1; 616fec6c5acSUday Bondhugula }); 617fec6c5acSUday Bondhugula 618fec6c5acSUday Bondhugula if (failed(mlir::applyFullConversion(getFunction(), target, patterns))) { 619fec6c5acSUday Bondhugula signalPassFailure(); 620fec6c5acSUday Bondhugula } 621fec6c5acSUday Bondhugula } 622fec6c5acSUday Bondhugula }; 623fec6c5acSUday Bondhugula } // end anonymous namespace 624fec6c5acSUday Bondhugula 625fec6c5acSUday Bondhugula namespace mlir { 626fec6c5acSUday Bondhugula void registerPatternsTestPass() { 627fec6c5acSUday Bondhugula mlir::PassRegistration<TestReturnTypeDriver>("test-return-type", 628fec6c5acSUday Bondhugula "Run return type functions"); 629fec6c5acSUday Bondhugula 6309ba37b3bSJacques Pienaar mlir::PassRegistration<TestDerivedAttributeDriver>( 6319ba37b3bSJacques Pienaar "test-derived-attr", "Run test derived attributes"); 6329ba37b3bSJacques Pienaar 633fec6c5acSUday Bondhugula mlir::PassRegistration<TestPatternDriver>("test-patterns", 634fec6c5acSUday Bondhugula "Run test dialect patterns"); 635fec6c5acSUday Bondhugula 636fec6c5acSUday Bondhugula mlir::PassRegistration<TestLegalizePatternDriver>( 637fec6c5acSUday Bondhugula "test-legalize-patterns", "Run test dialect legalization patterns", [] { 638fec6c5acSUday Bondhugula return std::make_unique<TestLegalizePatternDriver>( 639fec6c5acSUday Bondhugula legalizerConversionMode); 640fec6c5acSUday Bondhugula }); 641fec6c5acSUday Bondhugula 642fec6c5acSUday Bondhugula PassRegistration<TestRemappedValue>( 643fec6c5acSUday Bondhugula "test-remapped-value", 644fec6c5acSUday Bondhugula "Test public remapped value mechanism in ConversionPatternRewriter"); 645fec6c5acSUday Bondhugula } 646fec6c5acSUday Bondhugula } // namespace mlir 647