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) { 249595f356SRiver 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. 399595f356SRiver Riddle static void customCreate(ArrayRef<PDLValue> args, PatternRewriter &rewriter, 409595f356SRiver Riddle PDLResultList &results) { 4114ecafd0SChia-hung Duan results.push_back(rewriter.create( 4202c4c0d5SRiver Riddle OperationState(args[0].cast<Operation *>()->getLoc(), "test.success"))); 43abfd1a8bSRiver Riddle } 4414ecafd0SChia-hung Duan 4585ab413bSRiver Riddle static void customVariadicResultCreate(ArrayRef<PDLValue> args, 4685ab413bSRiver Riddle PatternRewriter &rewriter, 4785ab413bSRiver Riddle PDLResultList &results) { 4885ab413bSRiver Riddle Operation *root = args[0].cast<Operation *>(); 4985ab413bSRiver Riddle results.push_back(root->getOperands()); 5085ab413bSRiver Riddle results.push_back(root->getOperands().getTypes()); 5185ab413bSRiver Riddle } 529595f356SRiver Riddle static void customCreateType(ArrayRef<PDLValue> args, PatternRewriter &rewriter, 5385ab413bSRiver Riddle PDLResultList &results) { 5485ab413bSRiver Riddle results.push_back(rewriter.getF32Type()); 5585ab413bSRiver Riddle } 56abfd1a8bSRiver Riddle 57abfd1a8bSRiver Riddle /// Custom rewriter invoked from PDL. 589595f356SRiver Riddle static void customRewriter(ArrayRef<PDLValue> args, PatternRewriter &rewriter, 599595f356SRiver Riddle PDLResultList &results) { 6002c4c0d5SRiver Riddle Operation *root = args[0].cast<Operation *>(); 61abfd1a8bSRiver Riddle OperationState successOpState(root->getLoc(), "test.success"); 6202c4c0d5SRiver Riddle successOpState.addOperands(args[1].cast<Value>()); 6314ecafd0SChia-hung Duan rewriter.create(successOpState); 64abfd1a8bSRiver Riddle rewriter.eraseOp(root); 65abfd1a8bSRiver Riddle } 66abfd1a8bSRiver Riddle 67abfd1a8bSRiver Riddle namespace { 68abfd1a8bSRiver Riddle struct TestPDLByteCodePass 69abfd1a8bSRiver Riddle : public PassWrapper<TestPDLByteCodePass, OperationPass<ModuleOp>> { 70*5e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestPDLByteCodePass) 71*5e50dd04SRiver Riddle 72b5e22e6dSMehdi Amini StringRef getArgument() const final { return "test-pdl-bytecode-pass"; } 73b5e22e6dSMehdi Amini StringRef getDescription() const final { 74b5e22e6dSMehdi Amini return "Test PDL ByteCode functionality"; 75b5e22e6dSMehdi Amini } 76b4130e9eSStanislav Funiak void getDependentDialects(DialectRegistry ®istry) const override { 77b4130e9eSStanislav Funiak // Mark the pdl_interp dialect as a dependent. This is needed, because we 78b4130e9eSStanislav Funiak // create ops from that dialect as a part of the PDL-to-PDLInterp lowering. 79b4130e9eSStanislav Funiak registry.insert<pdl_interp::PDLInterpDialect>(); 80b4130e9eSStanislav Funiak } 81abfd1a8bSRiver Riddle void runOnOperation() final { 82abfd1a8bSRiver Riddle ModuleOp module = getOperation(); 83abfd1a8bSRiver Riddle 84abfd1a8bSRiver Riddle // The test cases are encompassed via two modules, one containing the 85abfd1a8bSRiver Riddle // patterns and one containing the operations to rewrite. 8641d4aa7dSChris Lattner ModuleOp patternModule = module.lookupSymbol<ModuleOp>( 8741d4aa7dSChris Lattner StringAttr::get(module->getContext(), "patterns")); 8841d4aa7dSChris Lattner ModuleOp irModule = module.lookupSymbol<ModuleOp>( 8941d4aa7dSChris Lattner StringAttr::get(module->getContext(), "ir")); 90abfd1a8bSRiver Riddle if (!patternModule || !irModule) 91abfd1a8bSRiver Riddle return; 92abfd1a8bSRiver Riddle 9306c3b9c7SRiver Riddle RewritePatternSet patternList(module->getContext()); 9406c3b9c7SRiver Riddle 9506c3b9c7SRiver Riddle // Register ahead of time to test when functions are registered without a 9606c3b9c7SRiver Riddle // pattern. 9706c3b9c7SRiver Riddle patternList.getPDLPatterns().registerConstraintFunction( 9806c3b9c7SRiver Riddle "multi_entity_constraint", customMultiEntityConstraint); 9906c3b9c7SRiver Riddle patternList.getPDLPatterns().registerConstraintFunction( 10006c3b9c7SRiver Riddle "single_entity_constraint", customSingleEntityConstraint); 10106c3b9c7SRiver Riddle 102abfd1a8bSRiver Riddle // Process the pattern module. 103abfd1a8bSRiver Riddle patternModule.getOperation()->remove(); 104abfd1a8bSRiver Riddle PDLPatternModule pdlPattern(patternModule); 10506c3b9c7SRiver Riddle 10606c3b9c7SRiver Riddle // Note: This constraint was already registered, but we re-register here to 10706c3b9c7SRiver Riddle // ensure that duplication registration is allowed (the duplicate mapping 10806c3b9c7SRiver Riddle // will be ignored). This tests that we support separating the registration 10906c3b9c7SRiver Riddle // of library functions from the construction of patterns, and also that we 11006c3b9c7SRiver Riddle // allow multiple patterns to depend on the same library functions (without 11106c3b9c7SRiver Riddle // asserting/crashing). 112abfd1a8bSRiver Riddle pdlPattern.registerConstraintFunction("multi_entity_constraint", 113abfd1a8bSRiver Riddle customMultiEntityConstraint); 11485ab413bSRiver Riddle pdlPattern.registerConstraintFunction("multi_entity_var_constraint", 11585ab413bSRiver Riddle customMultiEntityVariadicConstraint); 11602c4c0d5SRiver Riddle pdlPattern.registerRewriteFunction("creator", customCreate); 11785ab413bSRiver Riddle pdlPattern.registerRewriteFunction("var_creator", 11885ab413bSRiver Riddle customVariadicResultCreate); 11985ab413bSRiver Riddle pdlPattern.registerRewriteFunction("type_creator", customCreateType); 120abfd1a8bSRiver Riddle pdlPattern.registerRewriteFunction("rewriter", customRewriter); 12106c3b9c7SRiver Riddle patternList.add(std::move(pdlPattern)); 122abfd1a8bSRiver Riddle 123abfd1a8bSRiver Riddle // Invoke the pattern driver with the provided patterns. 124abfd1a8bSRiver Riddle (void)applyPatternsAndFoldGreedily(irModule.getBodyRegion(), 125abfd1a8bSRiver Riddle std::move(patternList)); 126abfd1a8bSRiver Riddle } 127abfd1a8bSRiver Riddle }; 128be0a7e9fSMehdi Amini } // namespace 129abfd1a8bSRiver Riddle 130abfd1a8bSRiver Riddle namespace mlir { 131abfd1a8bSRiver Riddle namespace test { 132b5e22e6dSMehdi Amini void registerTestPDLByteCodePass() { PassRegistration<TestPDLByteCodePass>(); } 133abfd1a8bSRiver Riddle } // namespace test 134abfd1a8bSRiver Riddle } // namespace mlir 135