4.2 KiB
4.2 KiB
阶段 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 第 3 节)。
按后端组织:
LLVMCPU/—— CPU(x86/ARM)LLVMGPU/—— GPU(CUDA via NVVM、ROCm via ROCDL)SPIRV/—— VulkanVMVX/—— 简单可移植参考后端WGSL/—— WebGPUCommon/—— 跨后端共享逻辑
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 见过)签名是:
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。