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