xref: /llvm-project/mlir/test/Examples/transform/Ch4/multiple.mlir (revision 2798b72ae7e5caad793169b77cbac47fe2362d0f)
14cb2ef4fSOleksandr "Alex" Zinenko// RUN: transform-opt-ch4 %s --transform-interpreter --verify-diagnostics
24cb2ef4fSOleksandr "Alex" Zinenko
34cb2ef4fSOleksandr "Alex" Zinenko// Matmul+ReLU.
44cb2ef4fSOleksandr "Alex" Zinenkofunc.func @fc_relu_operands_00(
54cb2ef4fSOleksandr "Alex" Zinenko    %lhs: tensor<512x512xf32>, %rhs: tensor<512x512xf32>,
64cb2ef4fSOleksandr "Alex" Zinenko    %bias: tensor<512x512xf32>, %output: tensor<512x512xf32>)
74cb2ef4fSOleksandr "Alex" Zinenko    -> tensor<512x512xf32> {
84cb2ef4fSOleksandr "Alex" Zinenko  // Matrix-matrix multiplication.
94cb2ef4fSOleksandr "Alex" Zinenko  // expected-remark @below {{matmul # 0}}
104cb2ef4fSOleksandr "Alex" Zinenko  %matmul = linalg.matmul ins(%lhs, %rhs: tensor<512x512xf32>, tensor<512x512xf32>)
114cb2ef4fSOleksandr "Alex" Zinenko                          outs(%output: tensor<512x512xf32>) -> tensor<512x512xf32>
124cb2ef4fSOleksandr "Alex" Zinenko
134cb2ef4fSOleksandr "Alex" Zinenko  // Elementwise addition.
144cb2ef4fSOleksandr "Alex" Zinenko  // expected-remark @below {{add # 0}}
154cb2ef4fSOleksandr "Alex" Zinenko  %biased = linalg.elemwise_binary { fun = #linalg.binary_fn<add> }
164cb2ef4fSOleksandr "Alex" Zinenko    ins(%matmul, %bias : tensor<512x512xf32>, tensor<512x512xf32>)
174cb2ef4fSOleksandr "Alex" Zinenko    outs(%output : tensor<512x512xf32>) -> tensor<512x512xf32>
184cb2ef4fSOleksandr "Alex" Zinenko
194cb2ef4fSOleksandr "Alex" Zinenko  // Elementwise max with 0 (ReLU).
204cb2ef4fSOleksandr "Alex" Zinenko  %c0f = arith.constant 0.0 : f32
214cb2ef4fSOleksandr "Alex" Zinenko  // expected-remark @below {{max # 0}}
224cb2ef4fSOleksandr "Alex" Zinenko  %relued = linalg.elemwise_binary { fun = #linalg.binary_fn<max_signed> }
234cb2ef4fSOleksandr "Alex" Zinenko    ins(%biased, %c0f : tensor<512x512xf32>, f32)
244cb2ef4fSOleksandr "Alex" Zinenko    outs(%output : tensor<512x512xf32>) -> tensor<512x512xf32>
254cb2ef4fSOleksandr "Alex" Zinenko  func.return %relued : tensor<512x512xf32>
264cb2ef4fSOleksandr "Alex" Zinenko}
274cb2ef4fSOleksandr "Alex" Zinenko
284cb2ef4fSOleksandr "Alex" Zinenko// Matmul+ReLU with swapped operands.
294cb2ef4fSOleksandr "Alex" Zinenkofunc.func @fc_relu_operands_01(
304cb2ef4fSOleksandr "Alex" Zinenko    %lhs: tensor<512x512xf32>, %rhs: tensor<512x512xf32>,
314cb2ef4fSOleksandr "Alex" Zinenko    %bias: tensor<512x512xf32>, %output: tensor<512x512xf32>)
324cb2ef4fSOleksandr "Alex" Zinenko    -> tensor<512x512xf32> {
334cb2ef4fSOleksandr "Alex" Zinenko  // Matrix-matrix multiplication.
344cb2ef4fSOleksandr "Alex" Zinenko  // expected-remark @below {{matmul # 1}}
354cb2ef4fSOleksandr "Alex" Zinenko  %matmul = linalg.matmul ins(%lhs, %rhs: tensor<512x512xf32>, tensor<512x512xf32>)
364cb2ef4fSOleksandr "Alex" Zinenko                          outs(%output: tensor<512x512xf32>) -> tensor<512x512xf32>
374cb2ef4fSOleksandr "Alex" Zinenko
384cb2ef4fSOleksandr "Alex" Zinenko  // Elementwise addition.
394cb2ef4fSOleksandr "Alex" Zinenko  // expected-remark @below {{add # 1}}
404cb2ef4fSOleksandr "Alex" Zinenko  %biased = linalg.elemwise_binary { fun = #linalg.binary_fn<add> }
414cb2ef4fSOleksandr "Alex" Zinenko    ins(%matmul, %bias : tensor<512x512xf32>, tensor<512x512xf32>)
424cb2ef4fSOleksandr "Alex" Zinenko    outs(%output : tensor<512x512xf32>) -> tensor<512x512xf32>
434cb2ef4fSOleksandr "Alex" Zinenko
444cb2ef4fSOleksandr "Alex" Zinenko  // Elementwise max with 0 (ReLU).
454cb2ef4fSOleksandr "Alex" Zinenko  %c0f = arith.constant 0.0 : f32
464cb2ef4fSOleksandr "Alex" Zinenko  // expected-remark @below {{max # 1}}
474cb2ef4fSOleksandr "Alex" Zinenko  %relued = linalg.elemwise_binary { fun = #linalg.binary_fn<max_signed> }
484cb2ef4fSOleksandr "Alex" Zinenko    ins(%c0f, %biased : f32, tensor<512x512xf32>)
494cb2ef4fSOleksandr "Alex" Zinenko    outs(%output : tensor<512x512xf32>) -> tensor<512x512xf32>
504cb2ef4fSOleksandr "Alex" Zinenko  func.return %relued : tensor<512x512xf32>
514cb2ef4fSOleksandr "Alex" Zinenko}
524cb2ef4fSOleksandr "Alex" Zinenko
534cb2ef4fSOleksandr "Alex" Zinenko// The module containing named sequences must have an attribute allowing them
544cb2ef4fSOleksandr "Alex" Zinenko// to enable verification.
554cb2ef4fSOleksandr "Alex" Zinenkomodule @transforms attributes { transform.with_named_sequence } {
564cb2ef4fSOleksandr "Alex" Zinenko  // Entry point. This takes as the only argument the root operation (typically
574cb2ef4fSOleksandr "Alex" Zinenko  // pass root) given to the transform interpreter.
584cb2ef4fSOleksandr "Alex" Zinenko  transform.named_sequence @__transform_main(
594cb2ef4fSOleksandr "Alex" Zinenko      %root: !transform.any_op {transform.consumed}) {
604cb2ef4fSOleksandr "Alex" Zinenko
614cb2ef4fSOleksandr "Alex" Zinenko    // Traverses the payload IR associated with the operand handle, invoking
624cb2ef4fSOleksandr "Alex" Zinenko    // @match_matmul_elemwise on each of the operations. If the named sequence
634cb2ef4fSOleksandr "Alex" Zinenko    // succeeds, i.e., if none of the nested match (transform) operations
644cb2ef4fSOleksandr "Alex" Zinenko    // produced a silenceable failure, invokes @print_matmul_elemwise and
654cb2ef4fSOleksandr "Alex" Zinenko    // forwards the values yielded as arguments of the new invocation. If the
664cb2ef4fSOleksandr "Alex" Zinenko    // named sequence fails with a silenceable failure, silences it (the message
674cb2ef4fSOleksandr "Alex" Zinenko    // is forwarded to the debug stream). Definite failures are propagated
684cb2ef4fSOleksandr "Alex" Zinenko    // immediately and unconditionally, as usual.
694cb2ef4fSOleksandr "Alex" Zinenko    transform.foreach_match in %root
704cb2ef4fSOleksandr "Alex" Zinenko      @match_matmul_elemwise -> @print_matmul_elemwise
714cb2ef4fSOleksandr "Alex" Zinenko      : (!transform.any_op) -> !transform.any_op
724cb2ef4fSOleksandr "Alex" Zinenko
734cb2ef4fSOleksandr "Alex" Zinenko    transform.yield
744cb2ef4fSOleksandr "Alex" Zinenko  }
754cb2ef4fSOleksandr "Alex" Zinenko
764cb2ef4fSOleksandr "Alex" Zinenko  // This is an action sequence.
774cb2ef4fSOleksandr "Alex" Zinenko  transform.named_sequence @print_matmul_elemwise(
784cb2ef4fSOleksandr "Alex" Zinenko      %matmul: !transform.any_op {transform.readonly},
794cb2ef4fSOleksandr "Alex" Zinenko      %add: !transform.any_op {transform.readonly},
804cb2ef4fSOleksandr "Alex" Zinenko      %max: !transform.any_op {transform.readonly},
814cb2ef4fSOleksandr "Alex" Zinenko      %pos: !transform.param<i32> {transform.readonly}) {
82*2798b72aSOleksandr "Alex" Zinenko    transform.debug.emit_param_as_remark %pos, "matmul #" at %matmul
834cb2ef4fSOleksandr "Alex" Zinenko      : !transform.param<i32>, !transform.any_op
84*2798b72aSOleksandr "Alex" Zinenko    transform.debug.emit_param_as_remark %pos, "add #" at %add
854cb2ef4fSOleksandr "Alex" Zinenko      : !transform.param<i32>, !transform.any_op
86*2798b72aSOleksandr "Alex" Zinenko    transform.debug.emit_param_as_remark %pos, "max #" at %max
874cb2ef4fSOleksandr "Alex" Zinenko      : !transform.param<i32>, !transform.any_op
884cb2ef4fSOleksandr "Alex" Zinenko    transform.yield
894cb2ef4fSOleksandr "Alex" Zinenko  }
904cb2ef4fSOleksandr "Alex" Zinenko
914cb2ef4fSOleksandr "Alex" Zinenko  // This is also a matcher sequence. It is similarly given an operation to
924cb2ef4fSOleksandr "Alex" Zinenko  // match and nested operations must succeed in order for a match to be deemed
934cb2ef4fSOleksandr "Alex" Zinenko  // successful. It starts matching from the last operation in the use-def chain
944cb2ef4fSOleksandr "Alex" Zinenko  // and goes back because each operand (use) has exactly one definition.
954cb2ef4fSOleksandr "Alex" Zinenko  transform.named_sequence @match_matmul_elemwise(
964cb2ef4fSOleksandr "Alex" Zinenko      %last: !transform.any_op {transform.readonly})
974cb2ef4fSOleksandr "Alex" Zinenko      -> (!transform.any_op, !transform.any_op, !transform.any_op,
984cb2ef4fSOleksandr "Alex" Zinenko          !transform.param<i32>) {
994cb2ef4fSOleksandr "Alex" Zinenko    // The last operation must be an elementwise binary.
1004cb2ef4fSOleksandr "Alex" Zinenko    transform.match.operation_name %last ["linalg.elemwise_binary"]
1014cb2ef4fSOleksandr "Alex" Zinenko      : !transform.any_op
1024cb2ef4fSOleksandr "Alex" Zinenko
1034cb2ef4fSOleksandr "Alex" Zinenko    // One of its operands must be defined by another operation, to which we
1044cb2ef4fSOleksandr "Alex" Zinenko    // will get a handle here. This is achieved thanks to a newly defined
1054cb2ef4fSOleksandr "Alex" Zinenko    // operation that tries to match operands one by one using the match
1064cb2ef4fSOleksandr "Alex" Zinenko    // operations nested in its region.
1074cb2ef4fSOleksandr "Alex" Zinenko    %pos, %middle = transform.match.my.has_operand_satisfying %last
1084cb2ef4fSOleksandr "Alex" Zinenko        : (!transform.any_op) -> (!transform.param<i32>, !transform.any_op) {
1094cb2ef4fSOleksandr "Alex" Zinenko    ^bb0(%operand: !transform.any_value):
1104cb2ef4fSOleksandr "Alex" Zinenko      // The operand must be defined by an operation.
1114cb2ef4fSOleksandr "Alex" Zinenko      %def = transform.get_defining_op %operand
1124cb2ef4fSOleksandr "Alex" Zinenko        : (!transform.any_value) -> !transform.any_op
1134cb2ef4fSOleksandr "Alex" Zinenko      // The defining operation must itself be an elementwise binary.
1144cb2ef4fSOleksandr "Alex" Zinenko      transform.match.operation_name %def ["linalg.elemwise_binary"]
1154cb2ef4fSOleksandr "Alex" Zinenko        : !transform.any_op
1164cb2ef4fSOleksandr "Alex" Zinenko      transform.yield %def : !transform.any_op
1174cb2ef4fSOleksandr "Alex" Zinenko    }
1184cb2ef4fSOleksandr "Alex" Zinenko
1194cb2ef4fSOleksandr "Alex" Zinenko    // And the first operand of that operation must be defined by yet another
1204cb2ef4fSOleksandr "Alex" Zinenko    // operation.
1214cb2ef4fSOleksandr "Alex" Zinenko    %matmul = transform.get_producer_of_operand %middle[0]
1224cb2ef4fSOleksandr "Alex" Zinenko      : (!transform.any_op) -> !transform.any_op
1234cb2ef4fSOleksandr "Alex" Zinenko    // And that operation is a matmul.
1244cb2ef4fSOleksandr "Alex" Zinenko    transform.match.operation_name %matmul ["linalg.matmul"] : !transform.any_op
1254cb2ef4fSOleksandr "Alex" Zinenko    // We will yield the handles to the matmul and the two elementwise
1264cb2ef4fSOleksandr "Alex" Zinenko    // operations separately.
1274cb2ef4fSOleksandr "Alex" Zinenko    transform.yield %matmul, %middle, %last, %pos
1284cb2ef4fSOleksandr "Alex" Zinenko      : !transform.any_op, !transform.any_op, !transform.any_op,
1294cb2ef4fSOleksandr "Alex" Zinenko        !transform.param<i32>
1304cb2ef4fSOleksandr "Alex" Zinenko  }
1314cb2ef4fSOleksandr "Alex" Zinenko}
132