Skip to content

Commit 58e8cd4

Browse files
fix example code and additional documentation.
1 parent 962d99a commit 58e8cd4

File tree

1 file changed

+33
-47
lines changed
  • mlir/docs/Tutorials/transform

1 file changed

+33
-47
lines changed

mlir/docs/Tutorials/transform/Ch2.md

Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -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 &registry) {
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
292291
module 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

Comments
 (0)