Files
note_AI_compiler/iree/08-codegen.md
T
2026-08-20 17:20:09 +08:00

4.2 KiB
Raw Blame History

阶段 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/ —— 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 见过)签名是:

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。