[Mlir-commits] [mlir] [mlir][transform] Fix ch2 and additional documentation (PR #148407)

Oleksandr Alex Zinenko llvmlistbot at llvm.org
Sun Jul 13 23:09:36 PDT 2025


================
@@ -288,67 +291,80 @@ After registering the extension, it becomes possible to use our new operation in
 ```mlir
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(
-      %arg0: !transform.any_op,
-      %arg1: !transform.op<"linalg.matmul">,
-      %arg2: !transform.op<"linalg.elementwise">) {
+       %arg0: !transform.any_op,
+       %arg1: !transform.op<"linalg.matmul">,
+       %arg2: !transform.op<"linalg.elementwise">) {
     // Since the %arg2 handle is associated with both elementwise operations,
     // we need to split it into two handles so we can target only the second
     // elementwise operation.
     %add, %max = transform.split_handle %arg2
         : (!transform.op<"linalg.elementwise">)
-        -> (!transform.any_op, !transform.any_op)
+          -> (!transform.any_op, !transform.any_op)
 
     // The actual tiling transformation takes tile sizes as attributes. It
     // produces a handle to the loop generated during tiling.
-    %loop, %tiled = transform.structured.tile_using_forall %max
+    %tiled, %loop = transform.structured.tile_using_forall %max
                     tile_sizes [8, 32]
         : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
 
     // We can now fuse the other operations into the loop. Here, we fuse
-    // operations one-by-one. This requires the operation that is being fused
-    // to define the value used within the loop, so the order of such fusions
-    // is important. We could also use "transform.merge_handles" to obtain
-    // a single handle to all operations and give it to
-    // `fuse_into_containing_op` that would take care of the ordering in this
-    // case.
-    %add_fused = transform.structured.fuse_into_containing_op %add into %loop
-        : (!transform.any_op, !transform.any_op) -> !transform.any_op
-    %matmul_fused = transform.structured.fuse_into_containing_op %arg1
-                    into %loop
-        : (!transform.op<"linalg.matmul">, !transform.any_op)
-       -> !transform.any_op
+    // operations one by one. This requires the operation that is being fused to
+    // define the value used within the loop, so the order of such fusions is
+    // important. We could also use "transform.merge_handles" to obtain a single
+    // handle to all operations and give it to `fuse_into_containing_op` that
+    // would take care of the ordering in this case.
+    %add_fused, %loop_0 =
+        transform.structured.fuse_into_containing_op %add into %loop
+          : (!transform.any_op, !transform.any_op)
+            -> (!transform.any_op, !transform.any_op)
+    %matmul_fused, %loop_1 =
+        transform.structured.fuse_into_containing_op %arg1 into %loop_0
+          : (!transform.op<"linalg.matmul">, !transform.any_op)
+            -> (!transform.any_op, !transform.any_op)
 
     // Tile again to get the desired size. Note that this time this tiles the
     // "add" operation and fuses matmul into the loop, but doesn't affect the
     // "max" operation. This illustrates the precise targeting with the
     // transform dialect. Otherwise, it is difficult to differentiate "add" and
     // "max", both of which having the same kind.
-    %loop_2, %tiled_2 = transform.structured.tile_using_forall %add_fused
-                        tile_sizes [4, 4]
-        : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
-    %matmul_fused_2 = transform.structured.fuse_into_containing_op %matmul_fused
-                      into %loop_2
-        : (!transform.any_op, !transform.any_op) -> !transform.any_op
+    %tiled_2, %loop_2 =
+        transform.structured.tile_using_forall %add_fused tile_sizes [4, 4]
+          : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
+    %matmul_fused_2, %loop_3 =
+        transform.structured.fuse_into_containing_op %matmul_fused into %loop_2
+          : (!transform.any_op, !transform.any_op)
+            -> (!transform.any_op, !transform.any_op)
 
     // Since outlining is currently only implemented for region-holding
     // operations such as loops, use tiling to size 1 to materialize the outer
     // loop that is going to be outlined.
-    %outline_target, %_ = transform.structured.tile_using_forall %tiled_2 tile_sizes [1]
-        : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
-    transform.structured.fuse_into_containing_op %matmul_fused_2 into %outline_target
-        : (!transform.any_op, !transform.any_op) -> !transform.any_op
+    %_, %outline_target =
+        transform.structured.tile_using_forall %tiled_2 tile_sizes [1]
+          : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
+    transform.structured.fuse_into_containing_op %matmul_fused_2
+        into %outline_target
+          : (!transform.any_op, !transform.any_op)
+            -> (!transform.any_op, !transform.any_op)
     %func, %call = transform.loop.outline %outline_target
                    {func_name = "outlined"}
-        : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
+        : (!transform.any_op) -> (!transform.any_op, !transform.op<"func.call">)
 
     // Rewrite the call target.
-    transform.my.change_call_target %call, "microkernel" : !transform.any_op
-
+    transform.my.change_call_target %call, "microkernel" : !transform.op<"func.call">
     transform.yield
   }
 }
 ```
 
+When you run it with the interpreter, it produces the following error.
+
+```
+sequence.mlir:7:8: error: 'func.call' op 'microkernel' does not reference a valid function
+  %1 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%0, %arg2 : tensor<512x512xf32>, tensor<512x512xf32>) outs(%arg3 : tensor<512x512xf32>) -> tensor<512x512xf32>
+       ^
+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>
+```
+
----------------
ftynse wrote:

This part is a rather bad ending for the chapter: it ends on an error that is not resolved in the next chapters. The _[actual test](https://github.com/llvm/llvm-project/blob/374d5da214ba8017614c350e9fe4688cdc79d5f5/mlir/test/Examples/transform/Ch2/sequence.mlir#L51-L56)_ has a declaration for the function so this error never happens. My thinking with this text was to explain important parts of the IR, not have people copy-paste snippets. MLIR is verbose, so it felt better to not include full examples verbatim but rather put a link to them. Maybe if it is worth spelling out somewhere in a way that would make it more obvious.

https://github.com/llvm/llvm-project/pull/148407


More information about the Mlir-commits mailing list