Open akmaru opened 1 year ago
tosa-to-arith
も追加すると、 tosa.const
もconversionされるようになった。
./bin/mlir-opt -pass-pipeline="builtin.module(func.func(tosa-to-linalg-named))" conv-bn-relu.mlir | ./bin/mlir-opt -pass-pipeline="builtin.module(func.func(tosa-to-linalg))" | ./bin/mlir-opt -pass-pipeline="builtin.module(func.func(tosa-to-arith))"
#map = affine_map<(d0, d1, d2, d3) -> (d3, d0, d1, d2)>
#map1 = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)>
#map2 = affine_map<(d0, d1, d2, d3) -> (d3)>
module {
func.func @conv_bn_relu(%arg0: tensor<1x224x224x3xf32>, %arg1: tensor<64x3x3x3xf32>, %arg2: tensor<64xf32>) -> tensor<1x224x224x64xf32> {
%cst = arith.constant 0.000000e+00 : f32
%padded = tensor.pad %arg0 low[0, 1, 1, 0] high[0, 1, 1, 0] {
^bb0(%arg3: index, %arg4: index, %arg5: index, %arg6: index):
tensor.yield %cst : f32
} : tensor<1x224x224x3xf32> to tensor<1x226x226x3xf32>
%cst_0 = arith.constant dense<[1, 2, 3, 0]> : tensor<4xi64>
%0 = tensor.empty() : tensor<3x3x3x64xf32>
%1 = linalg.generic {indexing_maps = [#map, #map1], iterator_types = ["parallel", "parallel", "parallel", "parallel"]} ins(%arg1 : tensor<64x3x3x3xf32>) outs(%0 : tensor<3x3x3x64xf32>) {
^bb0(%in: f32, %out: f32):
linalg.yield %in : f32
} -> tensor<3x3x3x64xf32>
%2 = tensor.empty() : tensor<1x224x224x64xf32>
%cst_1 = arith.constant 0.000000e+00 : f32
%3 = linalg.fill ins(%cst_1 : f32) outs(%2 : tensor<1x224x224x64xf32>) -> tensor<1x224x224x64xf32>
%4 = tensor.empty() : tensor<1x224x224x64xf32>
%5 = linalg.conv_2d_nhwc_hwcf {dilations = dense<1> : tensor<2xi64>, strides = dense<1> : tensor<2xi64>} ins(%padded, %1 : tensor<1x226x226x3xf32>, tensor<3x3x3x64xf32>) outs(%3 : tensor<1x224x224x64xf32>) -> tensor<1x224x224x64xf32>
%6 = linalg.generic {indexing_maps = [#map2, #map1, #map1], iterator_types = ["parallel", "parallel", "parallel", "parallel"]} ins(%arg2, %5 : tensor<64xf32>, tensor<1x224x224x64xf32>) outs(%4 : tensor<1x224x224x64xf32>) {
^bb0(%in: f32, %in_3: f32, %out: f32):
%9 = arith.addf %in, %in_3 : f32
linalg.yield %9 : f32
} -> tensor<1x224x224x64xf32>
%cst_2 = arith.constant dense<0.000000e+00> : tensor<1x224x224x64xf32>
%7 = tensor.empty() : tensor<1x224x224x64xf32>
%8 = linalg.generic {indexing_maps = [#map1, #map1, #map1], iterator_types = ["parallel", "parallel", "parallel", "parallel"]} ins(%6, %cst_2 : tensor<1x224x224x64xf32>, tensor<1x224x224x64xf32>) outs(%7 : tensor<1x224x224x64xf32>) {
^bb0(%in: f32, %in_3: f32, %out: f32):
%9 = arith.maxf %in, %in_3 : f32
linalg.yield %9 : f32
} -> tensor<1x224x224x64xf32>
return %8 : tensor<1x224x224x64xf32>
}
}
-debug
オプションを付与すると、debug logが出力される。
VSCode上でdebugするための、launch.jsonを作成した。
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) mlir-opt",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/mlir-opt",
"args": [
"-debug",
"-pass-pipeline=builtin.module(func.func(tosa-to-linalg-named))",
"build/conv-bn-relu.mlir"
],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"linux": {
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
}
]
}
DialectConversion時の主要なcallstackは下記のようになっている。
下記のように、 func.func 内に複数のpassをcomma区切りで記述することができるらしい。
./bin/mlir-opt -debug -pass-pipeline="builtin.module(func.func(tosa-to-linalg-named,tosa-to-linalg,tosa-to-arith))" conv-bn-relu.mlir
tosa::addTosaToLinalgPassesにTosa -> Linalg にConversionする際のpassが一通り記述されている。
void mlir::tosa::addTosaToLinalgPasses(OpPassManager &pm,
bool disableTosaDecompositions) {
// Optional decompositions are designed to benefit linalg.
if (!disableTosaDecompositions)
pm.addNestedPass<func::FuncOp>(tosa::createTosaOptionalDecompositions());
pm.addNestedPass<func::FuncOp>(createCanonicalizerPass());
pm.addNestedPass<func::FuncOp>(tosa::createTosaMakeBroadcastablePass());
pm.addNestedPass<func::FuncOp>(tosa::createTosaToLinalgNamed());
pm.addNestedPass<func::FuncOp>(createCanonicalizerPass());
// TODO: Remove pass that operates on const tensor and enable optionality
pm.addNestedPass<func::FuncOp>(tosa::createTosaLayerwiseConstantFoldPass());
pm.addNestedPass<func::FuncOp>(tosa::createTosaMakeBroadcastablePass());
pm.addNestedPass<func::FuncOp>(tosa::createTosaValidationPass());
pm.addNestedPass<func::FuncOp>(tosa::createTosaToLinalg());
}
conversionに関するPassとその名前は include/mlir/Conversion/Passes.td で定義されている。
Linalg特有のPassとその名前は include/mlir/Dialect/Linalg/Passes.tdで定義されている。
linalg-fuse-elementwise-ops
を試してみる。
./bin/mlir-opt -pass-pipeline="builtin.module(func.func(linalg-fuse-elementwise-ops))" conv-bn-relu-linalg.mlir
下記のように、addf(biasの加算)とmaxf(reluのmax)がgenerics内にfuseされているのがわかる。
%6 = linalg.generic {indexing_maps = [#map2, #map1, #map1], iterator_types = ["parallel", "parallel", "parallel", "parallel"]} ins(%arg2, %4 : tensor<64xf32>, tensor<1x224x224x64xf32>) outs(%5 : tensor<1x224x224x64xf32>) {
^bb0(%in: f32, %in_0: f32, %out: f32):
%7 = arith.addf %in, %in_0 : f32
%8 = arith.maxf %7, %cst : f32
linalg.yield %8 : f32
} -> tensor<1x224x224x64xf32>
TOSA -> Linalg へのconversion
下記の内容を
conv-relu.mlir
として保存した。下記のコマンドで linalg へのconversion
下記のようなIRが得られた。