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 9*b4130e9eSStanislav 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 ArrayAttr constantParams, 19abfd1a8bSRiver Riddle PatternRewriter &rewriter) { 20abfd1a8bSRiver Riddle Operation *rootOp = value.cast<Operation *>(); 21abfd1a8bSRiver Riddle return success(rootOp->getName().getStringRef() == "test.op"); 22abfd1a8bSRiver Riddle } 23abfd1a8bSRiver Riddle static LogicalResult customMultiEntityConstraint(ArrayRef<PDLValue> values, 24abfd1a8bSRiver Riddle ArrayAttr constantParams, 25abfd1a8bSRiver Riddle PatternRewriter &rewriter) { 26abfd1a8bSRiver Riddle return customSingleEntityConstraint(values[1], constantParams, rewriter); 27abfd1a8bSRiver Riddle } 2885ab413bSRiver Riddle static LogicalResult 2985ab413bSRiver Riddle customMultiEntityVariadicConstraint(ArrayRef<PDLValue> values, 3085ab413bSRiver Riddle ArrayAttr constantParams, 3185ab413bSRiver Riddle PatternRewriter &rewriter) { 3285ab413bSRiver Riddle if (llvm::any_of(values, [](const PDLValue &value) { return !value; })) 3385ab413bSRiver Riddle return failure(); 3485ab413bSRiver Riddle ValueRange operandValues = values[0].cast<ValueRange>(); 3585ab413bSRiver Riddle TypeRange typeValues = values[1].cast<TypeRange>(); 3685ab413bSRiver Riddle if (operandValues.size() != 2 || typeValues.size() != 2) 3785ab413bSRiver Riddle return failure(); 3885ab413bSRiver Riddle return success(); 3985ab413bSRiver Riddle } 40abfd1a8bSRiver Riddle 41abfd1a8bSRiver Riddle // Custom creator invoked from PDL. 4202c4c0d5SRiver Riddle static void customCreate(ArrayRef<PDLValue> args, ArrayAttr constantParams, 4302c4c0d5SRiver Riddle PatternRewriter &rewriter, PDLResultList &results) { 4402c4c0d5SRiver Riddle results.push_back(rewriter.createOperation( 4502c4c0d5SRiver Riddle OperationState(args[0].cast<Operation *>()->getLoc(), "test.success"))); 46abfd1a8bSRiver Riddle } 4785ab413bSRiver Riddle static void customVariadicResultCreate(ArrayRef<PDLValue> args, 4885ab413bSRiver Riddle ArrayAttr constantParams, 4985ab413bSRiver Riddle PatternRewriter &rewriter, 5085ab413bSRiver Riddle PDLResultList &results) { 5185ab413bSRiver Riddle Operation *root = args[0].cast<Operation *>(); 5285ab413bSRiver Riddle results.push_back(root->getOperands()); 5385ab413bSRiver Riddle results.push_back(root->getOperands().getTypes()); 5485ab413bSRiver Riddle } 5585ab413bSRiver Riddle static void customCreateType(ArrayRef<PDLValue> args, ArrayAttr constantParams, 5685ab413bSRiver Riddle PatternRewriter &rewriter, 5785ab413bSRiver Riddle PDLResultList &results) { 5885ab413bSRiver Riddle results.push_back(rewriter.getF32Type()); 5985ab413bSRiver Riddle } 60abfd1a8bSRiver Riddle 61abfd1a8bSRiver Riddle /// Custom rewriter invoked from PDL. 6202c4c0d5SRiver Riddle static void customRewriter(ArrayRef<PDLValue> args, ArrayAttr constantParams, 6302c4c0d5SRiver Riddle PatternRewriter &rewriter, PDLResultList &results) { 6402c4c0d5SRiver Riddle Operation *root = args[0].cast<Operation *>(); 65abfd1a8bSRiver Riddle OperationState successOpState(root->getLoc(), "test.success"); 6602c4c0d5SRiver Riddle successOpState.addOperands(args[1].cast<Value>()); 67abfd1a8bSRiver Riddle successOpState.addAttribute("constantParams", constantParams); 68abfd1a8bSRiver Riddle rewriter.createOperation(successOpState); 69abfd1a8bSRiver Riddle rewriter.eraseOp(root); 70abfd1a8bSRiver Riddle } 71abfd1a8bSRiver Riddle 72abfd1a8bSRiver Riddle namespace { 73abfd1a8bSRiver Riddle struct TestPDLByteCodePass 74abfd1a8bSRiver Riddle : public PassWrapper<TestPDLByteCodePass, OperationPass<ModuleOp>> { 75b5e22e6dSMehdi Amini StringRef getArgument() const final { return "test-pdl-bytecode-pass"; } 76b5e22e6dSMehdi Amini StringRef getDescription() const final { 77b5e22e6dSMehdi Amini return "Test PDL ByteCode functionality"; 78b5e22e6dSMehdi Amini } 79*b4130e9eSStanislav Funiak void getDependentDialects(DialectRegistry ®istry) const override { 80*b4130e9eSStanislav Funiak // Mark the pdl_interp dialect as a dependent. This is needed, because we 81*b4130e9eSStanislav Funiak // create ops from that dialect as a part of the PDL-to-PDLInterp lowering. 82*b4130e9eSStanislav Funiak registry.insert<pdl_interp::PDLInterpDialect>(); 83*b4130e9eSStanislav Funiak } 84abfd1a8bSRiver Riddle void runOnOperation() final { 85abfd1a8bSRiver Riddle ModuleOp module = getOperation(); 86abfd1a8bSRiver Riddle 87abfd1a8bSRiver Riddle // The test cases are encompassed via two modules, one containing the 88abfd1a8bSRiver Riddle // patterns and one containing the operations to rewrite. 8941d4aa7dSChris Lattner ModuleOp patternModule = module.lookupSymbol<ModuleOp>( 9041d4aa7dSChris Lattner StringAttr::get(module->getContext(), "patterns")); 9141d4aa7dSChris Lattner ModuleOp irModule = module.lookupSymbol<ModuleOp>( 9241d4aa7dSChris Lattner StringAttr::get(module->getContext(), "ir")); 93abfd1a8bSRiver Riddle if (!patternModule || !irModule) 94abfd1a8bSRiver Riddle return; 95abfd1a8bSRiver Riddle 9606c3b9c7SRiver Riddle RewritePatternSet patternList(module->getContext()); 9706c3b9c7SRiver Riddle 9806c3b9c7SRiver Riddle // Register ahead of time to test when functions are registered without a 9906c3b9c7SRiver Riddle // pattern. 10006c3b9c7SRiver Riddle patternList.getPDLPatterns().registerConstraintFunction( 10106c3b9c7SRiver Riddle "multi_entity_constraint", customMultiEntityConstraint); 10206c3b9c7SRiver Riddle patternList.getPDLPatterns().registerConstraintFunction( 10306c3b9c7SRiver Riddle "single_entity_constraint", customSingleEntityConstraint); 10406c3b9c7SRiver Riddle 105abfd1a8bSRiver Riddle // Process the pattern module. 106abfd1a8bSRiver Riddle patternModule.getOperation()->remove(); 107abfd1a8bSRiver Riddle PDLPatternModule pdlPattern(patternModule); 10806c3b9c7SRiver Riddle 10906c3b9c7SRiver Riddle // Note: This constraint was already registered, but we re-register here to 11006c3b9c7SRiver Riddle // ensure that duplication registration is allowed (the duplicate mapping 11106c3b9c7SRiver Riddle // will be ignored). This tests that we support separating the registration 11206c3b9c7SRiver Riddle // of library functions from the construction of patterns, and also that we 11306c3b9c7SRiver Riddle // allow multiple patterns to depend on the same library functions (without 11406c3b9c7SRiver Riddle // asserting/crashing). 115abfd1a8bSRiver Riddle pdlPattern.registerConstraintFunction("multi_entity_constraint", 116abfd1a8bSRiver Riddle customMultiEntityConstraint); 11785ab413bSRiver Riddle pdlPattern.registerConstraintFunction("multi_entity_var_constraint", 11885ab413bSRiver Riddle customMultiEntityVariadicConstraint); 11902c4c0d5SRiver Riddle pdlPattern.registerRewriteFunction("creator", customCreate); 12085ab413bSRiver Riddle pdlPattern.registerRewriteFunction("var_creator", 12185ab413bSRiver Riddle customVariadicResultCreate); 12285ab413bSRiver Riddle pdlPattern.registerRewriteFunction("type_creator", customCreateType); 123abfd1a8bSRiver Riddle pdlPattern.registerRewriteFunction("rewriter", customRewriter); 12406c3b9c7SRiver Riddle patternList.add(std::move(pdlPattern)); 125abfd1a8bSRiver Riddle 126abfd1a8bSRiver Riddle // Invoke the pattern driver with the provided patterns. 127abfd1a8bSRiver Riddle (void)applyPatternsAndFoldGreedily(irModule.getBodyRegion(), 128abfd1a8bSRiver Riddle std::move(patternList)); 129abfd1a8bSRiver Riddle } 130abfd1a8bSRiver Riddle }; 131be0a7e9fSMehdi Amini } // namespace 132abfd1a8bSRiver Riddle 133abfd1a8bSRiver Riddle namespace mlir { 134abfd1a8bSRiver Riddle namespace test { 135b5e22e6dSMehdi Amini void registerTestPDLByteCodePass() { PassRegistration<TestPDLByteCodePass>(); } 136abfd1a8bSRiver Riddle } // namespace test 137abfd1a8bSRiver Riddle } // namespace mlir 138