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