xref: /llvm-project/mlir/test/Examples/transform/Ch4/sequence.mlir (revision 2798b72ae7e5caad793169b77cbac47fe2362d0f)
14cb2ef4fSOleksandr "Alex" Zinenko// RUN: transform-opt-ch4 %s --transform-interpreter --verify-diagnostics
24cb2ef4fSOleksandr "Alex" Zinenko//
34cb2ef4fSOleksandr "Alex" Zinenko// RUN: transform-opt-ch4 %s \
44cb2ef4fSOleksandr "Alex" Zinenko// RUN:              --transform-interpreter='entry-point=__transform_main_v2' \
54cb2ef4fSOleksandr "Alex" Zinenko// RUN:              --verify-diagnostics
64cb2ef4fSOleksandr "Alex" Zinenko
74cb2ef4fSOleksandr "Alex" Zinenko// ****************************** IMPORTANT NOTE ******************************
84cb2ef4fSOleksandr "Alex" Zinenko//
94cb2ef4fSOleksandr "Alex" Zinenko// If you are changing this file, you may also need to change
104cb2ef4fSOleksandr "Alex" Zinenko// mlir/docs/Tutorials/Transform accordingly.
114cb2ef4fSOleksandr "Alex" Zinenko//
124cb2ef4fSOleksandr "Alex" Zinenko// ****************************************************************************
134cb2ef4fSOleksandr "Alex" Zinenko
144cb2ef4fSOleksandr "Alex" Zinenko// Original function to optimize.
154cb2ef4fSOleksandr "Alex" Zinenkofunc.func @fc_relu(%lhs: tensor<512x512xf32>, %rhs: tensor<512x512xf32>,
164cb2ef4fSOleksandr "Alex" Zinenko                   %bias: tensor<512x512xf32>, %output: tensor<512x512xf32>)
174cb2ef4fSOleksandr "Alex" Zinenko                   -> tensor<512x512xf32> {
184cb2ef4fSOleksandr "Alex" Zinenko  // Matrix-matrix multiplication.
194cb2ef4fSOleksandr "Alex" Zinenko  // expected-remark @below {{matmul}}
204cb2ef4fSOleksandr "Alex" Zinenko  %matmul = linalg.matmul ins(%lhs, %rhs: tensor<512x512xf32>, tensor<512x512xf32>)
214cb2ef4fSOleksandr "Alex" Zinenko                          outs(%output: tensor<512x512xf32>) -> tensor<512x512xf32>
224cb2ef4fSOleksandr "Alex" Zinenko
234cb2ef4fSOleksandr "Alex" Zinenko  // Elementwise addition.
244cb2ef4fSOleksandr "Alex" Zinenko  // expected-remark @below {{elementwise binary}}
254cb2ef4fSOleksandr "Alex" Zinenko  %biased = linalg.elemwise_binary { fun = #linalg.binary_fn<add> }
264cb2ef4fSOleksandr "Alex" Zinenko    ins(%matmul, %bias : tensor<512x512xf32>, tensor<512x512xf32>)
274cb2ef4fSOleksandr "Alex" Zinenko    outs(%output : tensor<512x512xf32>) -> tensor<512x512xf32>
284cb2ef4fSOleksandr "Alex" Zinenko
294cb2ef4fSOleksandr "Alex" Zinenko  // Elementwise max with 0 (ReLU).
304cb2ef4fSOleksandr "Alex" Zinenko  %c0f = arith.constant 0.0 : f32
314cb2ef4fSOleksandr "Alex" Zinenko  // expected-remark @below {{elementwise binary}}
324cb2ef4fSOleksandr "Alex" Zinenko  %relued = linalg.elemwise_binary { fun = #linalg.binary_fn<max_signed> }
334cb2ef4fSOleksandr "Alex" Zinenko    ins(%biased, %c0f : tensor<512x512xf32>, f32)
344cb2ef4fSOleksandr "Alex" Zinenko    outs(%output : tensor<512x512xf32>) -> tensor<512x512xf32>
354cb2ef4fSOleksandr "Alex" Zinenko  func.return %relued : tensor<512x512xf32>
364cb2ef4fSOleksandr "Alex" Zinenko}
374cb2ef4fSOleksandr "Alex" Zinenko
384cb2ef4fSOleksandr "Alex" Zinenko// The module containing named sequences must have an attribute allowing them
394cb2ef4fSOleksandr "Alex" Zinenko// to enable verification.
404cb2ef4fSOleksandr "Alex" Zinenkomodule @transforms attributes { transform.with_named_sequence } {
414cb2ef4fSOleksandr "Alex" Zinenko  // Entry point. This takes as the only argument the root operation (typically
424cb2ef4fSOleksandr "Alex" Zinenko  // pass root) given to the transform interpreter.
434cb2ef4fSOleksandr "Alex" Zinenko  transform.named_sequence @__transform_main(
444cb2ef4fSOleksandr "Alex" Zinenko      %root: !transform.any_op {transform.readonly}) {
454cb2ef4fSOleksandr "Alex" Zinenko    // Collect operations that match the criteria specified in the named
464cb2ef4fSOleksandr "Alex" Zinenko    // sequence. If the named sequence fails with a silenceable failure,
474cb2ef4fSOleksandr "Alex" Zinenko    // silences it (the message is forwarded to the debug stream). If the named
484cb2ef4fSOleksandr "Alex" Zinenko    // sequence succeeds, appends its results to the results of this operation.
494cb2ef4fSOleksandr "Alex" Zinenko    %elemwise = transform.collect_matching @match_elemwise in %root
504cb2ef4fSOleksandr "Alex" Zinenko      : (!transform.any_op) -> !transform.any_op
514cb2ef4fSOleksandr "Alex" Zinenko    %matmul = transform.collect_matching @match_matmul in %root
524cb2ef4fSOleksandr "Alex" Zinenko      : (!transform.any_op) -> !transform.any_op
534cb2ef4fSOleksandr "Alex" Zinenko
544cb2ef4fSOleksandr "Alex" Zinenko    transform.include @print_elemwise failures(propagate)  (%elemwise)
554cb2ef4fSOleksandr "Alex" Zinenko      : (!transform.any_op) -> ()
564cb2ef4fSOleksandr "Alex" Zinenko    transform.include @print_matmul failures(propagate)  (%matmul)
574cb2ef4fSOleksandr "Alex" Zinenko      : (!transform.any_op) -> ()
584cb2ef4fSOleksandr "Alex" Zinenko
594cb2ef4fSOleksandr "Alex" Zinenko    transform.yield
604cb2ef4fSOleksandr "Alex" Zinenko  }
614cb2ef4fSOleksandr "Alex" Zinenko
624cb2ef4fSOleksandr "Alex" Zinenko  // Alternative entry point.
634cb2ef4fSOleksandr "Alex" Zinenko  transform.named_sequence @__transform_main_v2(
644cb2ef4fSOleksandr "Alex" Zinenko      %root: !transform.any_op {transform.readonly}) {
654cb2ef4fSOleksandr "Alex" Zinenko    // Collect groups of operations that match the criteria specified in the
664cb2ef4fSOleksandr "Alex" Zinenko    // named sequence.
674cb2ef4fSOleksandr "Alex" Zinenko    %matmul, %el1, %el2 = transform.collect_matching @match_matmul_elemwise in %root
684cb2ef4fSOleksandr "Alex" Zinenko      : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
694cb2ef4fSOleksandr "Alex" Zinenko    %elemwise = transform.merge_handles %el1, %el2 : !transform.any_op
704cb2ef4fSOleksandr "Alex" Zinenko
714cb2ef4fSOleksandr "Alex" Zinenko    transform.include @print_elemwise failures(propagate)  (%elemwise)
724cb2ef4fSOleksandr "Alex" Zinenko      : (!transform.any_op) -> ()
734cb2ef4fSOleksandr "Alex" Zinenko    transform.include @print_matmul failures(propagate)  (%matmul)
744cb2ef4fSOleksandr "Alex" Zinenko      : (!transform.any_op) -> ()
754cb2ef4fSOleksandr "Alex" Zinenko
764cb2ef4fSOleksandr "Alex" Zinenko    transform.yield
774cb2ef4fSOleksandr "Alex" Zinenko  }
784cb2ef4fSOleksandr "Alex" Zinenko
794cb2ef4fSOleksandr "Alex" Zinenko  // This is a matcher sequence. It is given an operation to match and the
804cb2ef4fSOleksandr "Alex" Zinenko  // match is considered successful unless any nested operation produces a
814cb2ef4fSOleksandr "Alex" Zinenko  // failure. The values yielded by this operation will be forwarded to the
824cb2ef4fSOleksandr "Alex" Zinenko  // rewriter sequence on success.
834cb2ef4fSOleksandr "Alex" Zinenko  transform.named_sequence @match_elemwise(
844cb2ef4fSOleksandr "Alex" Zinenko      %entry: !transform.any_op {transform.readonly}) -> !transform.any_op {
854cb2ef4fSOleksandr "Alex" Zinenko    transform.match.operation_name %entry ["linalg.elemwise_binary"]
864cb2ef4fSOleksandr "Alex" Zinenko      : !transform.any_op
874cb2ef4fSOleksandr "Alex" Zinenko    transform.yield %entry : !transform.any_op
884cb2ef4fSOleksandr "Alex" Zinenko  }
894cb2ef4fSOleksandr "Alex" Zinenko  transform.named_sequence @match_matmul(
904cb2ef4fSOleksandr "Alex" Zinenko      %entry: !transform.any_op {transform.readonly}) -> !transform.any_op {
914cb2ef4fSOleksandr "Alex" Zinenko    transform.match.operation_name %entry ["linalg.matmul"] : !transform.any_op
924cb2ef4fSOleksandr "Alex" Zinenko    transform.yield %entry : !transform.any_op
934cb2ef4fSOleksandr "Alex" Zinenko  }
944cb2ef4fSOleksandr "Alex" Zinenko
954cb2ef4fSOleksandr "Alex" Zinenko  // This is an action sequence.
964cb2ef4fSOleksandr "Alex" Zinenko  transform.named_sequence @print_elemwise(
974cb2ef4fSOleksandr "Alex" Zinenko      %elemwise_binary: !transform.any_op {transform.readonly}) {
98*2798b72aSOleksandr "Alex" Zinenko    transform.debug.emit_remark_at
994cb2ef4fSOleksandr "Alex" Zinenko      %elemwise_binary, "elementwise binary" : !transform.any_op
1004cb2ef4fSOleksandr "Alex" Zinenko    transform.yield
1014cb2ef4fSOleksandr "Alex" Zinenko  }
1024cb2ef4fSOleksandr "Alex" Zinenko  transform.named_sequence @print_matmul(
1034cb2ef4fSOleksandr "Alex" Zinenko      %matmul: !transform.any_op {transform.readonly}) {
104*2798b72aSOleksandr "Alex" Zinenko    transform.debug.emit_remark_at %matmul, "matmul" : !transform.any_op
1054cb2ef4fSOleksandr "Alex" Zinenko    transform.yield
1064cb2ef4fSOleksandr "Alex" Zinenko  }
1074cb2ef4fSOleksandr "Alex" Zinenko
1084cb2ef4fSOleksandr "Alex" Zinenko  // This is also a matcher sequence. It is similarly given an operation to
1094cb2ef4fSOleksandr "Alex" Zinenko  // match and nested operations must succeed in order for a match to be deemed
1104cb2ef4fSOleksandr "Alex" Zinenko  // successful. It starts matching from the last operation in the use-def chain
1114cb2ef4fSOleksandr "Alex" Zinenko  // and goes back because each operand (use) has exactly one definition.
1124cb2ef4fSOleksandr "Alex" Zinenko  transform.named_sequence @match_matmul_elemwise(
1134cb2ef4fSOleksandr "Alex" Zinenko      %last: !transform.any_op {transform.readonly})
1144cb2ef4fSOleksandr "Alex" Zinenko      -> (!transform.any_op, !transform.any_op, !transform.any_op) {
1154cb2ef4fSOleksandr "Alex" Zinenko    // The last operation must be an elementwise binary.
1164cb2ef4fSOleksandr "Alex" Zinenko    transform.match.operation_name %last ["linalg.elemwise_binary"]
1174cb2ef4fSOleksandr "Alex" Zinenko      : !transform.any_op
1184cb2ef4fSOleksandr "Alex" Zinenko    // Its first operand must be defined by another operation, to which we
1194cb2ef4fSOleksandr "Alex" Zinenko    // will get a handle here. We are guaranteed that the first operand exists
1204cb2ef4fSOleksandr "Alex" Zinenko    // because we know the operation is binary, but even in absence of such a
1214cb2ef4fSOleksandr "Alex" Zinenko    // guarantee, this operation would have produced a silenceable failure when
1224cb2ef4fSOleksandr "Alex" Zinenko    // `%last` does not have enough operands.
1234cb2ef4fSOleksandr "Alex" Zinenko    %middle = transform.get_producer_of_operand %last[0]
1244cb2ef4fSOleksandr "Alex" Zinenko      : (!transform.any_op) -> !transform.any_op
1254cb2ef4fSOleksandr "Alex" Zinenko    // The defining operation must itself be an elementwise binary.
1264cb2ef4fSOleksandr "Alex" Zinenko    transform.match.operation_name %middle ["linalg.elemwise_binary"]
1274cb2ef4fSOleksandr "Alex" Zinenko      : !transform.any_op
1284cb2ef4fSOleksandr "Alex" Zinenko    // And the first operand of that operation must be defined by yet another
1294cb2ef4fSOleksandr "Alex" Zinenko    // operation.
1304cb2ef4fSOleksandr "Alex" Zinenko    %matmul = transform.get_producer_of_operand %middle[0]
1314cb2ef4fSOleksandr "Alex" Zinenko      : (!transform.any_op) -> !transform.any_op
1324cb2ef4fSOleksandr "Alex" Zinenko    // And that operation is a matmul.
1334cb2ef4fSOleksandr "Alex" Zinenko    transform.match.operation_name %matmul ["linalg.matmul"] : !transform.any_op
1344cb2ef4fSOleksandr "Alex" Zinenko    // We will yield the handles to the matmul and the two elementwise
1354cb2ef4fSOleksandr "Alex" Zinenko    // operations separately.
1364cb2ef4fSOleksandr "Alex" Zinenko    transform.yield %matmul, %middle, %last
1374cb2ef4fSOleksandr "Alex" Zinenko      : !transform.any_op, !transform.any_op, !transform.any_op
1384cb2ef4fSOleksandr "Alex" Zinenko  }
1394cb2ef4fSOleksandr "Alex" Zinenko}
140