1abfd1a8bSRiver Riddle //===- TestPDLByteCode.cpp - Test rewriter bytecode functionality ---------===// 2abfd1a8bSRiver Riddle // 3abfd1a8bSRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4abfd1a8bSRiver Riddle // See https://llvm.org/LICENSE.txt for license information. 5abfd1a8bSRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6abfd1a8bSRiver Riddle // 7abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===// 8abfd1a8bSRiver Riddle 9b4130e9eSStanislav Funiak #include "mlir/Dialect/PDLInterp/IR/PDLInterp.h" 10abfd1a8bSRiver Riddle #include "mlir/Pass/Pass.h" 11abfd1a8bSRiver Riddle #include "mlir/Pass/PassManager.h" 12abfd1a8bSRiver Riddle #include "mlir/Transforms/GreedyPatternRewriteDriver.h" 13abfd1a8bSRiver Riddle 14abfd1a8bSRiver Riddle using namespace mlir; 15abfd1a8bSRiver Riddle 16abfd1a8bSRiver Riddle /// Custom constraint invoked from PDL. 17abfd1a8bSRiver Riddle static LogicalResult customSingleEntityConstraint(PDLValue value, 18abfd1a8bSRiver Riddle PatternRewriter &rewriter) { 19abfd1a8bSRiver Riddle Operation *rootOp = value.cast<Operation *>(); 20abfd1a8bSRiver Riddle return success(rootOp->getName().getStringRef() == "test.op"); 21abfd1a8bSRiver Riddle } 22abfd1a8bSRiver Riddle static LogicalResult customMultiEntityConstraint(ArrayRef<PDLValue> values, 23abfd1a8bSRiver Riddle PatternRewriter &rewriter) { 24*9595f356SRiver Riddle return customSingleEntityConstraint(values[1], rewriter); 25abfd1a8bSRiver Riddle } 2685ab413bSRiver Riddle static LogicalResult 2785ab413bSRiver Riddle customMultiEntityVariadicConstraint(ArrayRef<PDLValue> values, 2885ab413bSRiver Riddle PatternRewriter &rewriter) { 2985ab413bSRiver Riddle if (llvm::any_of(values, [](const PDLValue &value) { return !value; })) 3085ab413bSRiver Riddle return failure(); 3185ab413bSRiver Riddle ValueRange operandValues = values[0].cast<ValueRange>(); 3285ab413bSRiver Riddle TypeRange typeValues = values[1].cast<TypeRange>(); 3385ab413bSRiver Riddle if (operandValues.size() != 2 || typeValues.size() != 2) 3485ab413bSRiver Riddle return failure(); 3585ab413bSRiver Riddle return success(); 3685ab413bSRiver Riddle } 37abfd1a8bSRiver Riddle 38abfd1a8bSRiver Riddle // Custom creator invoked from PDL. 39*9595f356SRiver Riddle static void customCreate(ArrayRef<PDLValue> args, PatternRewriter &rewriter, 40*9595f356SRiver Riddle PDLResultList &results) { 4102c4c0d5SRiver Riddle results.push_back(rewriter.createOperation( 4202c4c0d5SRiver Riddle OperationState(args[0].cast<Operation *>()->getLoc(), "test.success"))); 43abfd1a8bSRiver Riddle } 4485ab413bSRiver Riddle static void customVariadicResultCreate(ArrayRef<PDLValue> args, 4585ab413bSRiver Riddle PatternRewriter &rewriter, 4685ab413bSRiver Riddle PDLResultList &results) { 4785ab413bSRiver Riddle Operation *root = args[0].cast<Operation *>(); 4885ab413bSRiver Riddle results.push_back(root->getOperands()); 4985ab413bSRiver Riddle results.push_back(root->getOperands().getTypes()); 5085ab413bSRiver Riddle } 51*9595f356SRiver Riddle static void customCreateType(ArrayRef<PDLValue> args, PatternRewriter &rewriter, 5285ab413bSRiver Riddle PDLResultList &results) { 5385ab413bSRiver Riddle results.push_back(rewriter.getF32Type()); 5485ab413bSRiver Riddle } 55abfd1a8bSRiver Riddle 56abfd1a8bSRiver Riddle /// Custom rewriter invoked from PDL. 57*9595f356SRiver Riddle static void customRewriter(ArrayRef<PDLValue> args, PatternRewriter &rewriter, 58*9595f356SRiver Riddle PDLResultList &results) { 5902c4c0d5SRiver Riddle Operation *root = args[0].cast<Operation *>(); 60abfd1a8bSRiver Riddle OperationState successOpState(root->getLoc(), "test.success"); 6102c4c0d5SRiver Riddle successOpState.addOperands(args[1].cast<Value>()); 62abfd1a8bSRiver Riddle rewriter.createOperation(successOpState); 63abfd1a8bSRiver Riddle rewriter.eraseOp(root); 64abfd1a8bSRiver Riddle } 65abfd1a8bSRiver Riddle 66abfd1a8bSRiver Riddle namespace { 67abfd1a8bSRiver Riddle struct TestPDLByteCodePass 68abfd1a8bSRiver Riddle : public PassWrapper<TestPDLByteCodePass, OperationPass<ModuleOp>> { 69b5e22e6dSMehdi Amini StringRef getArgument() const final { return "test-pdl-bytecode-pass"; } 70b5e22e6dSMehdi Amini StringRef getDescription() const final { 71b5e22e6dSMehdi Amini return "Test PDL ByteCode functionality"; 72b5e22e6dSMehdi Amini } 73b4130e9eSStanislav Funiak void getDependentDialects(DialectRegistry ®istry) const override { 74b4130e9eSStanislav Funiak // Mark the pdl_interp dialect as a dependent. This is needed, because we 75b4130e9eSStanislav Funiak // create ops from that dialect as a part of the PDL-to-PDLInterp lowering. 76b4130e9eSStanislav Funiak registry.insert<pdl_interp::PDLInterpDialect>(); 77b4130e9eSStanislav Funiak } 78abfd1a8bSRiver Riddle void runOnOperation() final { 79abfd1a8bSRiver Riddle ModuleOp module = getOperation(); 80abfd1a8bSRiver Riddle 81abfd1a8bSRiver Riddle // The test cases are encompassed via two modules, one containing the 82abfd1a8bSRiver Riddle // patterns and one containing the operations to rewrite. 8341d4aa7dSChris Lattner ModuleOp patternModule = module.lookupSymbol<ModuleOp>( 8441d4aa7dSChris Lattner StringAttr::get(module->getContext(), "patterns")); 8541d4aa7dSChris Lattner ModuleOp irModule = module.lookupSymbol<ModuleOp>( 8641d4aa7dSChris Lattner StringAttr::get(module->getContext(), "ir")); 87abfd1a8bSRiver Riddle if (!patternModule || !irModule) 88abfd1a8bSRiver Riddle return; 89abfd1a8bSRiver Riddle 9006c3b9c7SRiver Riddle RewritePatternSet patternList(module->getContext()); 9106c3b9c7SRiver Riddle 9206c3b9c7SRiver Riddle // Register ahead of time to test when functions are registered without a 9306c3b9c7SRiver Riddle // pattern. 9406c3b9c7SRiver Riddle patternList.getPDLPatterns().registerConstraintFunction( 9506c3b9c7SRiver Riddle "multi_entity_constraint", customMultiEntityConstraint); 9606c3b9c7SRiver Riddle patternList.getPDLPatterns().registerConstraintFunction( 9706c3b9c7SRiver Riddle "single_entity_constraint", customSingleEntityConstraint); 9806c3b9c7SRiver Riddle 99abfd1a8bSRiver Riddle // Process the pattern module. 100abfd1a8bSRiver Riddle patternModule.getOperation()->remove(); 101abfd1a8bSRiver Riddle PDLPatternModule pdlPattern(patternModule); 10206c3b9c7SRiver Riddle 10306c3b9c7SRiver Riddle // Note: This constraint was already registered, but we re-register here to 10406c3b9c7SRiver Riddle // ensure that duplication registration is allowed (the duplicate mapping 10506c3b9c7SRiver Riddle // will be ignored). This tests that we support separating the registration 10606c3b9c7SRiver Riddle // of library functions from the construction of patterns, and also that we 10706c3b9c7SRiver Riddle // allow multiple patterns to depend on the same library functions (without 10806c3b9c7SRiver Riddle // asserting/crashing). 109abfd1a8bSRiver Riddle pdlPattern.registerConstraintFunction("multi_entity_constraint", 110abfd1a8bSRiver Riddle customMultiEntityConstraint); 11185ab413bSRiver Riddle pdlPattern.registerConstraintFunction("multi_entity_var_constraint", 11285ab413bSRiver Riddle customMultiEntityVariadicConstraint); 11302c4c0d5SRiver Riddle pdlPattern.registerRewriteFunction("creator", customCreate); 11485ab413bSRiver Riddle pdlPattern.registerRewriteFunction("var_creator", 11585ab413bSRiver Riddle customVariadicResultCreate); 11685ab413bSRiver Riddle pdlPattern.registerRewriteFunction("type_creator", customCreateType); 117abfd1a8bSRiver Riddle pdlPattern.registerRewriteFunction("rewriter", customRewriter); 11806c3b9c7SRiver Riddle patternList.add(std::move(pdlPattern)); 119abfd1a8bSRiver Riddle 120abfd1a8bSRiver Riddle // Invoke the pattern driver with the provided patterns. 121abfd1a8bSRiver Riddle (void)applyPatternsAndFoldGreedily(irModule.getBodyRegion(), 122abfd1a8bSRiver Riddle std::move(patternList)); 123abfd1a8bSRiver Riddle } 124abfd1a8bSRiver Riddle }; 125be0a7e9fSMehdi Amini } // namespace 126abfd1a8bSRiver Riddle 127abfd1a8bSRiver Riddle namespace mlir { 128abfd1a8bSRiver Riddle namespace test { 129b5e22e6dSMehdi Amini void registerTestPDLByteCodePass() { PassRegistration<TestPDLByteCodePass>(); } 130abfd1a8bSRiver Riddle } // namespace test 131abfd1a8bSRiver Riddle } // namespace mlir 132