Changes transform.foreach's interface to take multiple arguments, e.g.
transform.foreach %ops1, %ops2, %params : ... { ^bb0(%op1, %op2,
%param): BODY } The semantics are that the payloads for these handles
get iterated over as if the payloads have been zipped-up together - BODY
gets executed once for each such tuple. The documentation explains that
this implementation requires that the payloads have the same length.
This change also enables the target argument(s) to be any op/value/param
handle.
The added test cases demonstrate some use cases for this change.
2601 lines
97 KiB
MLIR
2601 lines
97 KiB
MLIR
// RUN: mlir-opt %s --transform-interpreter -allow-unregistered-dialect --split-input-file --verify-diagnostics | FileCheck %s
|
|
|
|
// UNSUPPORTED: target=aarch64-pc-windows-msvc
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-remark @below {{applying transformation}}
|
|
transform.test_transform_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.test_produce_self_handle_or_forward_operand { foo = "bar" } : () -> !transform.any_op
|
|
// expected-remark @below {{succeeded}}
|
|
transform.test_consume_operand_of_op_kind_or_fail %0, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.test_produce_self_handle_or_forward_operand { foo = "bar" } : () -> !transform.any_op
|
|
// expected-error @below {{expected the operand to be associated a payload op of kind transform.sequence got transform.test_produce_self_handle_or_forward_operand}}
|
|
transform.test_consume_operand_of_op_kind_or_fail %0, "transform.sequence" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// It is okay to have multiple handles to the same payload op as long
|
|
// as only one of them is consumed. The expensive checks mode is necessary
|
|
// to detect double-consumption.
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.test_produce_self_handle_or_forward_operand { foo = "bar" } : () -> !transform.any_op
|
|
%1 = transform.test_copy_payload %0 : (!transform.any_op) -> !transform.any_op
|
|
// expected-remark @below {{succeeded}}
|
|
transform.test_consume_operand_of_op_kind_or_fail %0, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
// expected-remark @below {{applying transformation "a"}}
|
|
test_transform_op "a"
|
|
// expected-remark @below {{applying transformation "b"}}
|
|
test_transform_op "b"
|
|
// expected-remark @below {{applying transformation "c"}}
|
|
test_transform_op "c"
|
|
}
|
|
// expected-remark @below {{applying transformation "d"}}
|
|
transform.test_transform_op "d"
|
|
// expected-remark @below {{applying transformation "e"}}
|
|
transform.test_transform_op "e"
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op
|
|
transform.sequence %0 : !transform.any_op failures(propagate) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
// expected-remark @below {{succeeded}}
|
|
test_consume_operand_of_op_kind_or_fail %arg1, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.sequence %arg0 : !transform.any_op -> !transform.any_op failures(propagate) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
%1 = test_produce_self_handle_or_forward_operand : () -> !transform.any_op
|
|
yield %1 : !transform.any_op
|
|
}
|
|
// expected-remark @below {{succeeded}}
|
|
transform.test_consume_operand_of_op_kind_or_fail %0, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// expected-remark @below {{parent function}}
|
|
func.func @foo() {
|
|
%0 = arith.constant 0 : i32
|
|
return
|
|
}
|
|
|
|
// expected-remark @below {{parent function}}
|
|
func.func @bar() {
|
|
%0 = arith.constant 0 : i32
|
|
%1 = arith.constant 1 : i32
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @const : benefit(1) {
|
|
%r = pdl.types
|
|
%0 = pdl.operation "arith.constant" -> (%r : !pdl.range<type>)
|
|
pdl.rewrite %0 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb1(%arg1: !transform.any_op):
|
|
%f = pdl_match @const in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%m = get_parent_op %f {isolated_from_above} : (!transform.any_op) -> !transform.any_op
|
|
transform.debug.emit_remark_at %m, "parent function" : !transform.any_op
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @test_get_nth_parent() {
|
|
"test.foo"() ({
|
|
// expected-remark @below{{2nd parent}}
|
|
"test.foo"() ({
|
|
"test.qux"() ({
|
|
// expected-remark @below{{1st parent}}
|
|
"test.foo"() ({
|
|
"test.bar"() : () -> ()
|
|
}) : () -> ()
|
|
}) : () -> ()
|
|
}) : () -> ()
|
|
}) : () -> ()
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%f = transform.structured.match ops{["test.bar"]} in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
%parent = transform.get_parent_op %f {nth_parent = 1, op_name = "test.foo"} : (!transform.any_op) -> !transform.any_op
|
|
transform.debug.emit_remark_at %parent, "1st parent" : !transform.any_op
|
|
%parent2 = transform.get_parent_op %f {nth_parent = 2, op_name = "test.foo"} : (!transform.any_op) -> !transform.any_op
|
|
transform.debug.emit_remark_at %parent2, "2nd parent" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @foo() {
|
|
%0 = arith.constant 0 : i32
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @match_func : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "func.func"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb1(%arg1: !transform.any_op):
|
|
// This is necessary to run the transformation on something other than the
|
|
// top-level module, "alternatives" cannot be run on that.
|
|
%0 = pdl_match @match_func in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
transform.alternatives %0 : !transform.any_op {
|
|
^bb2(%arg2: !transform.any_op):
|
|
%1 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op
|
|
// This operation fails, which triggers the next alternative without
|
|
// reporting the error.
|
|
transform.test_consume_operand_of_op_kind_or_fail %1, "transform.sequence" : !transform.any_op
|
|
}, {
|
|
^bb2(%arg2: !transform.any_op):
|
|
%1 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op
|
|
// expected-remark @below {{succeeded}}
|
|
transform.test_consume_operand_of_op_kind_or_fail %1, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op
|
|
}
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func private @bar()
|
|
|
|
func.func @foo() {
|
|
call @bar() : () -> ()
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @match_call : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "func.call"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb1(%arg1: !transform.any_op):
|
|
%0 = pdl_match @match_call in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%1 = get_parent_op %0 {isolated_from_above} : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{all alternatives failed}}
|
|
transform.alternatives %1 : !transform.any_op {
|
|
^bb2(%arg2: !transform.any_op):
|
|
%2 = transform.pdl_match @match_call in %arg2 : (!transform.any_op) -> !transform.any_op
|
|
// expected-remark @below {{applying}}
|
|
transform.test_emit_remark_and_erase_operand %2, "applying" {fail_after_erase} : !transform.any_op
|
|
}
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func private @bar()
|
|
|
|
func.func @foo() {
|
|
// expected-remark @below {{still here}}
|
|
call @bar() : () -> ()
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @match_call : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "func.call"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb1(%arg1: !transform.any_op):
|
|
%0 = pdl_match @match_call in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%1 = get_parent_op %0 {isolated_from_above} : (!transform.any_op) -> !transform.any_op
|
|
transform.alternatives %1 : !transform.any_op {
|
|
^bb2(%arg2: !transform.any_op):
|
|
%2 = transform.pdl_match @match_call in %arg2 : (!transform.any_op) -> !transform.any_op
|
|
// expected-remark @below {{applying}}
|
|
transform.test_emit_remark_and_erase_operand %2, "applying" {fail_after_erase} : !transform.any_op
|
|
}, {
|
|
^bb2(%arg2: !transform.any_op):
|
|
%2 = transform.pdl_match @match_call in %arg2 : (!transform.any_op) -> !transform.any_op
|
|
transform.debug.emit_remark_at %2, "still here" : !transform.any_op
|
|
// This alternative succeeds.
|
|
}, {
|
|
^bb2(%arg2: !transform.any_op):
|
|
// This alternative is never run, so we must not have a remark here.
|
|
%2 = transform.pdl_match @match_call in %arg2 : (!transform.any_op) -> !transform.any_op
|
|
transform.test_emit_remark_and_erase_operand %2, "should not happen" {fail_after_erase} : !transform.any_op
|
|
}
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func private @bar()
|
|
|
|
func.func @erase_call() {
|
|
call @bar() : () -> ()
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @match_call : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "func.call"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb1(%arg1: !transform.any_op):
|
|
%0 = pdl_match @match_call in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%1 = get_parent_op %0 {isolated_from_above} : (!transform.any_op) -> !transform.any_op
|
|
transform.alternatives %1 : !transform.any_op {
|
|
^bb2(%arg2: !transform.any_op):
|
|
%2 = transform.pdl_match @match_call in %arg2 : (!transform.any_op) -> !transform.any_op
|
|
// expected-remark @below {{applying}}
|
|
transform.test_emit_remark_and_erase_operand %2, "applying" {fail_after_erase} : !transform.any_op
|
|
}, {
|
|
^bb2(%arg2: !transform.any_op):
|
|
%2 = transform.pdl_match @match_call in %arg2 : (!transform.any_op) -> !transform.any_op
|
|
// expected-remark @below {{applying second time}}
|
|
transform.test_emit_remark_and_erase_operand %2, "applying second time" : !transform.any_op
|
|
}
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func private @bar()
|
|
|
|
func.func @foo() {
|
|
call @bar() : () -> ()
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @match_call : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "func.call"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb1(%arg1: !transform.any_op):
|
|
%0 = pdl_match @match_call in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%1 = get_parent_op %0 {isolated_from_above} : (!transform.any_op) -> !transform.any_op
|
|
%2 = transform.alternatives %1 : !transform.any_op -> !transform.any_op {
|
|
^bb2(%arg2: !transform.any_op):
|
|
%3 = transform.pdl_match @match_call in %arg2 : (!transform.any_op) -> !transform.any_op
|
|
// expected-remark @below {{applying}}
|
|
transform.test_emit_remark_and_erase_operand %3, "applying" {fail_after_erase} : !transform.any_op
|
|
%4 = transform.test_produce_self_handle_or_forward_operand %3 : (!transform.any_op) -> !transform.any_op
|
|
transform.yield %4 : !transform.any_op
|
|
}, {
|
|
^bb2(%arg2: !transform.any_op):
|
|
%4 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op
|
|
transform.yield %4 : !transform.any_op
|
|
}
|
|
// The first alternative failed, so the returned value is taken from the
|
|
// second alternative, associated test_produce_self_handle_or_forward_operand rather
|
|
// than pdl_match.
|
|
// expected-remark @below {{succeeded}}
|
|
transform.test_consume_operand_of_op_kind_or_fail %2, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// expected-note @below {{scope}}
|
|
module attributes {transform.with_named_sequence} {
|
|
func.func @foo() {
|
|
%0 = arith.constant 0 : i32
|
|
return
|
|
}
|
|
|
|
func.func @bar() {
|
|
%0 = arith.constant 0 : i32
|
|
%1 = arith.constant 1 : i32
|
|
return
|
|
}
|
|
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
// expected-error @below {{scope must not contain the transforms being applied}}
|
|
transform.alternatives %arg1 : !transform.any_op {
|
|
^bb2(%arg2: !transform.any_op):
|
|
%0 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op
|
|
transform.test_consume_operand_of_op_kind_or_fail %0, "transform.sequence" : !transform.any_op
|
|
}, {
|
|
^bb2(%arg2: !transform.any_op):
|
|
%0 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op
|
|
transform.test_consume_operand_of_op_kind_or_fail %0, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @foo(%arg0: index, %arg1: index, %arg2: index) {
|
|
// expected-note @below {{scope}}
|
|
scf.for %i = %arg0 to %arg1 step %arg2 {
|
|
%0 = arith.constant 0 : i32
|
|
}
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @match_const : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "arith.constant"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
|
|
sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb1(%arg1: !transform.any_op):
|
|
%0 = transform.pdl_match @match_const in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{only isolated-from-above ops can be alternative scopes}}
|
|
alternatives %1 : !transform.any_op {
|
|
^bb2(%arg2: !transform.any_op):
|
|
}
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
// -----
|
|
|
|
func.func @foo() {
|
|
// expected-note @below {{when applied to this op}}
|
|
"op" () : () -> ()
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @some : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
%0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{application of transform.test_wrong_number_of_results expected to produce 3 results (actually produced 1).}}
|
|
// expected-note @below {{if you need variadic results, consider a generic `apply` instead of the specialized `applyToOne`.}}
|
|
transform.test_wrong_number_of_results %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @foo() {
|
|
"op" () : () -> ()
|
|
// expected-note @below {{when applied to this op}}
|
|
"op" () : () -> ()
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @some : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
%0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{application of transform.test_wrong_number_of_multi_results expected to produce 1 results (actually produced 0)}}
|
|
// expected-note @below {{if you need variadic results, consider a generic `apply` instead of the specialized `applyToOne`.}}
|
|
transform.test_wrong_number_of_multi_results %0 : (!transform.any_op) -> (!transform.any_op)
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @foo() {
|
|
"op" () : () -> ()
|
|
"op" () : () -> ()
|
|
"op" () : () -> ()
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @some : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
%0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// Transform matches 3 ops and produces 2 results.
|
|
%1:2 = transform.test_correct_number_of_multi_results %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @foo() {
|
|
"wrong_op_name" () : () -> ()
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @some : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
%0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// Transform fails to match any but still produces 2 results.
|
|
%1:2 = transform.test_correct_number_of_multi_results %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// This should not fail.
|
|
|
|
func.func @foo() {
|
|
"op" () : () -> ()
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @some : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
%0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
transform.test_mixed_null_and_non_null_results %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Expecting to match all operations by merging the handles that matched addi
|
|
// and subi separately.
|
|
func.func @foo(%arg0: index) {
|
|
// expected-remark @below {{matched}}
|
|
%0 = arith.addi %arg0, %arg0 : index
|
|
// expected-remark @below {{matched}}
|
|
%1 = arith.subi %arg0, %arg0 : index
|
|
// expected-remark @below {{matched}}
|
|
%2 = arith.addi %0, %1 : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @addi : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "arith.addi"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
pdl.pattern @subi : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "arith.subi"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
%0 = pdl_match @addi in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%1 = pdl_match @subi in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%2 = merge_handles %0, %1 : !transform.any_op
|
|
transform.debug.emit_remark_at %2, "matched" : !transform.any_op
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @foo(%arg0: index) {
|
|
%0 = arith.addi %arg0, %arg0 : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @addi : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "arith.addi"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
%0 = pdl_match @addi in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%1 = pdl_match @addi in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%2 = merge_handles deduplicate %0, %1 : !transform.any_op
|
|
%3 = num_associations %2 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below {{1}}
|
|
transform.debug.emit_param_as_remark %3 : !transform.param<i64>
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @foo() {
|
|
"op" () { target_me } : () -> ()
|
|
// expected-note @below {{when applied to this op}}
|
|
"op" () : () -> ()
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @some : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
%0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{failed to apply}}
|
|
transform.test_mixed_success_and_silenceable %0 : !transform.any_op
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @foo() {
|
|
"op" () : () -> ()
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @some : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(suppress) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
%0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// Not expecting error here because we are suppressing it.
|
|
// expected-remark @below {{foo}}
|
|
test_emit_remark_and_erase_operand %0, "foo" {fail_after_erase} : !transform.any_op
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @foo() {
|
|
"op" () : () -> ()
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @some : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
%0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{silenceable error}}
|
|
// expected-remark @below {{foo}}
|
|
test_emit_remark_and_erase_operand %0, "foo" {fail_after_erase} : !transform.any_op
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
func.func private @foo()
|
|
func.func private @bar()
|
|
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @func : benefit(1) {
|
|
%0 = pdl.operands
|
|
%1 = pdl.types
|
|
%2 = pdl.operation "func.func"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
|
|
pdl.rewrite %2 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
%0 = pdl_match @func in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%1 = replicate num(%0) %arg1 : !transform.any_op, !transform.any_op
|
|
%p = num_associations %1 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below {{2}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
%2 = replicate num(%0) %1 : !transform.any_op, !transform.any_op
|
|
%p2 = num_associations %2 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below {{4}}
|
|
transform.debug.emit_param_as_remark %p2 : !transform.param<i64>
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @bar() {
|
|
// expected-remark @below {{transform applied}}
|
|
%0 = arith.constant 0 : i32
|
|
// expected-remark @below {{transform applied}}
|
|
%1 = arith.constant 1 : i32
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @const : benefit(1) {
|
|
%r = pdl.types
|
|
%0 = pdl.operation "arith.constant" -> (%r : !pdl.range<type>)
|
|
pdl.rewrite %0 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb1(%arg1: !transform.any_op):
|
|
%f = pdl_match @const in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
transform.foreach %f : !transform.any_op {
|
|
^bb2(%arg2: !transform.any_op):
|
|
%p = transform.num_associations %arg2 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below {{1}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
transform.debug.emit_remark_at %arg2, "transform applied" : !transform.any_op
|
|
}
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes { transform.with_named_sequence } {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
|
|
%0 = transform.structured.match ops{["linalg.matmul"]} in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
%results, %types = transform.foreach %0 : !transform.any_op -> !transform.any_value, !transform.any_param {
|
|
^bb0(%op0 : !transform.any_op):
|
|
%result = transform.get_result %op0[0] : (!transform.any_op) -> !transform.any_value
|
|
%type = transform.get_type elemental %result : (!transform.any_value) -> !transform.any_param
|
|
transform.yield %result, %type : !transform.any_value, !transform.any_param
|
|
}
|
|
transform.debug.emit_remark_at %results, "result selected" : !transform.any_value
|
|
transform.debug.emit_param_as_remark %types, "elemental types" at %0 : !transform.any_param, !transform.any_op
|
|
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
func.func @payload(%lhs: tensor<10x20xf16>,
|
|
%rhs: tensor<20x15xf32>) -> (tensor<10x15xf64>, tensor<10x15xf32>) {
|
|
%cst64 = arith.constant 0.0 : f64
|
|
%empty64 = tensor.empty() : tensor<10x15xf64>
|
|
%fill64 = linalg.fill ins(%cst64 : f64) outs(%empty64 : tensor<10x15xf64>) -> tensor<10x15xf64>
|
|
// expected-remark @below {{result selected}}
|
|
// expected-note @below {{value handle points to an op result #0}}
|
|
// expected-remark @below {{elemental types f64, f32}}
|
|
%result64 = linalg.matmul ins(%lhs, %rhs: tensor<10x20xf16>, tensor<20x15xf32>)
|
|
outs(%fill64: tensor<10x15xf64>) -> tensor<10x15xf64>
|
|
|
|
%cst32 = arith.constant 0.0 : f32
|
|
%empty32 = tensor.empty() : tensor<10x15xf32>
|
|
%fill32 = linalg.fill ins(%cst32 : f32) outs(%empty32 : tensor<10x15xf32>) -> tensor<10x15xf32>
|
|
// expected-remark @below {{result selected}}
|
|
// expected-note @below {{value handle points to an op result #0}}
|
|
// expected-remark @below {{elemental types f64, f32}}
|
|
%result32 = linalg.matmul ins(%lhs, %rhs: tensor<10x20xf16>, tensor<20x15xf32>)
|
|
outs(%fill32: tensor<10x15xf32>) -> tensor<10x15xf32>
|
|
|
|
return %result64, %result32 : tensor<10x15xf64>, tensor<10x15xf32>
|
|
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @two_const_ops() {
|
|
%0 = arith.constant 0 : index
|
|
%1 = arith.constant 1 : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%two_ops = transform.structured.match ops{["arith.constant"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%one_param = transform.param.constant 1 : i32 -> !transform.test_dialect_param
|
|
// expected-error @below {{prior targets' payload size (2) differs from payload size (1) of target}}
|
|
transform.foreach %two_ops, %one_param : !transform.any_op, !transform.test_dialect_param {
|
|
^bb2(%op: !transform.any_op, %param: !transform.test_dialect_param):
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @one_const_op() {
|
|
%0 = arith.constant 0 : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%one_op = transform.structured.match ops{["arith.constant"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%one_val = transform.test_produce_value_handle_to_self_operand %one_op : (!transform.any_op) -> !transform.any_value
|
|
%param_one = transform.param.constant 1 : i32 -> !transform.test_dialect_param
|
|
%param_two = transform.param.constant 2 : i32 -> !transform.test_dialect_param
|
|
%two_params = transform.merge_handles %param_one, %param_two : !transform.test_dialect_param
|
|
|
|
// expected-error @below {{prior targets' payload size (1) differs from payload size (2) of target}}
|
|
transform.foreach %one_val, %one_op, %two_params : !transform.any_value, !transform.any_op, !transform.test_dialect_param {
|
|
^bb2(%val: !transform.any_value, %op: !transform.any_op, %param: !transform.test_dialect_param):
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func @consume_in_foreach()
|
|
// CHECK-NEXT: return
|
|
func.func @consume_in_foreach() {
|
|
%0 = arith.constant 0 : index
|
|
%1 = arith.constant 1 : index
|
|
%2 = arith.constant 2 : index
|
|
%3 = arith.constant 3 : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%f = transform.structured.match ops{["arith.constant"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
transform.foreach %f : !transform.any_op {
|
|
^bb2(%arg2: !transform.any_op):
|
|
// expected-remark @below {{erasing}}
|
|
transform.test_emit_remark_and_erase_operand %arg2, "erasing" : !transform.any_op
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @bar() {
|
|
scf.execute_region {
|
|
// expected-remark @below {{transform applied}}
|
|
%0 = arith.constant 0 : i32
|
|
scf.yield
|
|
}
|
|
|
|
scf.execute_region {
|
|
// expected-remark @below {{transform applied}}
|
|
%1 = arith.constant 1 : i32
|
|
// expected-remark @below {{transform applied}}
|
|
%2 = arith.constant 2 : i32
|
|
scf.yield
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @const : benefit(1) {
|
|
%r = pdl.types
|
|
%0 = pdl.operation "arith.constant" -> (%r : !pdl.range<type>)
|
|
pdl.rewrite %0 with "transform.dialect"
|
|
}
|
|
|
|
pdl.pattern @execute_region : benefit(1) {
|
|
%r = pdl.types
|
|
%0 = pdl.operation "scf.execute_region" -> (%r : !pdl.range<type>)
|
|
pdl.rewrite %0 with "transform.dialect"
|
|
}
|
|
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb1(%arg1: !transform.any_op):
|
|
%f = pdl_match @execute_region in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%results = transform.foreach %f : !transform.any_op -> !transform.any_op {
|
|
^bb2(%arg2: !transform.any_op):
|
|
%g = transform.pdl_match @const in %arg2 : (!transform.any_op) -> !transform.any_op
|
|
transform.yield %g : !transform.any_op
|
|
}
|
|
|
|
%p = transform.num_associations %results : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below {{3}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
transform.debug.emit_remark_at %results, "transform applied" : !transform.any_op
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @get_parent_for_op_no_loop(%arg0: index, %arg1: index) {
|
|
// expected-remark @below {{found muli}}
|
|
%0 = arith.muli %arg0, %arg1 : index
|
|
arith.addi %0, %arg1 : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%muli = transform.get_producer_of_operand %addi[0] : (!transform.any_op) -> !transform.any_op
|
|
transform.debug.emit_remark_at %muli, "found muli" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @get_parent_for_op_no_loop(%arg0: index, %arg1: index) {
|
|
// expected-note @below {{target op}}
|
|
%0 = arith.muli %arg0, %arg1 : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%muli = transform.structured.match ops{["arith.muli"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{could not find a producer for operand number: 0 of}}
|
|
%bbarg = transform.get_producer_of_operand %muli[0] : (!transform.any_op) -> !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @get_consumer(%arg0: index, %arg1: index) {
|
|
%0 = arith.muli %arg0, %arg1 : index
|
|
// expected-remark @below {{found addi}}
|
|
arith.addi %0, %arg1 : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%muli = transform.structured.match ops{["arith.muli"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%addi = transform.get_consumers_of_result %muli[0] : (!transform.any_op) -> !transform.any_op
|
|
transform.debug.emit_remark_at %addi, "found addi" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @get_consumer_fail_1(%arg0: index, %arg1: index) {
|
|
%0 = arith.muli %arg0, %arg1 : index
|
|
%1 = arith.muli %arg0, %arg1 : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%muli = transform.structured.match ops{["arith.muli"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{handle must be mapped to exactly one payload op}}
|
|
%bbarg = transform.get_consumers_of_result %muli[0] : (!transform.any_op) -> !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @get_consumer_fail_2(%arg0: index, %arg1: index) {
|
|
%0 = arith.muli %arg0, %arg1 : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%muli = transform.structured.match ops{["arith.muli"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{result number overflow}}
|
|
%bbarg = transform.get_consumers_of_result %muli[1] : (!transform.any_op) -> !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @split_handle(%a: index, %b: index, %c: index) {
|
|
%0 = arith.muli %a, %b : index
|
|
%1 = arith.muli %a, %c : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%fun: !transform.any_op) {
|
|
%muli = transform.structured.match ops{["arith.muli"]} in %fun : (!transform.any_op) -> !transform.any_op
|
|
%h:2 = transform.split_handle %muli : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
|
|
%p = transform.num_associations %h#0 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below {{1}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
%muli_2 = transform.structured.match ops{["arith.muli"]} in %fun : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{expected to contain 3 payload ops but it contains 2 payload ops}}
|
|
%h_2:3 = transform.split_handle %muli_2 : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @split_handle(%a: index, %b: index, %c: index) {
|
|
%0 = arith.muli %a, %b : index
|
|
%1 = arith.muli %a, %c : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.sequence %root : !transform.any_op failures(suppress) {
|
|
^bb1(%fun: !transform.any_op):
|
|
%muli = transform.structured.match ops{["arith.muli"]} in %fun : (!transform.any_op) -> !transform.any_op
|
|
%h:2 = split_handle %muli : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
|
|
%p = transform.num_associations %h#0 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below {{1}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
%muli_2 = transform.structured.match ops{["arith.muli"]} in %fun : (!transform.any_op) -> !transform.any_op
|
|
// Silenceable failure and all handles are now empty.
|
|
%h_2:3 = split_handle %muli_2 : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
|
|
%p2 = transform.num_associations %h_2#0 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below {{0}}
|
|
transform.debug.emit_param_as_remark %p2 : !transform.param<i64>
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @split_handle(%a: index, %b: index, %c: index) {
|
|
%0 = arith.muli %a, %b : index
|
|
%1 = arith.muli %a, %c : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%fun: !transform.any_op) {
|
|
%muli_2 = transform.structured.match ops{["arith.muli"]} in %fun : (!transform.any_op) -> !transform.any_op
|
|
// No error, last result handle is empty.
|
|
%h:3 = transform.split_handle %muli_2 {fail_on_payload_too_small = false} : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
|
|
%p = transform.num_associations %h#0 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below {{1}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
%p2 = transform.num_associations %h#1 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below {{1}}
|
|
transform.debug.emit_param_as_remark %p2 : !transform.param<i64>
|
|
%p3 = transform.num_associations %h#2 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below {{0}}
|
|
transform.debug.emit_param_as_remark %p3 : !transform.param<i64>
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @split_handle(%a: index, %b: index, %c: index) {
|
|
%0 = arith.muli %a, %b : index
|
|
%1 = arith.muli %a, %c : index
|
|
%2 = arith.muli %a, %c : index
|
|
%3 = arith.muli %a, %c : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%fun: !transform.any_op) {
|
|
%muli_2 = transform.structured.match ops{["arith.muli"]} in %fun : (!transform.any_op) -> !transform.any_op
|
|
%h:2 = transform.split_handle %muli_2 {overflow_result = 0} : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
|
|
%p = transform.num_associations %h#0 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below {{3}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
%p2 = transform.num_associations %h#1 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below {{1}}
|
|
transform.debug.emit_param_as_remark %p2 : !transform.param<i64>
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
"test.some_op"() : () -> ()
|
|
"other_dialect.other_op"() : () -> ()
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @some : benefit(1) {
|
|
%0 = pdl.operation "test.some_op"
|
|
pdl.rewrite %0 with "transform.dialect"
|
|
}
|
|
|
|
sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb1(%arg1: !transform.any_op):
|
|
%0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%2 = transform.cast %0 : !transform.any_op to !transform.test_dialect_op
|
|
transform.cast %2 : !transform.test_dialect_op to !transform.any_op
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
"test.some_op"() : () -> ()
|
|
"other_dialect.other_op"() : () -> ()
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @other : benefit(1) {
|
|
%0 = pdl.operation "other_dialect.other_op"
|
|
pdl.rewrite %0 with "transform.dialect"
|
|
}
|
|
|
|
sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb1(%arg1: !transform.any_op):
|
|
%0 = pdl_match @other in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{expected the payload operation to belong to the 'test' dialect}}
|
|
%2 = transform.cast %0 : !transform.any_op to !transform.test_dialect_op
|
|
transform.cast %2 : !transform.test_dialect_op to !transform.any_op
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
"test.some_op"() : () -> ()
|
|
"other_dialect.other_op"() : () -> ()
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @some : benefit(1) {
|
|
%0 = pdl.operation "test.some_op"
|
|
pdl.rewrite %0 with "transform.dialect"
|
|
}
|
|
|
|
sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb1(%arg1: !transform.any_op):
|
|
%0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%2 = transform.cast %0 : !transform.any_op to !transform.op<"test.some_op">
|
|
transform.cast %2 : !transform.op<"test.some_op"> to !transform.any_op
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
"test.some_op"() : () -> ()
|
|
// expected-note @below {{payload operation}}
|
|
"other_dialect.other_op"() : () -> ()
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
pdl.pattern @other : benefit(1) {
|
|
%0 = pdl.operation "other_dialect.other_op"
|
|
pdl.rewrite %0 with "transform.dialect"
|
|
}
|
|
|
|
sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb1(%arg1: !transform.any_op):
|
|
%0 = pdl_match @other in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{incompatible payload operation name}}
|
|
%2 = transform.cast %0 : !transform.any_op to !transform.op<"test.some_op">
|
|
transform.cast %2 : !transform.op<"test.some_op"> to !transform.any_op
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.with_pdl_patterns %root : !transform.any_op {
|
|
^bb0(%arg0: !transform.any_op):
|
|
transform.sequence %arg0 : !transform.any_op failures(propagate) {
|
|
^bb0(%arg1: !transform.any_op):
|
|
%0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// here, the handles nested under are {%root, %arg0, %arg1, %0}
|
|
// expected-remark @below {{4 handles nested under}}
|
|
transform.test_report_number_of_tracked_handles_nested_under %arg1 : !transform.any_op
|
|
// expected-remark @below {{erased}}
|
|
transform.test_emit_remark_and_erase_operand %0, "erased" : !transform.any_op
|
|
// here, the handles nested under are only {%root, %arg0, %arg1}
|
|
// expected-remark @below {{3 handles nested under}}
|
|
transform.test_report_number_of_tracked_handles_nested_under %arg1 : !transform.any_op
|
|
}
|
|
|
|
pdl.pattern @some : benefit(1) {
|
|
%0 = pdl.operation "test.some_op"
|
|
pdl.rewrite %0 with "transform.dialect"
|
|
}
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
"test.some_op"() : () -> ()
|
|
|
|
// -----
|
|
|
|
func.func @split_handle(%a: index, %b: index, %c: index) {
|
|
%0 = arith.muli %a, %b : index
|
|
%1 = arith.muli %a, %c : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.sequence %root : !transform.any_op -> !transform.any_op failures(propagate) {
|
|
^bb1(%fun: !transform.any_op):
|
|
%muli = transform.structured.match ops{["arith.muli"]} in %fun : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{expected to contain 3 payload ops but it contains 2 payload ops}}
|
|
%h_2:3 = split_handle %muli : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
|
|
/// Test that yield does not crash in the presence of silenceable error in
|
|
/// propagate mode.
|
|
yield %fun : !transform.any_op
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.sequence %root : !transform.any_op -> !transform.any_op failures(suppress) {
|
|
^bb0(%arg0: !transform.any_op):
|
|
%muli = transform.structured.match ops{["arith.muli"]} in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
// Edge case propagating empty handles in splitting.
|
|
%0:3 = split_handle %muli : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
|
|
// Test does not crash when accessing the empty handle.
|
|
yield %0#0 : !transform.any_op
|
|
}
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.test_produce_param (0 : i32) : !transform.test_dialect_param
|
|
// expected-remark @below {{0 : i32}}
|
|
transform.debug.emit_param_as_remark %0 : !transform.test_dialect_param
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-error @below {{expected the type of the parameter attribute ('i32') to match the parameter type ('i64')}}
|
|
transform.test_produce_param (0 : i32) : !transform.param<i64>
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.test_add_to_param 40
|
|
%1 = transform.test_add_to_param %0, 2
|
|
// expected-remark @below {{42 : i32}}
|
|
transform.debug.emit_param_as_remark %1 : !transform.test_dialect_param
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.structured.match ops{["func.func"]} in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
%1 = transform.test_produce_param_with_number_of_test_ops %0 : !transform.any_op
|
|
// expected-remark @below {{1 : i32, 3 : i32}}
|
|
transform.debug.emit_param_as_remark %1 : !transform.test_dialect_param
|
|
%2 = transform.test_add_to_param %1, 100
|
|
// expected-remark @below {{101 : i32, 103 : i32}}
|
|
transform.debug.emit_param_as_remark %2 : !transform.test_dialect_param
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
func.func private @one_test_op(%arg0: i32) {
|
|
"test.op_a"(%arg0) { attr = 0 : i32} : (i32) -> i32
|
|
return
|
|
}
|
|
|
|
func.func private @three_test_ops(%arg0: i32) {
|
|
"test.op_a"(%arg0) { attr = 0 : i32} : (i32) -> i32
|
|
"test.op_a"(%arg0) { attr = 0 : i32} : (i32) -> i32
|
|
"test.op_a"(%arg0) { attr = 0 : i32} : (i32) -> i32
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
// expected-note @below {{when applied to this op}}
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-error @below {{expected to produce an Operation * for result #0}}
|
|
transform.test_produce_transform_param_or_forward_operand %arg0
|
|
{ first_result_is_param }
|
|
: (!transform.any_op) -> (!transform.any_op, !transform.param<i64>)
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Should not fail.
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
transform.test_produce_transform_param_or_forward_operand %arg0
|
|
{ first_result_is_null }
|
|
: (!transform.any_op) -> (!transform.any_op, !transform.param<i64>)
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// expected-note @below {{when applied to this op}}
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-error @below {{expected to produce an Attribute for result #1}}
|
|
transform.test_produce_transform_param_or_forward_operand %arg0
|
|
{ second_result_is_handle }
|
|
: (!transform.any_op) -> (!transform.any_op, !transform.param<i64>)
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// expected-note @below {{when applied to this op}}
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-error @below {{expected to produce a Value for result #0}}
|
|
transform.test_produce_transform_param_or_forward_operand %arg0
|
|
{ second_result_is_handle }
|
|
: (!transform.any_op) -> (!transform.any_value, !transform.param<i64>)
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-error @below {{attempting to assign a null payload op to this transform value}}
|
|
%0 = transform.test_produce_null_payload : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-error @below {{attempting to assign a null parameter to this transform value}}
|
|
%0 = transform.test_produce_null_param : !transform.param<i64>
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-error @below {{attempting to assign a null payload value to this transform handle}}
|
|
%0 = transform.test_produce_null_value : !transform.any_value
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// expected-error @below {{could not find a nested named sequence with name: __transform_main}}
|
|
module {
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
// expected-remark @below {{value handle}}
|
|
// expected-note @below {{value handle points to a block argument #0 in block #0 in region #0}}
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.test_produce_value_handle_to_self_operand %arg0 : (!transform.any_op) -> !transform.any_value
|
|
transform.debug.emit_remark_at %0, "value handle" : !transform.any_value
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// expected-remark @below {{result handle}}
|
|
// expected-note @below {{value handle points to an op result #1}}
|
|
%0:2 = "test.get_two_results"() : () -> (i32, i32)
|
|
// expected-remark @below {{result handle}}
|
|
// expected-note @below {{value handle points to an op result #1}}
|
|
%1:3 = "test.get_three_results"() : () -> (i32, i32, f32)
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%2 = transform.structured.match ops{["test.get_two_results", "test.get_three_results"]} in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
%3 = transform.test_produce_value_handle_to_result %2, 1 : (!transform.any_op) -> !transform.any_value
|
|
transform.debug.emit_remark_at %3, "result handle" : !transform.any_value
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
"test.op_with_regions"() ({
|
|
^bb0:
|
|
"test.regon_terminator"() : () -> ()
|
|
}, {
|
|
^bb1:
|
|
"test.regon_terminator"() : () -> ()
|
|
// expected-remark @below {{block argument handle}}
|
|
// expected-note @below {{value handle points to a block argument #2 in block #1 in region #1}}
|
|
^bb2(%arg0: i32, %arg1: f64, %arg3: index):
|
|
"test.match_anchor"() : () -> ()
|
|
"test.regon_terminator"() : () -> ()
|
|
}) : () -> ()
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%2 = transform.structured.match ops{["test.match_anchor"]} in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
%3 = transform.test_produce_value_handle_to_argument_of_parent_block %2, 2 : (!transform.any_op) -> !transform.any_value
|
|
transform.debug.emit_remark_at %3, "block argument handle" : !transform.any_value
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-note @below {{value defined here with type '!transform.test_dialect_param'}}
|
|
%0 = transform.test_produce_param_with_number_of_test_ops %arg0 : !transform.any_op
|
|
// expected-error @below {{unexpectedly consumed a value that is not a handle as operand #0}}
|
|
transform.test_consume_operand %0 : !transform.test_dialect_param
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// expected-remark @below {{addi operand}}
|
|
// expected-note @below {{value handle points to a block argument #0}}
|
|
func.func @get_operand_of_op(%arg0: index, %arg1: index) -> index {
|
|
%r = arith.addi %arg0, %arg1 : index
|
|
return %r : index
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%operand = transform.get_operand %addi[0] : (!transform.any_op) -> !transform.any_value
|
|
transform.debug.emit_remark_at %operand, "addi operand" : !transform.any_value
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @get_out_of_bounds_operand_of_op(%arg0: index, %arg1: index) -> index {
|
|
// expected-note @below {{while considering positions of this payload operation}}
|
|
%r = arith.addi %arg0, %arg1 : index
|
|
return %r : index
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{position overflow 2 (updated from 2) for maximum 2}}
|
|
%operand = transform.get_operand %addi[2] : (!transform.any_op) -> !transform.any_value
|
|
transform.debug.emit_remark_at %operand, "addi operand" : !transform.any_value
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// expected-remark @below {{addi operand}}
|
|
// expected-note @below {{value handle points to a block argument #1}}
|
|
func.func @get_inverted_operand_of_op(%arg0: index, %arg1: index) -> index {
|
|
%r = arith.addi %arg0, %arg1 : index
|
|
return %r : index
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%operand = transform.get_operand %addi[except(0)] : (!transform.any_op) -> !transform.any_value
|
|
transform.debug.emit_remark_at %operand, "addi operand" : !transform.any_value
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @get_multiple_operands_of_op(%arg0: index, %arg1: index) -> index {
|
|
%r = arith.addi %arg0, %arg1 : index
|
|
return %r : index
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%addui = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%operands = transform.get_operand %addui[all] : (!transform.any_op) -> !transform.any_value
|
|
%p = transform.num_associations %operands : (!transform.any_value) -> !transform.param<i64>
|
|
// expected-remark @below {{2}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @get_result_of_op(%arg0: index, %arg1: index) -> index {
|
|
// expected-remark @below {{addi result}}
|
|
// expected-note @below {{value handle points to an op result #0}}
|
|
%r = arith.addi %arg0, %arg1 : index
|
|
return %r : index
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%result = transform.get_result %addi[0] : (!transform.any_op) -> !transform.any_value
|
|
transform.debug.emit_remark_at %result, "addi result" : !transform.any_value
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @get_out_of_bounds_result_of_op(%arg0: index, %arg1: index) -> index {
|
|
// expected-note @below {{while considering positions of this payload operation}}
|
|
%r = arith.addi %arg0, %arg1 : index
|
|
return %r : index
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// expected-error @below {{position overflow 1 (updated from 1) for maximum 1}}
|
|
%result = transform.get_result %addi[1] : (!transform.any_op) -> !transform.any_value
|
|
transform.debug.emit_remark_at %result, "addi result" : !transform.any_value
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @get_result_of_op(%arg0: index, %arg1: index) -> index {
|
|
// expected-remark @below {{matched}}
|
|
%r = arith.addi %arg0, %arg1 : index
|
|
return %r : index
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%result = transform.get_result %addi[0] : (!transform.any_op) -> !transform.any_value
|
|
%op = transform.get_defining_op %result : (!transform.any_value) -> !transform.any_op
|
|
transform.debug.emit_remark_at %op, "matched" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @get_multiple_result_of_op(%arg0: index, %arg1: index) -> (index, i1) {
|
|
%r, %b = arith.addui_extended %arg0, %arg1 : index, i1
|
|
return %r, %b : index, i1
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%addui = transform.structured.match ops{["arith.addui_extended"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%results = transform.get_result %addui[all] : (!transform.any_op) -> !transform.any_value
|
|
%p = transform.num_associations %results : (!transform.any_value) -> !transform.param<i64>
|
|
// expected-remark @below {{2}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// expected-note @below {{target value}}
|
|
func.func @get_result_of_op_bbarg(%arg0: index, %arg1: index) -> index {
|
|
%r = arith.addi %arg0, %arg1 : index
|
|
return %r : index
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%bbarg = transform.test_produce_value_handle_to_argument_of_parent_block %addi, 0 : (!transform.any_op) -> !transform.any_value
|
|
// expected-error @below {{cannot get defining op of block argument}}
|
|
%op = transform.get_defining_op %bbarg : (!transform.any_value) -> !transform.any_op
|
|
transform.debug.emit_remark_at %op, "matched" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module @named_inclusion attributes { transform.with_named_sequence } {
|
|
|
|
transform.named_sequence @foo(%arg0: !transform.any_op {transform.readonly}) -> () {
|
|
// expected-remark @below {{applying transformation "a"}}
|
|
transform.test_transform_op "a"
|
|
transform.yield
|
|
}
|
|
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
transform.include @foo failures(propagate) (%arg0) : (!transform.any_op) -> ()
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module @named_inclusion_in_named attributes { transform.with_named_sequence } {
|
|
|
|
transform.named_sequence @foo(%arg0: !transform.any_op {transform.readonly}) -> () {
|
|
// expected-remark @below {{applying transformation "a"}}
|
|
transform.test_transform_op "a"
|
|
transform.yield
|
|
}
|
|
|
|
transform.named_sequence @bar(%arg0: !transform.any_op {transform.readonly}) -> () {
|
|
// expected-remark @below {{applying transformation "b"}}
|
|
transform.test_transform_op "b"
|
|
transform.include @foo failures(propagate) (%arg0) : (!transform.any_op) -> ()
|
|
transform.yield
|
|
}
|
|
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
transform.include @bar failures(suppress) (%arg0) : (!transform.any_op) -> ()
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// expected-remark @below {{operation}}
|
|
module @named_operands attributes { transform.with_named_sequence } {
|
|
|
|
transform.named_sequence @foo(%arg0: !transform.any_op {transform.readonly},
|
|
%arg1: !transform.any_value {transform.readonly}) -> () {
|
|
transform.debug.emit_remark_at %arg0, "operation" : !transform.any_op
|
|
transform.debug.emit_remark_at %arg1, "value" : !transform.any_value
|
|
transform.yield
|
|
}
|
|
|
|
// expected-remark @below {{value}}
|
|
// expected-note @below {{value handle points to a block argument #0 in block #0 in region #0}}
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.test_produce_value_handle_to_self_operand %arg0 : (!transform.any_op) -> !transform.any_value
|
|
transform.include @foo failures(propagate) (%arg0, %0) : (!transform.any_op, !transform.any_value) -> ()
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// expected-remark @below {{operation}}
|
|
module @named_return attributes { transform.with_named_sequence } {
|
|
|
|
// expected-remark @below {{value}}
|
|
// expected-note @below {{value handle points to a block argument #0 in block #0 in region #0}}
|
|
transform.named_sequence @foo(%arg0: !transform.any_op {transform.readonly}) -> (!transform.any_op, !transform.any_value) {
|
|
%0 = transform.test_produce_value_handle_to_self_operand %arg0 : (!transform.any_op) -> !transform.any_value
|
|
transform.yield %arg0, %0 : !transform.any_op, !transform.any_value
|
|
}
|
|
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0:2 = transform.include @foo failures(propagate) (%arg0) : (!transform.any_op) -> (!transform.any_op, !transform.any_value)
|
|
transform.debug.emit_remark_at %0#0, "operation" : !transform.any_op
|
|
transform.debug.emit_remark_at %0#1, "value" : !transform.any_value
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes { transform.with_named_sequence } {
|
|
transform.named_sequence @match1(%current: !transform.any_op {transform.readonly}) -> (!transform.any_op) {
|
|
transform.test_succeed_if_operand_of_op_kind %current, "test.some_op" : !transform.any_op
|
|
transform.yield %current : !transform.any_op
|
|
}
|
|
|
|
transform.named_sequence @match2(%current: !transform.any_op {transform.readonly}) -> (!transform.any_op) {
|
|
transform.test_succeed_if_operand_of_op_kind %current, "func.func" : !transform.any_op
|
|
transform.yield %current : !transform.any_op
|
|
}
|
|
|
|
transform.named_sequence @action1(%current: !transform.any_op {transform.readonly}) {
|
|
transform.debug.emit_remark_at %current, "matched1" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
transform.named_sequence @action2(%current: !transform.any_op {transform.readonly}) {
|
|
transform.debug.emit_remark_at %current, "matched2" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.foreach_match in %root
|
|
@match1 -> @action1,
|
|
@match2 -> @action2
|
|
: (!transform.any_op) -> (!transform.any_op)
|
|
transform.yield
|
|
}
|
|
|
|
// expected-remark @below {{matched2}}
|
|
func.func private @foo()
|
|
// expected-remark @below {{matched2}}
|
|
func.func private @bar()
|
|
"test.testtest"() : () -> ()
|
|
// expected-remark @below {{matched1}}
|
|
"test.some_op"() : () -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes { transform.with_named_sequence } {
|
|
transform.named_sequence @match(!transform.any_op {transform.readonly})
|
|
transform.named_sequence @action()
|
|
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
// expected-error @below {{unresolved external symbol @match}}
|
|
transform.foreach_match in %root
|
|
@match -> @action : (!transform.any_op) -> !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes { transform.with_named_sequence } {
|
|
transform.named_sequence @match(%arg: !transform.any_op {transform.readonly}) {
|
|
transform.yield
|
|
}
|
|
transform.named_sequence @action()
|
|
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
// expected-error @below {{unresolved external symbol @action}}
|
|
transform.foreach_match in %root
|
|
@match -> @action : (!transform.any_op) -> !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes { transform.with_named_sequence } {
|
|
transform.named_sequence @match(%arg: !transform.any_op {transform.readonly}) {
|
|
// expected-error @below {{expected operations in the match part to implement MatchOpInterface}}
|
|
"test.unknown_op"() : () -> ()
|
|
transform.yield
|
|
}
|
|
transform.named_sequence @action() {
|
|
transform.yield
|
|
}
|
|
|
|
transform.named_sequence @__transform_main(%root: !transform.any_op) {
|
|
transform.foreach_match in %root
|
|
@match -> @action : (!transform.any_op) -> !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes { transform.with_named_sequence } {
|
|
transform.named_sequence @match_func(%arg0: !transform.any_op {transform.readonly})
|
|
-> !transform.any_op {
|
|
transform.match.operation_name %arg0 ["func.func"] : !transform.any_op
|
|
transform.yield %arg0 : !transform.any_op
|
|
}
|
|
|
|
transform.named_sequence @print_func(%arg0: !transform.any_op {transform.readonly}) {
|
|
transform.debug.emit_remark_at %arg0, "matched func" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
transform.foreach_match in %arg0 @match_func -> @print_func : (!transform.any_op) -> !transform.any_op
|
|
transform.yield
|
|
}
|
|
|
|
// expected-remark @below {{matched func}}
|
|
func.func @payload() {
|
|
return
|
|
}
|
|
|
|
// expected-remark @below {{matched func}}
|
|
func.func private @declaration()
|
|
|
|
"test.something_else"() : () -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes { transform.with_named_sequence } {
|
|
transform.named_sequence @eq_1(%arg0: !transform.any_op {transform.readonly})
|
|
-> !transform.any_op {
|
|
transform.match.operation_name %arg0 ["func.func"] : !transform.any_op
|
|
%0 = transform.test_produce_param_with_number_of_test_ops %arg0 : !transform.any_op
|
|
%1 = transform.param.constant 1 : i32 -> !transform.test_dialect_param
|
|
transform.match.param.cmpi eq %0, %1 : !transform.test_dialect_param
|
|
transform.debug.emit_remark_at %arg0, "matched == 1" : !transform.any_op
|
|
transform.yield %arg0 : !transform.any_op
|
|
}
|
|
|
|
transform.named_sequence @ne_0(%arg0: !transform.any_op {transform.readonly})
|
|
-> !transform.any_op {
|
|
transform.match.operation_name %arg0 ["func.func"] : !transform.any_op
|
|
%0 = transform.test_produce_param_with_number_of_test_ops %arg0 : !transform.any_op
|
|
%1 = transform.param.constant 0 : i32 -> !transform.test_dialect_param
|
|
transform.match.param.cmpi ne %0, %1 : !transform.test_dialect_param
|
|
transform.debug.emit_remark_at %arg0, "matched != 0" : !transform.any_op
|
|
transform.yield %arg0 : !transform.any_op
|
|
}
|
|
|
|
transform.named_sequence @gt_m1(%arg0: !transform.any_op {transform.readonly})
|
|
-> !transform.any_op {
|
|
transform.match.operation_name %arg0 ["func.func"] : !transform.any_op
|
|
%0 = transform.test_produce_param_with_number_of_test_ops %arg0 : !transform.any_op
|
|
%1 = transform.param.constant -1 : i32 -> !transform.test_dialect_param
|
|
transform.match.param.cmpi gt %0, %1 : !transform.test_dialect_param
|
|
transform.debug.emit_remark_at %arg0, "matched > -1" : !transform.any_op
|
|
transform.yield %arg0 : !transform.any_op
|
|
}
|
|
|
|
transform.named_sequence @ge_1(%arg0: !transform.any_op {transform.readonly})
|
|
-> !transform.any_op {
|
|
transform.match.operation_name %arg0 ["func.func"] : !transform.any_op
|
|
%0 = transform.test_produce_param_with_number_of_test_ops %arg0 : !transform.any_op
|
|
%1 = transform.param.constant 1 : i32 -> !transform.test_dialect_param
|
|
transform.match.param.cmpi ge %0, %1 : !transform.test_dialect_param
|
|
transform.debug.emit_remark_at %arg0, "matched >= 1" : !transform.any_op
|
|
transform.yield %arg0 : !transform.any_op
|
|
}
|
|
|
|
transform.named_sequence @lt_1(%arg0: !transform.any_op {transform.readonly})
|
|
-> !transform.any_op {
|
|
transform.match.operation_name %arg0 ["func.func"] : !transform.any_op
|
|
%0 = transform.test_produce_param_with_number_of_test_ops %arg0 : !transform.any_op
|
|
%1 = transform.param.constant 1 : i32 -> !transform.test_dialect_param
|
|
transform.match.param.cmpi lt %0, %1 : !transform.test_dialect_param
|
|
transform.debug.emit_remark_at %arg0, "matched < 1" : !transform.any_op
|
|
transform.yield %arg0 : !transform.any_op
|
|
}
|
|
|
|
transform.named_sequence @le_1(%arg0: !transform.any_op {transform.readonly})
|
|
-> !transform.any_op {
|
|
transform.match.operation_name %arg0 ["func.func"] : !transform.any_op
|
|
%0 = transform.test_produce_param_with_number_of_test_ops %arg0 : !transform.any_op
|
|
%1 = transform.param.constant 1 : i32 -> !transform.test_dialect_param
|
|
transform.match.param.cmpi le %0, %1 : !transform.test_dialect_param
|
|
transform.debug.emit_remark_at %arg0, "matched <= 1" : !transform.any_op
|
|
transform.yield %arg0 : !transform.any_op
|
|
}
|
|
|
|
transform.named_sequence @do_nothing(%arg0: !transform.any_op {transform.readonly}) {
|
|
transform.yield
|
|
}
|
|
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.foreach_match in %arg0 @eq_1 -> @do_nothing : (!transform.any_op) -> !transform.any_op
|
|
%1 = transform.foreach_match in %0 @ne_0 -> @do_nothing : (!transform.any_op) -> !transform.any_op
|
|
%2 = transform.foreach_match in %1 @gt_m1 -> @do_nothing : (!transform.any_op) -> !transform.any_op
|
|
%3 = transform.foreach_match in %2 @ge_1 -> @do_nothing : (!transform.any_op) -> !transform.any_op
|
|
%4 = transform.foreach_match in %3 @lt_1 -> @do_nothing : (!transform.any_op) -> !transform.any_op
|
|
%5 = transform.foreach_match in %4 @le_1 -> @do_nothing : (!transform.any_op) -> !transform.any_op
|
|
transform.yield
|
|
}
|
|
|
|
// expected-remark @below {{matched > -1}}
|
|
// expected-remark @below {{matched < 1}}
|
|
// expected-remark @below {{matched <= 1}}
|
|
func.func private @declaration()
|
|
|
|
// expected-remark @below {{matched == 1}}
|
|
// expected-remark @below {{matched != 0}}
|
|
// expected-remark @below {{matched > -1}}
|
|
// expected-remark @below {{matched >= 1}}
|
|
// expected-remark @below {{matched <= 1}}
|
|
func.func @definition() {
|
|
"test.something"() : () -> ()
|
|
return
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func @test_tracked_rewrite() {
|
|
// CHECK-NEXT: transform.test_dummy_payload_op {new_op} : () -> i1
|
|
// CHECK-NEXT: transform.test_dummy_payload_op {new_op} : () -> i1
|
|
// CHECK-NEXT: return
|
|
// CHECK-NEXT: }
|
|
func.func @test_tracked_rewrite() {
|
|
%0 = transform.test_dummy_payload_op {replace_me} : () -> (i1)
|
|
%1 = transform.test_dummy_payload_op {erase_me} : () -> (i1)
|
|
%2 = transform.test_dummy_payload_op {replace_me} : () -> (i1)
|
|
func.return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%0 = transform.structured.match ops{["transform.test_dummy_payload_op"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
// expected-remark @below {{2 iterations}}
|
|
transform.test_tracked_rewrite %0 : (!transform.any_op) -> ()
|
|
// One replacement op (test.drop_mapping) is dropped from the mapping.
|
|
%p = transform.num_associations %0 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below {{2}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Parameter deduplication happens by value
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%1 = transform.param.constant 1 -> !transform.param<i64>
|
|
%2 = transform.param.constant 1 -> !transform.param<i64>
|
|
%3 = transform.param.constant 2 -> !transform.param<i64>
|
|
%4 = transform.merge_handles %1, %2 { deduplicate } : !transform.param<i64>
|
|
%p = transform.num_associations %4 : (!transform.param<i64>) -> !transform.param<i64>
|
|
// expected-remark @below {{1}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
|
|
%5 = transform.merge_handles %1, %1 { deduplicate } : !transform.param<i64>
|
|
%p2 = transform.num_associations %5 : (!transform.param<i64>) -> !transform.param<i64>
|
|
// expected-remark @below {{1}}
|
|
transform.debug.emit_param_as_remark %p2 : !transform.param<i64>
|
|
|
|
%6 = transform.merge_handles %1, %3 { deduplicate } : !transform.param<i64>
|
|
%p3 = transform.num_associations %6 : (!transform.param<i64>) -> !transform.param<i64>
|
|
// expected-remark @below {{2}}
|
|
transform.debug.emit_param_as_remark %p3 : !transform.param<i64>
|
|
|
|
%7 = transform.merge_handles %1, %1, %2, %3 : !transform.param<i64>
|
|
%p4 = transform.num_associations %7 : (!transform.param<i64>) -> !transform.param<i64>
|
|
// expected-remark @below {{4}}
|
|
transform.debug.emit_param_as_remark %p4 : !transform.param<i64>
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
%0:3 = "test.get_two_results"() : () -> (i32, i32, f32)
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%1 = transform.structured.match ops{["test.get_two_results"]} in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
%2 = transform.test_produce_value_handle_to_result %1, 0 : (!transform.any_op) -> !transform.any_value
|
|
%3 = transform.test_produce_value_handle_to_result %1, 1 : (!transform.any_op) -> !transform.any_value
|
|
|
|
%4 = transform.merge_handles %2, %2 { deduplicate } : !transform.any_value
|
|
%p = transform.num_associations %4 : (!transform.any_value) -> !transform.param<i64>
|
|
// expected-remark @below {{1}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
|
|
%5 = transform.merge_handles %2, %3 { deduplicate } : !transform.any_value
|
|
%p2 = transform.num_associations %5 : (!transform.any_value) -> !transform.param<i64>
|
|
// expected-remark @below {{2}}
|
|
transform.debug.emit_param_as_remark %p2 : !transform.param<i64>
|
|
|
|
%6 = transform.test_produce_value_handle_to_result %1, 0 : (!transform.any_op) -> !transform.any_value
|
|
%7 = transform.merge_handles %2, %6 { deduplicate } : !transform.any_value
|
|
%p3 = transform.num_associations %6 : (!transform.any_value) -> !transform.param<i64>
|
|
// expected-remark @below {{1}}
|
|
transform.debug.emit_param_as_remark %p3 : !transform.param<i64>
|
|
|
|
%8 = transform.merge_handles %2, %2, %3, %4 : !transform.any_value
|
|
%p4 = transform.num_associations %8 : (!transform.any_value) -> !transform.param<i64>
|
|
// expected-remark @below {{4}}
|
|
transform.debug.emit_param_as_remark %p4 : !transform.param<i64>
|
|
transform.yield
|
|
}
|
|
}
|
|
// -----
|
|
|
|
// CHECK-LABEL: func @test_annotation()
|
|
// CHECK-NEXT: "test.annotate_me"()
|
|
// CHECK-SAME: any_attr = "example"
|
|
// CHECK-SAME: broadcast_attr = 2 : i64
|
|
// CHECK-SAME: new_attr = 1 : i32
|
|
// CHECK-SAME: unit_attr
|
|
// CHECK-NEXT: "test.annotate_me"()
|
|
// CHECK-SAME: any_attr = "example"
|
|
// CHECK-SAME: broadcast_attr = 2 : i64
|
|
// CHECK-SAME: existing_attr = "test"
|
|
// CHECK-SAME: new_attr = 1 : i32
|
|
// CHECK-SAME: unit_attr
|
|
// CHECK-NEXT: "test.annotate_me"()
|
|
// CHECK-SAME: any_attr = "example"
|
|
// CHECK-SAME: broadcast_attr = 2 : i64
|
|
// CHECK-SAME: new_attr = 1 : i32
|
|
// CHECK-SAME: unit_attr
|
|
func.func @test_annotation() {
|
|
%0 = "test.annotate_me"() : () -> (i1)
|
|
%1 = "test.annotate_me"() {existing_attr = "test"} : () -> (i1)
|
|
%2 = "test.annotate_me"() {new_attr = 0} : () -> (i1)
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.structured.match ops{["test.annotate_me"]} in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
%1 = transform.test_produce_param_with_number_of_test_ops %0 : !transform.any_op
|
|
transform.annotate %0 "new_attr" = %1 : !transform.any_op, !transform.test_dialect_param
|
|
|
|
%2 = transform.param.constant 2 -> !transform.param<i64>
|
|
transform.annotate %0 "broadcast_attr" = %2 : !transform.any_op, !transform.param<i64>
|
|
transform.annotate %0 "unit_attr" : !transform.any_op
|
|
|
|
%3 = transform.param.constant "example" -> !transform.any_param
|
|
transform.annotate %0 "any_attr" = %3 : !transform.any_op, !transform.any_param
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @notify_payload_op_replaced(%arg0: index, %arg1: index) {
|
|
%0 = arith.muli %arg0, %arg1 {original} : index
|
|
// expected-remark @below{{updated handle}}
|
|
%1 = arith.muli %arg0, %arg1 {replacement} : index
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%0 = transform.structured.match attributes{original} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%1 = transform.structured.match attributes{replacement} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
transform.test_notify_payload_op_replaced %0, %1 : (!transform.any_op, !transform.any_op) -> ()
|
|
transform.debug.emit_remark_at %0, "updated handle" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func @test_apply_cse()
|
|
// CHECK: %[[const:.*]] = arith.constant 0 : index
|
|
// CHECK: %[[ex1:.*]] = scf.execute_region -> index {
|
|
// CHECK: scf.yield %[[const]]
|
|
// CHECK: }
|
|
// CHECK: %[[ex2:.*]] = scf.execute_region -> index {
|
|
// CHECK: scf.yield %[[const]]
|
|
// CHECK: }
|
|
// CHECK: return %[[const]], %[[ex1]], %[[ex2]]
|
|
func.func @test_apply_cse() -> (index, index, index) {
|
|
// expected-remark @below{{eliminated 1}}
|
|
// expected-remark @below{{eliminated 2}}
|
|
%0 = arith.constant 0 : index
|
|
%1 = scf.execute_region -> index {
|
|
%2 = arith.constant 0 : index
|
|
scf.yield %2 : index
|
|
} {first}
|
|
%3 = scf.execute_region -> index {
|
|
%4 = arith.constant 0 : index
|
|
scf.yield %4 : index
|
|
} {second}
|
|
return %0, %1, %3 : index, index, index
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%0 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%first = transform.structured.match attributes{first} in %0 : (!transform.any_op) -> !transform.any_op
|
|
%elim_first = transform.structured.match ops{["arith.constant"]} in %first : (!transform.any_op) -> !transform.any_op
|
|
%second = transform.structured.match attributes{first} in %0 : (!transform.any_op) -> !transform.any_op
|
|
%elim_second = transform.structured.match ops{["arith.constant"]} in %first : (!transform.any_op) -> !transform.any_op
|
|
|
|
// There are 3 arith.constant ops.
|
|
%all = transform.structured.match ops{["arith.constant"]} in %0 : (!transform.any_op) -> !transform.any_op
|
|
%p = transform.num_associations %all : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below{{3}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
// "deduplicate" has no effect because these are 3 different ops.
|
|
%merged_before = transform.merge_handles deduplicate %all : !transform.any_op
|
|
%p2 = transform.num_associations %merged_before : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below{{3}}
|
|
transform.debug.emit_param_as_remark %p2 : !transform.param<i64>
|
|
|
|
// Apply CSE.
|
|
transform.apply_cse to %0 : !transform.any_op
|
|
|
|
// The handle is still mapped to 3 arith.constant ops.
|
|
%p3 = transform.num_associations %all : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below{{3}}
|
|
transform.debug.emit_param_as_remark %p3 : !transform.param<i64>
|
|
// But they are all the same op.
|
|
%merged_after = transform.merge_handles deduplicate %all : !transform.any_op
|
|
%p4 = transform.num_associations %merged_after : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below{{1}}
|
|
transform.debug.emit_param_as_remark %p4 : !transform.param<i64>
|
|
|
|
// The other handles were also updated.
|
|
transform.debug.emit_remark_at %elim_first, "eliminated 1" : !transform.any_op
|
|
%p5 = transform.num_associations %elim_first : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below{{1}}
|
|
transform.debug.emit_param_as_remark %p5 : !transform.param<i64>
|
|
transform.debug.emit_remark_at %elim_second, "eliminated 2" : !transform.any_op
|
|
%p6 = transform.num_associations %elim_second : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below{{1}}
|
|
transform.debug.emit_param_as_remark %p6 : !transform.param<i64>
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func @test_licm(
|
|
// CHECK: arith.muli
|
|
// CHECK: scf.for {{.*}} {
|
|
// CHECK: vector.print
|
|
// CHECK: }
|
|
func.func @test_licm(%arg0: index, %arg1: index, %arg2: index) {
|
|
scf.for %iv = %arg0 to %arg1 step %arg2 {
|
|
%0 = arith.muli %arg0, %arg1 : index
|
|
vector.print %0 : index
|
|
}
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%0 = transform.structured.match ops{["scf.for"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
transform.apply_licm to %0 : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// expected-note @below{{when applied to this op}}
|
|
module attributes {transform.with_named_sequence} {
|
|
func.func @test_licm_invalid() {
|
|
return
|
|
}
|
|
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
// expected-error @below{{transform applied to the wrong op kind}}
|
|
transform.apply_licm to %arg1 : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @get_parent_op() {
|
|
// expected-remark @below{{found test.foo parent}}
|
|
"test.foo"() ({
|
|
// expected-remark @below{{direct parent}}
|
|
"test.bar"() ({
|
|
"test.qux"() : () -> ()
|
|
"test.qux"() : () -> ()
|
|
}) : () -> ()
|
|
}) : () -> ()
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
|
|
%0 = transform.structured.match ops{["test.qux"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
|
|
// Get parent by name.
|
|
%1 = transform.get_parent_op %0 {op_name = "test.foo"} : (!transform.any_op) -> !transform.any_op
|
|
transform.debug.emit_remark_at %1, "found test.foo parent" : !transform.any_op
|
|
|
|
// Get immediate parent.
|
|
%2 = transform.get_parent_op %0 : (!transform.any_op) -> !transform.any_op
|
|
transform.debug.emit_remark_at %2, "direct parent" : !transform.any_op
|
|
%p = transform.num_associations %2 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below{{2}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
|
|
// Deduplicate results.
|
|
%3 = transform.structured.match ops{["test.qux"]} in %arg1 : (!transform.any_op) -> !transform.any_op
|
|
%4 = transform.get_parent_op %3 {deduplicate} : (!transform.any_op) -> !transform.any_op
|
|
%p2 = transform.num_associations %4 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below{{1}}
|
|
transform.debug.emit_param_as_remark %p2 : !transform.param<i64>
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
|
|
// -----
|
|
|
|
// expected-note @below {{target op}}
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-error @below{{could not find a parent op that matches all requirements}}
|
|
%3 = transform.get_parent_op %arg0 {op_name = "builtin.module"} : (!transform.any_op) -> !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @cast(%arg0: f32) -> f64 {
|
|
// expected-remark @below{{f64}}
|
|
%0 = arith.extf %arg0 : f32 to f64
|
|
return %0 : f64
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.structured.match ops{["arith.extf"]} in %arg0 : (!transform.any_op) -> !transform.op<"arith.extf">
|
|
%1 = transform.get_result %0[0] : (!transform.op<"arith.extf">) -> !transform.any_value
|
|
%2 = transform.get_type %1 : (!transform.any_value) -> !transform.type
|
|
transform.debug.emit_param_as_remark %2 at %0 : !transform.type, !transform.op<"arith.extf">
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-error @below {{expected type attribute, got 0 : i32}}
|
|
transform.test_produce_param (0 : i32) : !transform.type
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-error @below {{expected affine map attribute, got 0 : i32}}
|
|
transform.test_produce_param (0 : i32) : !transform.affine_map
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: @type_param_anchor
|
|
func.func private @type_param_anchor()
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// CHECK: test_produce_param(f32) : !transform.type
|
|
transform.test_produce_param(f32) : !transform.type
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: @affine_map_param_anchor
|
|
func.func private @affine_map_param_anchor()
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// CHECK: test_produce_param(#{{.*}}) : !transform.affine_map
|
|
transform.test_produce_param(affine_map<(d0) -> ()>) : !transform.affine_map
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @verify_success(%arg0: f64) -> f64 {
|
|
return %arg0 : f64
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.structured.match ops{["func.func"]} in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
transform.verify %0 : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// expected-error @below{{fail_to_verify is set}}
|
|
// expected-note @below{{payload op}}
|
|
func.func @verify_failure(%arg0: f64) -> f64 {
|
|
return %arg0 : f64
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%0 = transform.structured.match ops{["func.func"]} in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
transform.test_produce_invalid_ir %0 : !transform.any_op
|
|
// expected-error @below{{failed to verify payload op}}
|
|
transform.verify %0 : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @select() {
|
|
// expected-remark @below{{found foo}}
|
|
"test.foo"() : () -> ()
|
|
// expected-remark @below{{found bar}}
|
|
"test.bar"() : () -> ()
|
|
// expected-remark @below{{found foo}}
|
|
"test.foo"() : () -> ()
|
|
func.return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// Match all ops inside the function (including the function itself).
|
|
%func_op = transform.structured.match ops{["func.func"]} in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
%0 = transform.structured.match in %func_op : (!transform.any_op) -> !transform.any_op
|
|
%p = transform.num_associations %0 : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below{{5}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
|
|
// Select "test.foo".
|
|
%foo = transform.select "test.foo" in %0 : (!transform.any_op) -> !transform.any_op
|
|
transform.debug.emit_remark_at %foo, "found foo" : !transform.any_op
|
|
|
|
// Select "test.bar".
|
|
%bar = transform.select "test.bar" in %0 : (!transform.any_op) -> !transform.any_op
|
|
transform.debug.emit_remark_at %bar, "found bar" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func @apply_dce(
|
|
// CHECK-NEXT: memref.store
|
|
// CHECK-NEXT: return
|
|
func.func @apply_dce(%f: f32, %m: memref<5xf32>, %idx: index) {
|
|
// Two dead ops, interleaved with a non-dead op.
|
|
%0 = tensor.empty() : tensor<5xf32>
|
|
memref.store %f, %m[%idx] : memref<5xf32>
|
|
%1 = tensor.insert %f into %0[%idx] : tensor<5xf32>
|
|
return
|
|
}
|
|
|
|
module attributes {transform.with_named_sequence} {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
%func_op = transform.structured.match ops{["func.func"]} in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
%empty_op = transform.structured.match ops{["tensor.empty"]} in %func_op : (!transform.any_op) -> !transform.any_op
|
|
transform.apply_dce to %func_op : !transform.any_op
|
|
|
|
%p = transform.num_associations %empty_op : (!transform.any_op) -> !transform.param<i64>
|
|
// expected-remark @below{{0}}
|
|
transform.debug.emit_param_as_remark %p : !transform.param<i64>
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
|
|
// -----
|
|
|
|
func.func @no_constant_under_loop(%lb: index, %ub: index, %step: index) {
|
|
scf.for %i= %lb to %ub step %step {
|
|
arith.constant 0 : index
|
|
}
|
|
return
|
|
}
|
|
|
|
module @named_inclusion attributes { transform.with_named_sequence } {
|
|
// Match `arith.constant`s that are not nested under a `scf.for` and ensure
|
|
// there are none in the program
|
|
|
|
transform.named_sequence @print(%root: !transform.any_op {transform.readonly}) {
|
|
transform.debug.emit_remark_at %root, "matched func" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
|
|
transform.named_sequence @match_constant_not_under_scf_for(%root: !transform.any_op {transform.readonly})
|
|
-> !transform.any_op {
|
|
transform.match.operation_name %root ["arith.constant"] : !transform.any_op
|
|
%for = transform.get_parent_op %root { op_name = "scf.for", allow_empty_results }
|
|
: (!transform.any_op) -> (!transform.any_op)
|
|
transform.match.operation_empty %for : !transform.any_op
|
|
transform.yield %root : !transform.any_op
|
|
}
|
|
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
transform.foreach_match in %arg0
|
|
@match_constant_not_under_scf_for -> @print
|
|
: (!transform.any_op) -> (!transform.any_op)
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @no_constant_under_loop(%lb: index, %ub: index, %step: index) {
|
|
// expected-remark @below {{no parent scf.for}}
|
|
arith.constant 0 : index
|
|
return
|
|
}
|
|
|
|
module @named_inclusion attributes { transform.with_named_sequence } {
|
|
// Match `arith.constant`s that are not nested under a `scf.for` and ensure
|
|
// there are none in the program
|
|
|
|
transform.named_sequence @print(%root: !transform.any_op {transform.readonly}) {
|
|
transform.debug.emit_remark_at %root, "no parent scf.for" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
|
|
transform.named_sequence @match_constant_not_under_scf_for(%root: !transform.any_op {transform.readonly})
|
|
-> !transform.any_op {
|
|
transform.match.operation_name %root ["arith.constant"] : !transform.any_op
|
|
%for = transform.get_parent_op %root { op_name = "scf.for", allow_empty_results }
|
|
: (!transform.any_op) -> (!transform.any_op)
|
|
transform.match.operation_empty %for : !transform.any_op
|
|
transform.yield %root : !transform.any_op
|
|
}
|
|
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
transform.foreach_match in %arg0
|
|
@match_constant_not_under_scf_for -> @print
|
|
: (!transform.any_op) -> (!transform.any_op)
|
|
transform.yield
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes { transform.with_named_sequence } {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-error @below {{result #0, associated with 2 payload objects, expected 1}}
|
|
transform.collect_matching @matcher in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
transform.yield
|
|
}
|
|
|
|
transform.named_sequence @matcher(%arg0: !transform.any_op {transform.readonly}) -> !transform.any_op {
|
|
%0 = transform.merge_handles %arg0, %arg0 : !transform.any_op
|
|
transform.yield %0 : !transform.any_op
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes { transform.with_named_sequence } {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-error @below {{unresolved external symbol @matcher}}
|
|
transform.collect_matching @matcher in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
transform.yield
|
|
}
|
|
|
|
transform.named_sequence @matcher(%arg0: !transform.any_op {transform.readonly}) -> !transform.any_op
|
|
}
|
|
|
|
// -----
|
|
|
|
module attributes { transform.with_named_sequence } {
|
|
transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
|
|
// expected-remark @below {{matched}}
|
|
%0 = transform.collect_matching @matcher in %arg0 : (!transform.any_op) -> !transform.any_op
|
|
// expected-remark @below {{matched}}
|
|
transform.debug.emit_remark_at %0, "matched" : !transform.any_op
|
|
transform.yield
|
|
}
|
|
|
|
transform.named_sequence @matcher(%arg0: !transform.any_op {transform.readonly}) -> !transform.any_op {
|
|
transform.match.operation_name %arg0 ["transform.debug.emit_remark_at", "transform.collect_matching"] : !transform.any_op
|
|
transform.yield %arg0 : !transform.any_op
|
|
}
|
|
}
|