# 阶段 6:Codegen(可执行体 lowering)✅ > 2026-08-15。对应规划阶段 6。源码:`src/iree/compiler/src/iree/compiler/Codegen/`。 > **这是你之前接触过的部分,重点是建立「MLIR pass ↔ TVM schedule」的映射。** ## 1. Codegen 的职责 把 HAL 层交给它的 `flow.executable`(内含 linalg 计算)lowering 成设备代码(LLVM IR / SPIR-V)。 由 HAL 的 TargetBackend 触发(见 [07-hal.md](07-hal.md) 第 3 节)。 按后端组织: - `LLVMCPU/` —— CPU(x86/ARM) - `LLVMGPU/` —— GPU(CUDA via NVVM、ROCm via ROCDL) - `SPIRV/` —— Vulkan - `VMVX/` —— 简单可移植参考后端 - `WGSL/` —— WebGPU - `Common/` —— 跨后端共享逻辑 ## 2. 关键 lowering 链(LLVMCPU,来自阶段 2 pass 序列) ``` LLVMCPUSelectLoweringStrategy # 选 tiling/向量化策略(对应 TVM 选 schedule) → TileAndDistributeToWorkgroups # workgroup 级 tiling → LLVMCPUTileAndFuseProducerConsumer # tile-and-fuse(对应 TVM 的 compute_at + fuse) → LLVMCPUTile # tiling → LLVMCPUPeel # loop peeling → LLVMCPUTileToVectorSize # tile 到向量大小 → GenericVectorization # 向量化(对应 TVM 的 vectorize) → IREEComprehensiveBufferize # bufferize:tensor → memref(对应 TVM storage lowering) → LLVMCPUVirtualVectorLowering # 向量 lowering → ConvertToLLVM # 转 LLVM IR ``` ## 3. MLIR pass ↔ TVM schedule 对照(你的主场) | TVM 0.6 schedule 原语 | IREE codegen 的 MLIR pass | |---|---| | `split`(循环拆分) | `LLVMCPUTile` + `LLVMCPUTileToVectorSize` | | `reorder`(循环重排) | tiling pass 里隐含 | | `fuse` + `compute_at` | `LLVMCPUTileAndFuseProducerConsumer` | | `vectorize` | `GenericVectorization` | | `unroll` | `LLVMCPUPeel` + 向量 lowering | | buffer 分配 / storage | `IREEComprehensiveBufferize`(tensor→memref) | | codegen(LLVM/CUDA) | `ConvertToLLVM` / `ConvertToNVVM` / `ConvertToROCDL` | **核心差异**:TVM 的 schedule 是**用户手写/自动搜索**的显式变换序列;IREE 的 codegen 是 **声明式 pass pipeline**,策略由 `LLVMCPUSelectLoweringStrategy` 基于 op 类型/shape 自动选择。 (IREE 也有 `transform` dialect 支持手写 schedule,但那是在 linalg 之上。) ## 4. Dispatch ABI(运行时↔可执行体的接口,关键) codegen 出来的 LLVM 函数(阶段 2 dump 见过)签名是: ```mlir llvm.func @matmul_dispatch_0_matmul_2x2x4_f32(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) -> i32 ``` - 参数不是直接传 buffer,而是通过 `iree_hal_executable_dispatch_state_v0_t` 结构体(`DispatchABI.cpp` 定义) 取 bindings —— 这是运行时和编译出的 kernel 之间的固定 ABI - 对应 TVM 里 kernel 的参数打包(`TVMArgs` / 显式参数) ## 5. 关键文件 | 文件 | 作用 | |---|---| | `LLVMCPU/LLVMCPUSelectLoweringStrategy.cpp` | 选策略(tiling 尺寸、向量化方案)——核心 | | `LLVMCPU/LLVMCPUTileAndFuseProducerConsumer.cpp` | tile-and-fuse | | `LLVMCPU/LLVMCPUTile.cpp` / `LLVMCPUPeel.cpp` | tiling / peeling | | `LLVMCPU/LLVMCPUTileToVectorSize.cpp` | tile 到向量 | | `LLVMCPU/LLVMCPUVirtualVectorLowering.cpp` | 向量 lowering | | `LLVMCPU/DispatchABI.cpp` | dispatch ABI | | `LLVMCPU/ConvertToLLVM.cpp` / `LLVMCPULowerExecutableTarget.cpp` | 转 LLVM | | `LLVMGPU/ConvertToNVVM.cpp` / `ConvertToROCDL.cpp` | GPU 后端 | | `LLVMGPU/KernelConfig.cpp` | GPU kernel 配置 | ## 6. 源码阅读路径 ``` src/iree/compiler/src/iree/compiler/Codegen/ ├── Common/ # 跨后端共享 ├── Interfaces/ # 接口 ├── LLVMCPU/ # CPU 后端 │ ├── LLVMCPUSelectLoweringStrategy.cpp # 先读这个(策略选择) │ ├── LLVMCPUTileAndFuseProducerConsumer.cpp │ └── DispatchABI.cpp ├── LLVMGPU/ # GPU 后端(NVVM/ROCDL) ├── SPIRV/ # Vulkan └── Transforms/ # 通用变换 ``` > 学习建议:你有 codegen 经验,重点看 `LLVMCPUSelectLoweringStrategy.cpp` 理解「策略怎么选」, > 以及 `DispatchABI.cpp` 理解「kernel 和运行时怎么对接」。GPU 后端看 `LLVMGPU/KernelConfig.cpp`。