- Published on
IREE 编译命令逐项拆解
- Authors

- Name
- alan
本文档对以下完整编译命令中的每个参数进行逐一拆解,说明其作用、效果和生成的文件。
iree-compile simpy_conv.mlir \
--iree-hal-target-device=local \
--iree-hal-local-target-device-backends=llvm-cpu \
--iree-llvmcpu-target-cpu=host \
--iree-hal-dump-executable-files-to=cds_test/simpy_conv/dump_executeable \
--iree-hal-dump-executable-intermediates-to=cds_test/simpy_conv/intermediates \
--iree-hal-dump-executable-sources-to=cds_test/simpy_conv/exe-sources \
--iree-hal-dump-executable-binaries-to=cds_test/simpy_conv/exe-binaries \
--dump-compilation-phases-to=cds_test/simpy_conv/phases \
--mlir-print-ir-after-all \
--mlir-print-ir-tree-dir=cds_test/simpy_conv/print_ir \
-o simple_conv2d.vmfb
1. 输入与输出
simpy_conv.mlir(输入)
作用:指定要编译的 MLIR 中间表示文件。
内容:从 ONNX 模型转换而来的卷积层 IR,包含:
util.func public @mxnet_converted_model_extracted— 主函数- 权重常量(卷积 kernel 的 3×64×7×7 float32 数据)
linalg.conv_2d_nhwc_fhwi算子
-o simple_conv2d.vmfb(输出)
作用:指定最终编译产物 — IREE VMFB(Virtual Machine Bytecode)文件路径。
效果:生成可被 iree-run-module 或 Python Runtime 加载执行的字节码。
文件大小:约 52K(本例中)。
2. 目标设备配置
--iree-hal-target-device=local
作用:指定编译目标设备类型为 local(本地 CPU)。
效果:告诉 IREE 编译器生成在本地 CPU 上运行的代码,而非 GPU(CUDA/ROCm/Vulkan)或其他加速器。
可选值:
| 值 | 目标设备 |
|---|---|
local | 本地 CPU(多线程或单线程) |
cuda | NVIDIA GPU |
rocm | AMD GPU |
vulkan-spirv | Vulkan GPU |
metal-spirv | Apple GPU |
--iree-hal-local-target-device-backends=llvm-cpu
作用:在 local 设备下,指定具体的代码生成后端为 LLVM CPU。
效果:使用 LLVM 将 MLIR lowered 后的 IR 编译为机器码(x86_64 / ARM 等 ELF 格式)。
可选值:
| 值 | 说明 |
|---|---|
llvm-cpu | LLVM CPU 后端(生成原生机器码) |
vmvx | VMVX 字节码后端(可移植但性能较低) |
--iree-llvmcpu-target-cpu=host
作用:针对当前主机的 CPU 架构进行优化。
效果:编译器会探测当前 CPU 的架构(如 Apple Silicon 的 apple-m1 或 x86 的 skylake),生成利用该 CPU 特有指令集(如 AVX2、NEON)的代码。性能最优,但生成的二进制可能无法在其它 CPU 上运行。
对比:
| 值 | 说明 |
|---|---|
host | 针对当前 CPU 优化,性能最优 |
generic | 生成通用代码,可在任何同架构 CPU 运行,性能较差 |
3. 可执行文件导出(Dump Executable)
以下四个参数将编译过程中产生的 可执行单元(Executable) 的不同阶段产物导出到指定目录。IREE 会将模型中的计算算子(如卷积、矩阵乘法)编译为独立的 "dispatch" 可执行文件。
--iree-hal-dump-executable-files-to=cds_test/simpy_conv/dump_executeable
作用:导出可执行单元的最终文件。
生成的文件:
| 文件 | 说明 |
|---|---|
configured_module_mxnet_converted_model_extracted$async_dispatch_0.mlir | dispatch 0 的配置后 IR |
configured_module_mxnet_converted_model_extracted$async_dispatch_1.mlir | dispatch 1 的配置后 IR |
module_*_embedded_elf_x86_64_benchmark.mlir | 嵌入的 ELF 基准测试 IR |
用途:查看每个 dispatch 算子最终被编译成的机器码表示。dispatch_0 和 dispatch_1 分别对应模型中的不同计算核(如卷积主循环和 bias 添加)。
--iree-hal-dump-executable-intermediates-to=cds_test/simpy_conv/intermediates
作用:导出 LLVM 编译链路中的中间产物。
生成的文件:
| 文件 | 说明 |
|---|---|
*.codegen.ll | LLVM IR(代码生成阶段,优化前) |
*.codegen.bc | LLVM Bitcode(代码生成阶段,二进制格式) |
*.linked.ll | 链接后的 LLVM IR |
*.linked.bc | 链接后的 LLVM Bitcode |
*.optimized.ll | 优化后的 LLVM IR(经过 -O2/-O3) |
*.optimized.bc | 优化后的 LLVM Bitcode |
*.o | 目标文件(机器码) |
*.s | 汇编代码(人类可读的机器码) |
用途:
.s文件最重要:可以查看生成的具体汇编指令,分析向量化(AVX/NEON)、循环展开等优化效果。.ll文件:可以查看 LLVM IR 级别的优化。.o文件:最终链接进 VMFB 的机器码。
--iree-hal-dump-executable-sources-to=cds_test/simpy_conv/exe-sources
作用:导出可执行单元的 输入源 IR(即传给 LLVM 后端之前的 MLIR)。
生成的文件:
| 文件 | 说明 |
|---|---|
module_mxnet_converted_model_extracted$async_dispatch_0.mlir | dispatch 0 的源 IR |
module_mxnet_converted_model_extracted$async_dispatch_1.mlir | dispatch 1 的源 IR |
用途:查看 IREE 代码生成器(Codegen)准备提交给 LLVM 的 IR 长什么样。这是 HAL Executable dialect 的 IR,包含 hal.executable.variant 等信息。与 intermediates 中的 .ll 文件对比,可以看到 MLIR → LLVM IR 的转换。
--iree-hal-dump-executable-binaries-to=cds_test/simpy_conv/exe-binaries
作用:导出链接后的最终可执行二进制文件。
生成的文件:
| 文件 | 说明 |
|---|---|
module_simpy_conv_linked_embedded_elf_x86_64.so | 嵌入的 ELF 共享对象 |
用途:这是实际被加载到内存中执行的机器码二进制文件。可以用 nm、objdump、file 等工具分析:
file cds_test/simpy_conv/exe-binaries/*.so
nm cds_test/simpy_conv/exe-binaries/*.so
4. 编译阶段导出
--dump-compilation-phases-to=cds_test/simpy_conv/phases
作用:将整个编译流水线分为 12 个阶段,每个阶段导出一个 IR 快照。
生成的文件(按顺序):
| 序号 | 文件 | 阶段名称 | 说明 |
|---|---|---|---|
| 1 | simpy_conv.1.input.mlir | input | 原始输入 IR,未经任何处理 |
| 2 | simpy_conv.2.abi.mlir | abi | ABI(应用二进制接口)转换,确定函数签名 |
| 3 | simpy_conv.3.preprocessing.mlir | preprocessing | 预处理:常量折叠、死代码消除 |
| 4 | simpy_conv.4.global-optimization.mlir | global-optimization | 全局优化:算子融合、常量传播 |
| 5 | simpy_conv.5.dispatch-creation.mlir | dispatch-creation | 创建 dispatch:将算子分组为可并行执行的单元 |
| 6 | simpy_conv.6.flow.mlir | flow | Flow dialect:建模计算、分配和流 |
| 7 | simpy_conv.7.stream.mlir | stream | Stream dialect:设备放置、异步调度 |
| 8 | simpy_conv.8.executable-sources.mlir | executable-sources | 可执行源:准备编译为机器码的 dispatch |
| 9 | simpy_conv.9.executable-configurations.mlir | executable-configurations | 可执行配置:设置每个 dispatch 的编译参数 |
| 10 | simpy_conv.10.executable-targets.mlir | executable-targets | 可执行目标:指定目标后端 |
| 11 | simpy_conv.11.hal.mlir | hal | HAL dialect:硬件抽象层,缓冲区和管理 |
| 12 | simpy_conv.12.vm.mlir | vm | VM dialect:最终虚拟机字节码前的 IR |
用途:
- 调试编译问题的核心工具。如果编译失败或结果不对,逐个查看这些文件,定位是在哪个阶段出的问题。
- 对比相邻两个文件(如
5.dispatch-creation.mlirvs6.flow.mlir),可以理解某个 Pass 做了什么变换。 - 典型调试流程:从
12.vm.mlir倒着往前看,找到第一个"看起来不对"的文件,问题就在该阶段。
5. IR 打印
--mlir-print-ir-after-all
作用:在 每一个 MLIR Pass 执行完毕后,将当前完整的 IR 打印到 stderr。
效果:
- 输出量巨大(本例产生了 277 个文件)。
- 每个文件以 Pass 编号和名称命名,如
45_iree-flow-collapse-reduction.mlir。 - stderr 输出时会夹杂大量
// -----//分隔符。
与 --dump-compilation-phases-to 的区别:
| 参数 | 粒度 | 文件数 | 用途 |
|---|---|---|---|
--dump-compilation-phases-to | 粗(12 个大阶段) | 12 | 定位大阶段问题 |
--mlir-print-ir-after-all | 细(每个 Pass) | 277+ | 精确定位具体 Pass 问题 |
--mlir-print-ir-tree-dir=cds_test/simpy_conv/print_ir
作用:将 --mlir-print-ir-after-all 的输出写入指定目录,而不是打印到 stderr。
生成的文件:
- 目录结构:
print_ir/builtin_module_no-symbol-name/<序号>_<pass名称>.mlir - 本例共 277 个文件,从
1_torch-reify-shape-calculations.mlir到277(最后的 VM 模块)。 - 末尾还有一些子目录,如
hal_executable_*、util_func_*、vm_module_*等,对应不同 IR 组件的变换过程。
典型文件序列示例:
1 torch-reify-shape-calculations # Torch Shape 推导
10 iree-auto-input-conversion # 自动输入转换
11 iree-import-public # 导入 public 符号
14 iree-import-ml-prog # 导入 ml_program dialect
50+ iree-flow-* # Flow dialect 变换
100+ iree-stream-* # Stream dialect 变换
120+ iree-util-* # Util 变换
200+ hal-* # HAL lowering
250+ vm-* # VM bytecode 生成
用途:
- 精确定位哪个 Pass 引入了问题。
- 学习 IREE 编译管线:从头到尾阅读这些文件可以理解 ONNX 模型如何一步步变成 VM 字节码。
- 搜索特定关键字(如
linalg.conv)追踪卷积算子在各阶段的表示。
6. 整体编译流程图
simpy_conv.mlir (ONNX 转换来的 MLIR)
│
▼
┌─────────────────────────────────────────┐
│ Phase 1-4: 输入 → 预处理 → 全局优化 │ ← phases/*.1-4.mlir
│ (常量折叠、算子融合、ABI 转换) │
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Phase 5-7: Dispatch → Flow → Stream │ ← phases/*.5-7.mlir
│ (算子分组、设备放置、异步调度) │
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Phase 8-10: Executable 准备 │ ← phases/*.8-10.mlir
│ (源导出、配置、目标设定) │ ← exe-sources/*.mlir
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Phase 11-12: HAL → VM │ ← phases/*.11-12.mlir
│ (硬件抽象、虚拟机表示) │
└─────────────────────────────────────────┘
│
├─── 每个 dispatch ────────────────────┐
│ ▼
│ ┌──────────────────────────────┐ │
│ │ MLIR → LLVM IR → 机器码 │ │ ← intermediates/*.ll, *.bc, *.s, *.o
│ └──────────────────────────────┘ │
│ │
│ ┌──────────────────────────────┐ │
│ │ 链接为 ELF 共享对象 │ │ ← exe-binaries/*.so
│ └──────────────────────────────┘ │
│ │
│ ┌──────────────────────────────┐ │
│ │ 最终可执行文件导出 │ │ ← dump_executeable/*.mlir
│ └──────────────────────────────┘ │
└───────────────────────────────────────┘
│
▼
simple_conv2d.vmfb (IREE VM 字节码)
7. 常用组合建议
| 目的 | 推荐参数组合 |
|---|---|
| 快速编译 | 仅需 -o + 三个 target 参数 |
| 定位编译问题 | 加 --dump-compilation-phases-to= |
| 精确定位 Pass 问题 | 加 --mlir-print-ir-after-all + --mlir-print-ir-tree-dir= |
| 分析生成的机器码 | 加 --iree-hal-dump-executable-intermediates-to=(看 .s 文件) |
| 分析 dispatch 划分 | 加 --iree-hal-dump-executable-sources-to= |
| 全面调试 | 全部加上(如本命令) |