[Mlir-commits] [mlir] [mlir][transform] Fix transform dialect tutorial chapter 1 (PR #147983)
lonely eagle
llvmlistbot at llvm.org
Thu Jul 10 08:14:52 PDT 2025
https://github.com/linuxlonelyeagle created https://github.com/llvm/llvm-project/pull/147983
In the transform dialect tutorial chapter 1, there were some errors that prevented the example from running. This PR fixes them.
>From 506d3a233d5be2f123445c0d4978090482d68634 Mon Sep 17 00:00:00 2001
From: linuxlonelyeagle <2020382038 at qq.com>
Date: Thu, 10 Jul 2025 15:10:45 +0000
Subject: [PATCH] fix transform dialect tutorial ch1.
---
mlir/docs/Tutorials/transform/Ch1.md | 48 +++++++++++++++++-----------
1 file changed, 29 insertions(+), 19 deletions(-)
diff --git a/mlir/docs/Tutorials/transform/Ch1.md b/mlir/docs/Tutorials/transform/Ch1.md
index 7463a9afbe97e..c83aa9a8e3961 100644
--- a/mlir/docs/Tutorials/transform/Ch1.md
+++ b/mlir/docs/Tutorials/transform/Ch1.md
@@ -11,6 +11,9 @@ The application of transform IR always starts from one top-level operation. In t
Let us illustrate this with a simple sequence of transformations on the common “fully connected + bias + ReLU” ML layer, which boils down to performing a matrix multiplication, followed by an (elementwise) matrix addition and taking an elementwise maximum with 0. This can be expressed using the following IR:
```mlir
+#map0 = affine_map<(d0, d1) -> (d0, d1)>
+#map1 = affine_map<(do, d1) -> ()>
+
func.func @fc_relu(%lhs: tensor<512x512xf32>, %rhs: tensor<512x512xf32>,
%bias: tensor<512x512xf32>, %output: tensor<512x512xf32>)
-> tensor<512x512xf32> {
@@ -26,6 +29,7 @@ func.func @fc_relu(%lhs: tensor<512x512xf32>, %rhs: tensor<512x512xf32>,
// Elementwise max with 0 (ReLU).
%c0f = arith.constant 0.0 : f32
%relued = linalg.elementwise kind=#linalg.elementwise_kind<max_signed>
+ indexing_maps = [#map0, #map1, #map0]
ins(%biased, %c0f : tensor<512x512xf32>, f32)
outs(%output : tensor<512x512xf32>) -> tensor<512x512xf32>
func.return %relued : tensor<512x512xf32>
@@ -95,18 +99,18 @@ $ mlir-opt sequence.mlir --pass-pipeline="
The `sequence.mlir` file contains _both_ the payload IR function _and_ the transform IR sequence nested in the same module. The transform interpreter pass will apply the `@__transform_main` named sequence to the anchor operation of the pass. In our case, we also asked the interpreter pass to associate the two extra arguments of the top-level sequence with all `linalg.matmul` and `linalg.elementwise` payload operations through the respective pass options. Running this pass results in the expected remarks:
```sh
-sequence.mlir:7:13: remark: matmul
+test.mlir:8:13: remark: matmul
%matmul = linalg.matmul ins(%lhs, %rhs: tensor<512x512xf32>, tensor<512x512xf32>)
^
-sequence.mlir:7:13: note: see current operation: %0 = linalg.matmul ins(%arg0, %arg1 : tensor<512x512xf32>, tensor<512x512xf32>) outs(%arg3 : tensor<512x512xf32>) -> tensor<512x512xf32>
-sequence.mlir:10:13: remark: elemwise_binaries
+test.mlir:8:13: note: see current operation: %0 = linalg.matmul ins(%arg0, %arg1 : tensor<512x512xf32>, tensor<512x512xf32>) outs(%arg3 : tensor<512x512xf32>) -> tensor<512x512xf32>
+test.mlir:12:13: remark: elemwise_binaries
%biased = linalg.elementwise kind=#linalg.elementwise_kind<add>
^
-sequence.mlir:10:13: note: see current operation: %1 = linalg.elementwise kind=#linalg.elementwise_kind<add>> ins(%0, %arg2 : tensor<512x512xf32>, tensor<512x512xf32>) outs(%arg3 : tensor<512x512xf32>) -> tensor<512x512xf32>
-sequence.mlir:14:13: remark: elemwise_binaries
+test.mlir:12:13: note: see current operation: %1 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%0, %arg2 : tensor<512x512xf32>, tensor<512x512xf32>) outs(%arg3 : tensor<512x512xf32>) -> tensor<512x512xf32>
+test.mlir:19:13: remark: elemwise_binaries
%relued = linalg.elementwise kind=#linalg.elementwise_kind<max_signed>
^
-sequence.mlir:14:13: note: see current operation: %2 = linalg.elementwise kind=#linalg.elementwise_kind<max_signed>> ins(%1, %cst : tensor<512x512xf32>, f32) outs(%arg3 : tensor<512x512xf32>) -> tensor<512x512xf32>
+test.mlir:19:13: note: see current operation: %2 = linalg.elementwise kind=#linalg.elementwise_kind<max_signed> indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>, affine_map<(d0, d1) -> ()>, affine_map<(d0, d1) -> (d0, d1)>] ins(%1, %cst : tensor<512x512xf32>, f32) outs(%arg3 : tensor<512x512xf32>) -> tensor<512x512xf32>
```
Note that `%arg2` is associated with both elementwise payload operations. Any handle is associated with a list of entities. Individual transformations may or may not care about the order of elements in that list.
@@ -140,33 +144,39 @@ The transformation returns two handles, as indicated in its [documentation](http
Running this transformation with the same command as above expectedly produces the tiled code.
```mlir
+#map = affine_map<(d0) -> (d0 * 4)>
+#map1 = affine_map<(d0) -> (d0 * 32)>
+#map2 = affine_map<(d0, d1) -> (d0, d1)>
+#map3 = affine_map<(d0, d1) -> ()>
+
func.func @fc_relu(%arg0: tensor<512x512xf32>,
- %arg1: tensor<512x512xf32>,
+ %arg1: tensor<512x512xf32>,
%arg2: tensor<512x512xf32>,
%arg3: tensor<512x512xf32>) -> tensor<512x512xf32> {
- %cst = arith.constant 0.000000e+00 : f32
%0 = scf.forall (%arg4, %arg5) in (128, 16) shared_outs(%arg6 = %arg3) -> (tensor<512x512xf32>) {
- %3 = affine.apply affine_map<(d0) -> (d0 * 4)>(%arg4)
- %4 = affine.apply affine_map<(d0) -> (d0 * 32)>(%arg5)
+ %3 = affine.apply #map(%arg4)
+ %4 = affine.apply #map1(%arg5)
%extracted_slice = tensor.extract_slice %arg0[%3, 0] [4, 512] [1, 1]
: tensor<512x512xf32> to tensor<4x512xf32>
%extracted_slice_0 = tensor.extract_slice %arg1[0, %4] [512, 32] [1, 1]
- : tensor<512x512xf32> to tensor<512x32xf32>
+ : tensor<512x512xf32> to tensor<512x32xf32>
%extracted_slice_1 = tensor.extract_slice %arg6[%3, %4] [4, 32] [1, 1]
- : tensor<512x512xf32> to tensor<4x32xf32>
+ : tensor<512x512xf32> to tensor<4x32xf32>
%5 = linalg.matmul
ins(%extracted_slice, %extracted_slice_0
- : tensor<4x512xf32>, tensor<512x32xf32>)
+ : tensor<4x512xf32>, tensor<512x32xf32>)
outs(%extracted_slice_1 : tensor<4x32xf32>) -> tensor<4x32xf32>
scf.forall.in_parallel {
tensor.parallel_insert_slice %5 into %arg6[%3, %4] [4, 32] [1, 1]
- : tensor<4x32xf32> into tensor<512x512xf32>
+ : tensor<4x32xf32> into tensor<512x512xf32>
}
}
- %1 = linalg.elementwise kind=#linalg.elementwise_kind<add>>
- ins(%0, %arg2 : tensor<512x512xf32>, tensor<512x512xf32>)
- outs(%arg3 : tensor<512x512xf32>) -> tensor<512x512xf32>
- %2 = linalg.elementwise kind=#linalg.elementwise_kind<max_signed>>
+ %1 = linalg.elementwise kind=#linalg.elementwise_kind<add>
+ ins(%0, %arg2 : tensor<512x512xf32>, tensor<512x512xf32>)
+ outs(%arg3 : tensor<512x512xf32>) -> tensor<512x512xf32>
+ %cst = arith.constant 0.000000e+00 : f32
+ %2 = linalg.elementwise kind=#linalg.elementwise_kind<max_signed>
+ indexing_maps = [#map2, #map3, #map2]
ins(%1, %cst : tensor<512x512xf32>, f32)
outs(%arg3 : tensor<512x512xf32>) -> tensor<512x512xf32>
return %2 : tensor<512x512xf32>
@@ -216,7 +226,7 @@ One may observe that some operations such as `transform.cast` do not consume the
```mlir
module attributes {transform.with_named_sequence} {
- transform.named_sequence @__transform_main
+ transform.named_sequence @__transform_main(
%arg0: !transform.any_op,
%arg1: !transform.op<"linalg.matmul">,
%arg2: !transform.op<"linalg.elementwise">) {
More information about the Mlir-commits
mailing list