// RUN: mlir-pdll %s -I %S -I %S/../../../../include -split-input-file -x mlir | FileCheck %s //===----------------------------------------------------------------------===// // AttributeExpr //===----------------------------------------------------------------------===// // CHECK: pdl.pattern @AttrExpr // CHECK: %[[ATTR:.*]] = attribute = 10 // CHECK: operation({{.*}}) {"attr" = %[[ATTR]]} Pattern AttrExpr => erase op<> { attr = attr<"10"> }; // ----- //===----------------------------------------------------------------------===// // CallExpr //===----------------------------------------------------------------------===// // CHECK: pdl.pattern @TestCallWithArgsAndReturn // CHECK: %[[ROOT:.*]] = operation // CHECK: rewrite %[[ROOT]] // CHECK: %[[REPL_OP:.*]] = operation "test.op" // CHECK: %[[RESULTS:.*]] = results of %[[REPL_OP]] // CHECK: replace %[[ROOT]] with(%[[RESULTS]] : !pdl.range) Rewrite TestRewrite(root: Op) -> ValueRange => root; Pattern TestCallWithArgsAndReturn => replace root: Op with TestRewrite(op); // ----- // CHECK: pdl.pattern @TestExternalCall // CHECK: %[[ROOT:.*]] = operation // CHECK: rewrite %[[ROOT]] // CHECK: %[[RESULTS:.*]] = apply_native_rewrite "TestRewrite"(%[[ROOT]] : !pdl.operation) : !pdl.range // CHECK: replace %[[ROOT]] with(%[[RESULTS]] : !pdl.range) Rewrite TestRewrite(op: Op) -> ValueRange; Pattern TestExternalCall => replace root: Op with TestRewrite(root); // ----- // CHECK: pdl.pattern @TestExternalNegatedCall // CHECK: %[[ROOT:.*]] = operation // CHECK: apply_native_constraint "TestConstraint"(%[[ROOT]] : !pdl.operation) {isNegated = true} // CHECK: rewrite %[[ROOT]] // CHECK: erase %[[ROOT]] Constraint TestConstraint(op: Op); Pattern TestExternalNegatedCall { let root = op : Op; not TestConstraint(root); erase root; } // ----- //===----------------------------------------------------------------------===// // MemberAccessExpr //===----------------------------------------------------------------------===// // Handle implicit "all" operation results access. // CHECK: pdl.pattern @OpAllResultMemberAccess // CHECK: %[[OP0:.*]] = operation // CHECK: %[[OP0_RES:.*]] = result 0 of %[[OP0]] // CHECK: %[[OP1:.*]] = operation // CHECK: %[[OP1_RES:.*]] = results of %[[OP1]] // CHECK: operation(%[[OP0_RES]], %[[OP1_RES]] : !pdl.value, !pdl.range) Pattern OpAllResultMemberAccess { let singleVar: Value = op<>; let rangeVar: ValueRange = op<>; erase op<>(singleVar, rangeVar); } // ----- // Handle result indexing on unregistered op. // CHECK: pdl.pattern @UnregisteredOpResultIndexing // CHECK: %[[BAR_OP:.*]] = operation "my_dialect.unregistered_bar" // CHECK: %[[BAR_RES:.*]] = result 0 of %[[BAR_OP]] // CHECK: operation "my_dialect.unregistered_foo"(%[[BAR_RES]] : !pdl.value) Pattern UnregisteredOpResultIndexing { let bar : Op; let op = op(bar.0); erase op; } // ----- // Handle implicit "named" operation results access. #include "include/ops.td" // CHECK: pdl.pattern @OpResultMemberAccess // CHECK: %[[OP0:.*]] = operation // CHECK: %[[RES:.*]] = results 0 of %[[OP0]] -> !pdl.value // CHECK: %[[RES1:.*]] = results 0 of %[[OP0]] -> !pdl.value // CHECK: %[[RES2:.*]] = results 1 of %[[OP0]] -> !pdl.range // CHECK: %[[RES3:.*]] = results 1 of %[[OP0]] -> !pdl.range // CHECK: operation(%[[RES]], %[[RES1]], %[[RES2]], %[[RES3]] : !pdl.value, !pdl.value, !pdl.range, !pdl.range) Pattern OpResultMemberAccess { let op: Op; erase op<>(op.0, op.result, op.1, op.var_result); } // ----- // CHECK: pdl.pattern @TupleMemberAccessNumber // CHECK: %[[FIRST:.*]] = operation "test.first" // CHECK: %[[SECOND:.*]] = operation "test.second" // CHECK: rewrite %[[FIRST]] { // CHECK: replace %[[FIRST]] with %[[SECOND]] Pattern TupleMemberAccessNumber { let firstOp = op; let secondOp = op(firstOp); let tuple = (firstOp, secondOp); replace tuple.0 with tuple.1; } // ----- // CHECK: pdl.pattern @TupleMemberAccessName // CHECK: %[[FIRST:.*]] = operation "test.first" // CHECK: %[[SECOND:.*]] = operation "test.second" // CHECK: rewrite %[[FIRST]] { // CHECK: replace %[[FIRST]] with %[[SECOND]] Pattern TupleMemberAccessName { let firstOp = op; let secondOp = op(firstOp); let tuple = (first = firstOp, second = secondOp); replace tuple.first with tuple.second; } // ----- //===----------------------------------------------------------------------===// // RangeExpr //===----------------------------------------------------------------------===// // CHECK: pdl.pattern @RangeExpr // CHECK: %[[ARG:.*]] = operand // CHECK: %[[ARGS:.*]] = operands // CHECK: %[[TYPE:.*]] = type // CHECK: %[[TYPES:.*]] = types // CHECK: range : !pdl.range // CHECK: range %[[ARG]], %[[ARGS]] : !pdl.value, !pdl.range // CHECK: range : !pdl.range // CHECK: range %[[TYPE]], %[[TYPES]] : !pdl.type, !pdl.range Pattern RangeExpr { replace op<>(arg: Value, args: ValueRange) -> (type: Type, types: TypeRange) with op((), (arg, args)) -> ((), (type, types)); } // ----- //===----------------------------------------------------------------------===// // TypeExpr //===----------------------------------------------------------------------===// // CHECK: pdl.pattern @TypeExpr // CHECK: %[[TYPE:.*]] = type : i32 // CHECK: operation({{.*}}) -> (%[[TYPE]] : !pdl.type) Pattern TypeExpr => erase op<> -> (type<"i32">);