@@ -133,7 +133,7 @@ This will generate two files, `MyExtension.h.inc` and `MyExtension.cpp.inc`, tha
133133``` c++
134134// In MyExtension.cpp.
135135
136- #include " MyExtension.h. "
136+ #include " MyExtension.h"
137137
138138#define GET_OP_CLASSES
139139#include " MyExtension.cpp.inc"
@@ -247,8 +247,7 @@ must be modified with the provided rewriter.
247247 return diag;
248248 }
249249
250- // Use rewriter to modify the callee in place.
251- rewriter.modifyOpInPlace(call, [&]() { call.setCallee(getNewTarget()); });
250+ updateCallee(call, getNewTarget());
252251 }
253252
254253 // If everything went well, return success.
@@ -266,7 +265,7 @@ void ChangeCallTargetOp::getEffects(
266265 // Indicate that the `call` handle is only read by this operation because the
267266 // associated operation is not erased but rather modified in-place, so the
268267 // reference to it remains valid.
269- onlyReadsHandle(this->getOperation()->getOpOperands().front (), effects);
268+ onlyReadsHandle(getCall (), effects);
270269
271270 // Indicate that the payload is modified by this operation.
272271 modifiesPayload(effects);
@@ -286,20 +285,20 @@ void registerMyExtension(::mlir::DialectRegistry ®istry) {
286285}
287286```
288287
289- After registering the extension, it becomes possible to use our new operation in the Transform dialect interpreter. The upstream testing pass can be used as is.
288+ After registering the extension, it becomes possible to use our new operation in the Transform dialect interpreter. The upstream testing pass can be used as is. It actually exists in `mlir/test/Examples/transform/Ch2/sequence.mlir`, which contains the `microkernel` implementation.
290289
291290```mlir
292291module attributes {transform.with_named_sequence} {
293292 transform.named_sequence @__transform_main(
294- %arg0: !transform.any_op,
295- %arg1: !transform.op<"linalg.matmul">,
296- %arg2: !transform.op<"linalg.elementwise">) {
293+ %arg0: !transform.any_op,
294+ %arg1: !transform.op<"linalg.matmul">,
295+ %arg2: !transform.op<"linalg.elementwise">) {
297296 // Since the %arg2 handle is associated with both elementwise operations,
298297 // we need to split it into two handles so we can target only the second
299298 // elementwise operation.
300299 %add, %max = transform.split_handle %arg2
301300 : (!transform.op<"linalg.elementwise">)
302- -> (!transform.any_op, !transform.any_op)
301+ -> (!transform.any_op, !transform.any_op)
303302
304303 // The actual tiling transformation takes tile sizes as attributes. It
305304 // produces a handle to the loop generated during tiling.
@@ -308,63 +307,50 @@ module attributes {transform.with_named_sequence} {
308307 : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
309308
310309 // We can now fuse the other operations into the loop. Here, we fuse
311- // operations one by one. This requires the operation that is being fused to
312- // define the value used within the loop, so the order of such fusions is
313- // important. We could also use "transform.merge_handles" to obtain a single
314- // handle to all operations and give it to `fuse_into_containing_op` that
315- // would take care of the ordering in this case.
316- %add_fused, %loop_0 =
317- transform.structured.fuse_into_containing_op %add into %loop
318- : (!transform.any_op, !transform.any_op)
319- -> (!transform.any_op, !transform.any_op)
320- %matmul_fused, %loop_1 =
321- transform.structured.fuse_into_containing_op %arg1 into %loop_0
322- : (!transform.op<"linalg.matmul">, !transform.any_op)
323- -> (!transform.any_op, !transform.any_op)
310+ // operations one-by-one. This requires the operation that is being fused
311+ // to define the value used within the loop, so the order of such fusions
312+ // is important. We could also use "transform.merge_handles" to obtain
313+ // a single handle to all operations and give it to
314+ // `fuse_into_containing_op` that would take care of the ordering in this
315+ // case.
316+ %add_fused, %loop2 = transform.structured.fuse_into_containing_op %add into %loop
317+ : (!transform.any_op, !transform.any_op) -> (!transform.any_op, !transform.any_op)
318+ %matmul_fused, %loop3 = transform.structured.fuse_into_containing_op %arg1
319+ into %loop2
320+ : (!transform.op<"linalg.matmul">, !transform.any_op)
321+ -> (!transform.any_op, !transform.any_op)
324322
325323 // Tile again to get the desired size. Note that this time this tiles the
326324 // "add" operation and fuses matmul into the loop, but doesn't affect the
327325 // "max" operation. This illustrates the precise targeting with the
328326 // transform dialect. Otherwise, it is difficult to differentiate "add" and
329327 // "max", both of which having the same kind.
330- %tiled_2, %loop_2 =
331- transform.structured.tile_using_forall %add_fused tile_sizes [4, 4]
332- : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
333- %matmul_fused_2, %loop_3 =
334- transform.structured.fuse_into_containing_op %matmul_fused into %loop_2
335- : (!transform.any_op, !transform.any_op)
336- -> (!transform.any_op, !transform.any_op)
328+ %tiled_second, %loop_second = transform.structured.tile_using_forall %add_fused
329+ tile_sizes [4, 4]
330+ : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
331+ %matmul_fused_2, %loop_second_2 = transform.structured.fuse_into_containing_op %matmul_fused
332+ into %loop_second
333+ : (!transform.any_op, !transform.any_op) -> (!transform.any_op, !transform.any_op)
337334
338335 // Since outlining is currently only implemented for region-holding
339336 // operations such as loops, use tiling to size 1 to materialize the outer
340337 // loop that is going to be outlined.
341- %_, %outline_target =
342- transform.structured.tile_using_forall %tiled_2 tile_sizes [1]
343- : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
344- transform.structured.fuse_into_containing_op %matmul_fused_2
345- into %outline_target
346- : (!transform.any_op, !transform.any_op)
347- -> (!transform.any_op, !transform.any_op)
338+ %_0, %loop_third = transform.structured.tile_using_forall %tiled_second tile_sizes [1]
339+ : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
340+ %_1, %outline_target = transform.structured.fuse_into_containing_op %matmul_fused_2 into %loop_third
341+ : (!transform.any_op, !transform.any_op) -> (!transform.any_op, !transform.any_op)
348342 %func, %call = transform.loop.outline %outline_target
349343 {func_name = "outlined"}
350- : (!transform.any_op) -> (!transform.any_op, !transform.op<"func.call"> )
344+ : (!transform.any_op) -> (!transform.any_op, !transform.any_op )
351345
352346 // Rewrite the call target.
353- transform.my.change_call_target %call, "microkernel" : !transform.op<"func.call">
347+ transform.my.change_call_target %call, "microkernel" : !transform.any_op
348+
354349 transform.yield
355350 }
356351}
357352```
358353
359- When you run it with the interpreter, it produces the following error.
360-
361- ```
362- sequence.mlir:7:8: error: 'func.call' op 'microkernel' does not reference a valid function
363- %1 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%0, %arg2 : tensor<512x512xf32>, tensor<512x512xf32>) outs(%arg3 : tensor<512x512xf32>) -> tensor<512x512xf32>
364- ^
365- sequence.mlir:7:8: note: see current operation: %39 = "func.call"(%32, %33, %34, %36, %37) <{callee = @microkernel}> : (tensor<4x512xf32>, tensor<512x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xf32>
366- ```
367-
368354## Appendix: Autogenerated Documentation
369355
370356[ include "Tutorials/transform/MyExtensionCh2.md"]
0 commit comments