158 lines
5.4 KiB
Text
158 lines
5.4 KiB
Text
// 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<value>)
|
|
Rewrite TestRewrite(root: Op) -> ValueRange => root;
|
|
Pattern TestCallWithArgsAndReturn => replace root: Op with TestRewrite(op<test.op>);
|
|
|
|
// -----
|
|
|
|
// CHECK: pdl.pattern @TestExternalCall
|
|
// CHECK: %[[ROOT:.*]] = operation
|
|
// CHECK: rewrite %[[ROOT]]
|
|
// CHECK: %[[RESULTS:.*]] = apply_native_rewrite "TestRewrite"(%[[ROOT]] : !pdl.operation) : !pdl.range<value>
|
|
// CHECK: replace %[[ROOT]] with(%[[RESULTS]] : !pdl.range<value>)
|
|
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<value>)
|
|
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<my_dialect.unregistered_bar>;
|
|
let op = op<my_dialect.unregistered_foo>(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<value>
|
|
// CHECK: %[[RES3:.*]] = results 1 of %[[OP0]] -> !pdl.range<value>
|
|
// CHECK: operation(%[[RES]], %[[RES1]], %[[RES2]], %[[RES3]] : !pdl.value, !pdl.value, !pdl.range<value>, !pdl.range<value>)
|
|
Pattern OpResultMemberAccess {
|
|
let op: Op<test.with_results>;
|
|
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<test.first>;
|
|
let secondOp = op<test.second>(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<test.first>;
|
|
let secondOp = op<test.second>(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<value>
|
|
// CHECK: range %[[ARG]], %[[ARGS]] : !pdl.value, !pdl.range<value>
|
|
// CHECK: range : !pdl.range<type>
|
|
// CHECK: range %[[TYPE]], %[[TYPES]] : !pdl.type, !pdl.range<type>
|
|
Pattern RangeExpr {
|
|
replace op<>(arg: Value, args: ValueRange) -> (type: Type, types: TypeRange)
|
|
with op<test.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">);
|