| # RUN: %PYTHON %s | FileCheck %s |
| |
| from mlir.ir import * |
| from mlir.dialects import transform |
| from mlir.dialects.transform import pdl as transform_pdl |
| |
| |
| def run(f): |
| with Context(), Location.unknown(): |
| module = Module.create() |
| with InsertionPoint(module.body): |
| print("\nTEST:", f.__name__) |
| f(module) |
| print(module) |
| return f |
| |
| |
| @run |
| def testTypes(module: Module): |
| # CHECK-LABEL: TEST: testTypes |
| # CHECK: !transform.any_op |
| any_op = transform.AnyOpType.get() |
| print(any_op) |
| |
| # CHECK: !transform.any_param |
| any_param = transform.AnyParamType.get() |
| print(any_param) |
| |
| # CHECK: !transform.any_value |
| any_value = transform.AnyValueType.get() |
| print(any_value) |
| |
| # CHECK: !transform.op<"foo.bar"> |
| # CHECK: foo.bar |
| concrete_op = transform.OperationType.get("foo.bar") |
| print(concrete_op) |
| print(concrete_op.operation_name) |
| |
| # CHECK: !transform.param<i32> |
| # CHECK: i32 |
| param = transform.ParamType.get(IntegerType.get_signless(32)) |
| print(param) |
| print(param.type) |
| |
| |
| @run |
| def testSequenceOp(module: Module): |
| sequence = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, |
| [transform.AnyOpType.get()], |
| transform.AnyOpType.get(), |
| ) |
| with InsertionPoint(sequence.body): |
| res = transform.CastOp(transform.AnyOpType.get(), sequence.bodyTarget) |
| res2 = transform.cast(transform.any_op_t(), res.result) |
| transform.YieldOp([res2]) |
| # CHECK-LABEL: TEST: testSequenceOp |
| # CHECK: transform.sequence |
| # CHECK: ^{{.*}}(%[[ARG0:.+]]: !transform.any_op): |
| # CHECK: %[[RES:.+]] = cast %[[ARG0]] : !transform.any_op to !transform.any_op |
| # CHECK: %[[RES2:.+]] = cast %[[RES]] : !transform.any_op to !transform.any_op |
| # CHECK: yield %[[RES2]] : !transform.any_op |
| # CHECK: } |
| |
| |
| @run |
| def testSequenceOp(module: Module): |
| sequence = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, |
| [transform.AnyOpType.get()], |
| transform.AnyOpType.get(), |
| ) |
| with InsertionPoint(sequence.body): |
| transform.YieldOp([sequence.bodyTarget]) |
| # CHECK-LABEL: TEST: testSequenceOp |
| # CHECK: = transform.sequence -> !transform.any_op failures(propagate) { |
| # CHECK: ^{{.*}}(%[[ARG0:.+]]: !transform.any_op): |
| # CHECK: yield %[[ARG0]] : !transform.any_op |
| # CHECK: } |
| |
| |
| @run |
| def testNestedSequenceOp(module: Module): |
| sequence = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, [], transform.AnyOpType.get() |
| ) |
| with InsertionPoint(sequence.body): |
| nested = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, [], sequence.bodyTarget |
| ) |
| with InsertionPoint(nested.body): |
| doubly_nested = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, |
| [transform.AnyOpType.get()], |
| nested.bodyTarget, |
| ) |
| with InsertionPoint(doubly_nested.body): |
| transform.YieldOp([doubly_nested.bodyTarget]) |
| transform.YieldOp() |
| transform.YieldOp() |
| # CHECK-LABEL: TEST: testNestedSequenceOp |
| # CHECK: transform.sequence failures(propagate) { |
| # CHECK: ^{{.*}}(%[[ARG0:.+]]: !transform.any_op): |
| # CHECK: sequence %[[ARG0]] : !transform.any_op failures(propagate) { |
| # CHECK: ^{{.*}}(%[[ARG1:.+]]: !transform.any_op): |
| # CHECK: = sequence %[[ARG1]] : !transform.any_op -> !transform.any_op failures(propagate) { |
| # CHECK: ^{{.*}}(%[[ARG2:.+]]: !transform.any_op): |
| # CHECK: yield %[[ARG2]] : !transform.any_op |
| # CHECK: } |
| # CHECK: } |
| # CHECK: } |
| |
| |
| @run |
| def testSequenceOpWithExtras(module: Module): |
| sequence = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, |
| [], |
| transform.AnyOpType.get(), |
| [transform.AnyOpType.get(), transform.OperationType.get("foo.bar")], |
| ) |
| with InsertionPoint(sequence.body): |
| transform.YieldOp() |
| # CHECK-LABEL: TEST: testSequenceOpWithExtras |
| # CHECK: transform.sequence failures(propagate) |
| # CHECK: ^{{.*}}(%{{.*}}: !transform.any_op, %{{.*}}: !transform.any_op, %{{.*}}: !transform.op<"foo.bar">): |
| sequence = transform.sequence( |
| transform.FailurePropagationMode.Propagate, |
| [], |
| transform.AnyOpType.get(), |
| [transform.AnyOpType.get(), transform.OperationType.get("foo.bar")], |
| ) |
| with InsertionPoint(sequence.body): |
| transform.yield_() |
| # CHECK: transform.sequence failures(propagate) |
| # CHECK: ^{{.*}}(%{{.*}}: !transform.any_op, %{{.*}}: !transform.any_op, %{{.*}}: !transform.op<"foo.bar">): |
| |
| |
| @run |
| def testNestedSequenceOpWithExtras(module: Module): |
| sequence = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, |
| [], |
| transform.AnyOpType.get(), |
| [transform.AnyOpType.get(), transform.OperationType.get("foo.bar")], |
| ) |
| with InsertionPoint(sequence.body): |
| nested = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, |
| [], |
| sequence.bodyTarget, |
| sequence.bodyExtraArgs, |
| ) |
| with InsertionPoint(nested.body): |
| transform.YieldOp() |
| transform.YieldOp() |
| # CHECK-LABEL: TEST: testNestedSequenceOpWithExtras |
| # CHECK: transform.sequence failures(propagate) |
| # CHECK: ^{{.*}}(%[[ARG0:.*]]: !transform.any_op, %[[ARG1:.*]]: !transform.any_op, %[[ARG2:.*]]: !transform.op<"foo.bar">): |
| # CHECK: sequence %[[ARG0]], %[[ARG1]], %[[ARG2]] : (!transform.any_op, !transform.any_op, !transform.op<"foo.bar">) |
| |
| |
| @run |
| def testTransformPDLOps(module: Module): |
| withPdl = transform_pdl.WithPDLPatternsOp(transform.AnyOpType.get()) |
| with InsertionPoint(withPdl.body): |
| sequence = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, |
| [transform.AnyOpType.get()], |
| withPdl.bodyTarget, |
| ) |
| with InsertionPoint(sequence.body): |
| match = transform_pdl.PDLMatchOp( |
| transform.AnyOpType.get(), sequence.bodyTarget, "pdl_matcher" |
| ) |
| transform.YieldOp(match) |
| # CHECK-LABEL: TEST: testTransformPDLOps |
| # CHECK: transform.with_pdl_patterns { |
| # CHECK: ^{{.*}}(%[[ARG0:.+]]: !transform.any_op): |
| # CHECK: = sequence %[[ARG0]] : !transform.any_op -> !transform.any_op failures(propagate) { |
| # CHECK: ^{{.*}}(%[[ARG1:.+]]: !transform.any_op): |
| # CHECK: %[[RES:.+]] = pdl_match @pdl_matcher in %[[ARG1]] |
| # CHECK: yield %[[RES]] : !transform.any_op |
| # CHECK: } |
| # CHECK: } |
| |
| |
| @run |
| def testNamedSequenceOp(module: Module): |
| module.operation.attributes["transform.with_named_sequence"] = UnitAttr.get() |
| named_sequence = transform.NamedSequenceOp( |
| "__transform_main", |
| [transform.AnyOpType.get()], |
| [transform.AnyOpType.get()], |
| arg_attrs=[{"transform.consumed": UnitAttr.get()}], |
| ) |
| with InsertionPoint(named_sequence.body): |
| transform.YieldOp([named_sequence.bodyTarget]) |
| # CHECK-LABEL: TEST: testNamedSequenceOp |
| # CHECK: module attributes {transform.with_named_sequence} { |
| # CHECK: transform.named_sequence @__transform_main(%[[ARG0:.+]]: !transform.any_op {transform.consumed}) -> !transform.any_op { |
| # CHECK: yield %[[ARG0]] : !transform.any_op |
| named_sequence = transform.named_sequence( |
| "other_seq", |
| [transform.AnyOpType.get()], |
| [transform.AnyOpType.get()], |
| arg_attrs=[{"transform.consumed": UnitAttr.get()}], |
| ) |
| with InsertionPoint(named_sequence.body): |
| transform.yield_([named_sequence.bodyTarget]) |
| # CHECK: transform.named_sequence @other_seq(%[[ARG1:.+]]: !transform.any_op {transform.consumed}) -> !transform.any_op { |
| # CHECK: yield %[[ARG1]] : !transform.any_op |
| |
| |
| @run |
| def testGetParentOp(module: Module): |
| sequence = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, [], transform.AnyOpType.get() |
| ) |
| with InsertionPoint(sequence.body): |
| transform.GetParentOp( |
| transform.AnyOpType.get(), |
| sequence.bodyTarget, |
| isolated_from_above=True, |
| nth_parent=2, |
| ) |
| transform.get_parent_op( |
| transform.AnyOpType.get(), |
| sequence.bodyTarget, |
| isolated_from_above=True, |
| nth_parent=2, |
| allow_empty_results=True, |
| op_name="func.func", |
| deduplicate=True, |
| ) |
| transform.YieldOp() |
| # CHECK-LABEL: TEST: testGetParentOp |
| # CHECK: transform.sequence |
| # CHECK: ^{{.*}}(%[[ARG1:.+]]: !transform.any_op): |
| # CHECK: = get_parent_op %[[ARG1]] {isolated_from_above, nth_parent = 2 : i64} |
| # CHECK: = get_parent_op %[[ARG1]] {allow_empty_results, deduplicate, isolated_from_above, nth_parent = 2 : i64, op_name = "func.func"} |
| |
| |
| @run |
| def testMergeHandlesOp(module: Module): |
| sequence = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, [], transform.AnyOpType.get() |
| ) |
| with InsertionPoint(sequence.body): |
| res = transform.MergeHandlesOp([sequence.bodyTarget]) |
| transform.merge_handles([res.result], deduplicate=True) |
| transform.YieldOp() |
| # CHECK-LABEL: TEST: testMergeHandlesOp |
| # CHECK: transform.sequence |
| # CHECK: ^{{.*}}(%[[ARG1:.+]]: !transform.any_op): |
| # CHECK: %[[RES1:.+]] = merge_handles %[[ARG1]] : !transform.any_op |
| # CHECK: = merge_handles deduplicate %[[RES1]] : !transform.any_op |
| |
| |
| @run |
| def testApplyPatternsOpCompact(module: Module): |
| sequence = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, [], transform.AnyOpType.get() |
| ) |
| with InsertionPoint(sequence.body): |
| with InsertionPoint(transform.ApplyPatternsOp(sequence.bodyTarget).patterns): |
| transform.ApplyCanonicalizationPatternsOp() |
| with InsertionPoint( |
| transform.apply_patterns( |
| sequence.bodyTarget, |
| apply_cse=True, |
| max_iterations=3, |
| max_num_rewrites=5, |
| ).patterns |
| ): |
| transform.ApplyCanonicalizationPatternsOp() |
| transform.YieldOp() |
| # CHECK-LABEL: TEST: testApplyPatternsOpCompact |
| # CHECK: apply_patterns to |
| # CHECK: transform.apply_patterns.canonicalization |
| # CHECK: } : !transform.any_op |
| # CHECK: apply_patterns to |
| # CHECK: transform.apply_patterns.canonicalization |
| # CHECK: } {apply_cse, max_iterations = 3 : i64, max_num_rewrites = 5 : i64} : !transform.any_op |
| |
| |
| @run |
| def testApplyPatternsOpWithType(module: Module): |
| sequence = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, |
| [], |
| transform.OperationType.get("test.dummy"), |
| ) |
| with InsertionPoint(sequence.body): |
| with InsertionPoint(transform.ApplyPatternsOp(sequence.bodyTarget).patterns): |
| transform.ApplyCanonicalizationPatternsOp() |
| transform.YieldOp() |
| # CHECK-LABEL: TEST: testApplyPatternsOp |
| # CHECK: apply_patterns to |
| # CHECK: transform.apply_patterns.canonicalization |
| # CHECK: !transform.op<"test.dummy"> |
| |
| |
| @run |
| def testReplicateOp(module: Module): |
| with_pdl = transform_pdl.WithPDLPatternsOp(transform.AnyOpType.get()) |
| with InsertionPoint(with_pdl.body): |
| sequence = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, [], with_pdl.bodyTarget |
| ) |
| with InsertionPoint(sequence.body): |
| m1 = transform_pdl.PDLMatchOp( |
| transform.AnyOpType.get(), sequence.bodyTarget, "first" |
| ) |
| m2 = transform_pdl.PDLMatchOp( |
| transform.AnyOpType.get(), sequence.bodyTarget, "second" |
| ) |
| transform.ReplicateOp(m1, [m2]) |
| transform.replicate(m1, [m2]) |
| transform.YieldOp() |
| # CHECK-LABEL: TEST: testReplicateOp |
| # CHECK: %[[FIRST:.+]] = pdl_match |
| # CHECK: %[[SECOND:.+]] = pdl_match |
| # CHECK: %{{.*}} = replicate num(%[[FIRST]]) %[[SECOND]] |
| # CHECK: %{{.*}} = replicate num(%[[FIRST]]) %[[SECOND]] |
| |
| |
| # CHECK-LABEL: TEST: testApplyRegisteredPassOp |
| @run |
| def testApplyRegisteredPassOp(module: Module): |
| # CHECK: transform.sequence |
| sequence = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, [], transform.AnyOpType.get() |
| ) |
| with InsertionPoint(sequence.body): |
| # CHECK: %{{.*}} = apply_registered_pass "canonicalize" to {{.*}} : (!transform.any_op) -> !transform.any_op |
| mod = transform.ApplyRegisteredPassOp( |
| transform.AnyOpType.get(), sequence.bodyTarget, "canonicalize" |
| ) |
| # CHECK: %{{.*}} = apply_registered_pass "canonicalize" |
| # CHECK-SAME: with options = {"top-down" = false} |
| # CHECK-SAME: to {{.*}} : (!transform.any_op) -> !transform.any_op |
| mod = transform.ApplyRegisteredPassOp( |
| transform.AnyOpType.get(), |
| mod.result, |
| "canonicalize", |
| options={"top-down": BoolAttr.get(False)}, |
| ) |
| # CHECK: %[[MAX_ITER:.+]] = transform.param.constant |
| max_iter = transform.param_constant( |
| transform.AnyParamType.get(), |
| IntegerAttr.get(IntegerType.get_signless(64), 10), |
| ) |
| # CHECK: %[[MAX_REWRITE:.+]] = transform.param.constant |
| max_rewrites = transform.param_constant( |
| transform.AnyParamType.get(), |
| IntegerAttr.get(IntegerType.get_signless(64), 1), |
| ) |
| # CHECK: %{{.*}} = apply_registered_pass "canonicalize" |
| # NB: MLIR has sorted the dict lexicographically by key: |
| # CHECK-SAME: with options = {"max-iterations" = %[[MAX_ITER]], |
| # CHECK-SAME: "max-rewrites" = %[[MAX_REWRITE]], |
| # CHECK-SAME: "test-convergence" = true, |
| # CHECK-SAME: "top-down" = false} |
| # CHECK-SAME: to %{{.*}} : (!transform.any_op, !transform.any_param, !transform.any_param) -> !transform.any_op |
| mod = transform.apply_registered_pass( |
| transform.AnyOpType.get(), |
| mod, |
| "canonicalize", |
| options={ |
| "top-down": BoolAttr.get(False), |
| "max-iterations": max_iter, |
| "test-convergence": True, |
| "max-rewrites": max_rewrites, |
| }, |
| ) |
| # CHECK: %{{.*}} = apply_registered_pass "symbol-privatize" |
| # CHECK-SAME: with options = {"exclude" = ["a", "b"]} |
| # CHECK-SAME: to %{{.*}} : (!transform.any_op) -> !transform.any_op |
| mod = transform.apply_registered_pass( |
| transform.AnyOpType.get(), |
| mod, |
| "symbol-privatize", |
| options={"exclude": ("a", "b")}, |
| ) |
| # CHECK: %[[SYMBOL_A:.+]] = transform.param.constant |
| symbol_a = transform.param_constant( |
| transform.AnyParamType.get(), StringAttr.get("a") |
| ) |
| # CHECK: %[[SYMBOL_B:.+]] = transform.param.constant |
| symbol_b = transform.param_constant( |
| transform.AnyParamType.get(), StringAttr.get("b") |
| ) |
| # CHECK: %{{.*}} = apply_registered_pass "symbol-privatize" |
| # CHECK-SAME: with options = {"exclude" = [%[[SYMBOL_A]], %[[SYMBOL_B]]]} |
| # CHECK-SAME: to %{{.*}} : (!transform.any_op, !transform.any_param, !transform.any_param) -> !transform.any_op |
| mod = transform.apply_registered_pass( |
| transform.AnyOpType.get(), |
| mod, |
| "symbol-privatize", |
| options={"exclude": (symbol_a, symbol_b)}, |
| ) |
| transform.YieldOp() |
| |
| |
| # CHECK-LABEL: TEST: testForeachOp |
| @run |
| def testForeachOp(module: Module): |
| # CHECK: transform.sequence |
| sequence = transform.SequenceOp( |
| transform.FailurePropagationMode.Propagate, |
| [transform.AnyOpType.get()], |
| transform.AnyOpType.get(), |
| ) |
| with InsertionPoint(sequence.body): |
| # CHECK: {{.*}} = foreach %{{.*}} : !transform.any_op -> !transform.any_op |
| foreach1 = transform.ForeachOp( |
| (transform.AnyOpType.get(),), (sequence.bodyTarget,) |
| ) |
| with InsertionPoint(foreach1.body): |
| # CHECK: transform.yield {{.*}} : !transform.any_op |
| transform.yield_(foreach1.bodyTargets) |
| |
| a_val = transform.get_operand( |
| transform.AnyValueType.get(), foreach1.result, [0] |
| ) |
| a_param = transform.param_constant( |
| transform.AnyParamType.get(), StringAttr.get("a_param") |
| ) |
| |
| # CHECK: {{.*}} = foreach %{{.*}}, %{{.*}}, %{{.*}} : !transform.any_op, !transform.any_value, !transform.any_param -> !transform.any_value, !transform.any_param |
| foreach2 = transform.foreach( |
| (transform.AnyValueType.get(), transform.AnyParamType.get()), |
| (sequence.bodyTarget, a_val, a_param), |
| ) |
| with InsertionPoint(foreach2.owner.body): |
| # CHECK: transform.yield {{.*}} : !transform.any_value, !transform.any_param |
| transform.yield_(foreach2.owner.bodyTargets[1:3]) |
| |
| another_param = transform.param_constant( |
| transform.AnyParamType.get(), StringAttr.get("another_param") |
| ) |
| params = transform.merge_handles([a_param, another_param]) |
| |
| # CHECK: {{.*}} = foreach %{{.*}}, %{{.*}}, %{{.*}} with_zip_shortest : !transform.any_op, !transform.any_param, !transform.any_param -> !transform.any_op |
| foreach3 = transform.foreach( |
| (transform.AnyOpType.get(),), |
| (foreach1.result, foreach2[1], params), |
| with_zip_shortest=True, |
| ) |
| with InsertionPoint(foreach3.owner.body): |
| # CHECK: transform.yield {{.*}} : !transform.any_op |
| transform.yield_((foreach3.owner.bodyTargets[0],)) |
| |
| transform.yield_((foreach3,)) |