// RUN: mlir-pdll %s -I %S -I %S/../../../../include -split-input-file -x cpp | FileCheck %s // Check that we generate a wrapper pattern for each PDL pattern. Also // add in a pattern awkwardly named the same as our generated patterns to // check that we handle overlap. // CHECK: struct GeneratedPDLLPattern0 : ::mlir::PDLPatternModule { // CHECK: template // CHECK: : ::mlir::PDLPatternModule(::mlir::parseSourceString<::mlir::ModuleOp>( // CHECK: R"mlir( // CHECK: pdl.pattern // CHECK: operation "test.op" // CHECK: )mlir", context), std::forward(configs)...) // CHECK: struct NamedPattern : ::mlir::PDLPatternModule { // CHECK: : ::mlir::PDLPatternModule(::mlir::parseSourceString<::mlir::ModuleOp>( // CHECK: R"mlir( // CHECK: pdl.pattern // CHECK: operation "test.op2" // CHECK: )mlir", context), std::forward(configs)...) // CHECK: struct GeneratedPDLLPattern1 : ::mlir::PDLPatternModule { // CHECK: struct GeneratedPDLLPattern2 : ::mlir::PDLPatternModule { // CHECK: : ::mlir::PDLPatternModule(::mlir::parseSourceString<::mlir::ModuleOp>( // CHECK: R"mlir( // CHECK: pdl.pattern // CHECK: operation "test.op3" // CHECK: )mlir", context), std::forward(configs)...) // CHECK: static void LLVM_ATTRIBUTE_UNUSED populateGeneratedPDLLPatterns(::mlir::RewritePatternSet &patterns, ConfigsT &&...configs) { // CHECK-NEXT: patterns.add(patterns.getContext(), configs...); // CHECK-NEXT: patterns.add(patterns.getContext(), configs...); // CHECK-NEXT: patterns.add(patterns.getContext(), configs...); // CHECK-NEXT: patterns.add(patterns.getContext(), configs...); // CHECK-NEXT: } Pattern => erase op; Pattern NamedPattern => erase op; Pattern GeneratedPDLLPattern1 => erase op<>; Pattern => erase op; // ----- // Check the generation of native constraints and rewrites. #include "include/ods.td" // CHECK: static ::mlir::LogicalResult TestCstPDLFn(::mlir::PatternRewriter &rewriter, // CHECK-SAME: ::mlir::Attribute attr, ::mlir::Operation * op, ::mlir::Type type, // CHECK-SAME: ::mlir::Value value, ::mlir::TypeRange typeRange, ::mlir::ValueRange valueRange) { // CHECK-NEXT: return success(); // CHECK: } // CHECK-NOT: TestUnusedCst // CHECK: static void TestRewritePDLFn(::mlir::PatternRewriter &rewriter, // CHECK-SAME: ::mlir::Attribute attr, ::mlir::Operation * op, ::mlir::Type type, // CHECK-SAME: ::mlir::Value value, ::mlir::TypeRange typeRange, ::mlir::ValueRange valueRange) { // CHECK: foo; // CHECK: } // CHECK: TestAttrInterface TestRewriteODSPDLFn(::mlir::PatternRewriter &rewriter, TestAttrInterface attr) { // CHECK: static ::mlir::Attribute TestRewriteSinglePDLFn(::mlir::PatternRewriter &rewriter) { // CHECK: std::tuple<::mlir::Attribute, ::mlir::Type> TestRewriteTuplePDLFn(::mlir::PatternRewriter &rewriter) { // CHECK-NOT: TestUnusedRewrite // CHECK: struct TestCstAndRewrite : ::mlir::PDLPatternModule { // CHECK: registerConstraintFunction("TestCst", TestCstPDLFn); // CHECK: registerRewriteFunction("TestRewrite", TestRewritePDLFn); Constraint TestCst(attr: Attr, op: Op, type: Type, value: Value, typeRange: TypeRange, valueRange: ValueRange) [{ return success(); }]; Constraint TestUnusedCst() [{ return success(); }]; Rewrite TestRewrite(attr: Attr, op: Op, type: Type, value: Value, typeRange: TypeRange, valueRange: ValueRange) [{ foo; }]; Rewrite TestRewriteODS(attr: TestAttrInterface) -> TestAttrInterface [{}]; Rewrite TestRewriteSingle() -> Attr [{}]; Rewrite TestRewriteTuple() -> (Attr, Type) [{}]; Rewrite TestUnusedRewrite(op: Op) [{}]; Pattern TestCstAndRewrite { let root = op<>(operand: Value, operands: ValueRange) -> (type: Type, types: TypeRange); TestCst(attr<"true">, root, type, operand, types, operands); rewrite root with { TestRewrite(attr<"true">, root, type, operand, types, operands); TestRewriteODS(attr<"true">); TestRewriteSingle(); TestRewriteTuple(); erase root; }; }