必须先 bufferize 再降级:Linalg 工作在 tensor 值语义层,而 Affine 循环需 memref 可变内存访问,故 convert-linalg-to-loops 前须经 bufferization 转为 memref + load/store。

Linalg 降级到 Affine 循环前,必须先 bufferize
直接对 linalg.generic 或 linalg.matmul 调用 convert-linalg-to-loops 会失败——这不是 bug,是设计使然。Linalg Dialect 默认工作在 tensor 语义层(值语义、不可变),而循环需要可变内存访问,中间必须插入 bufferization 步骤,把 tensor 操作转成 memref + load/store 的组合。
- 常见错误现象:
error: 'linalg.generic' op operand #0 must be of memref type, but got 'tensor<?x ?xf32>' - 正确顺序只能是:
linalg.bufferize→convert-linalg-to-loops→affine-loop-normalize(可选) - bufferize 不是无损的:动态维度(
?x?xf32)会被保留,但 shape 推导失败时会报错,需提前确保 dim size 可推导或显式提供memref.alloc尺寸 - 如果你用的是 MLIR 15+,
linalg-bufferizepass 默认启用allow-returning-dynamic-allocs,否则遇到 runtime shape 会直接 abort
convert-linalg-to-loops 生成的循环结构依赖 linalg op 的 indexing_maps
convert-linalg-to-loops 不是“硬编码写 for 循环”,而是根据 linalg op 的 indexing_maps 和 iterator_types 自动生成嵌套结构。比如一个 linalg.matmul 的 indexing_maps 是:
[affine_map<(d0, d1, d2) -> (d0, d2)>, // A[d0, d2] affine_map<(d0, d1, d2) -> (d2, d1)>, // B[d2, d1] affine_map<(d0, d1, d2) -> (d0, d1)>] // C[d0, d1]
它就会生成三层循环:d0(C 行)、d1(C 列)、d2(求和维度),顺序由 iterator_types = ["parallel", "parallel", "reduction"] 决定。
- 如果 indexing_maps 写错(比如把 A 的 map 写成
(d0, d1)而漏掉d2),生成的循环会少维,导致访存越界或结果全零 - reduction 维度必须出现在所有输入 map 中,且只在一个输出 map 中出现;否则 pass 会拒绝转换
- 不建议手动改 indexing_maps 来“调优”——它本质是算子语义声明,不是性能开关;性能靠后续 tiling / vectorization
降级后 Affine 循环仍需 normalize 才能进 LLVM
刚生成的 Affine 循环常含复杂表达式(如 affine.for %i = 0 to (d0 + d1) * 2),LLVM lowering 需要更规整的循环边界和步长。此时必须跑 affine-loop-normalize,它会把任意仿射表达式拆成标准形式:%i = 0 to ? step 1。
- 没 normalize 就跑
convert-affine-to-scfl,大概率触发断言:expected loop step to be 1 - normalize 后的循环体里,
affine.load/affine.store仍存在;下一步要用convert-affine-to-scfl把它们转成scf.for+memref.load/memref.store - 注意:normalize 会引入额外的
affine.apply计算索引,若原 loop bound 含非线性项(如d0 * d0),它无法处理,需提前用affine-simplify或重写逻辑
真正难的不是“怎么降”,而是“在哪停”——Linalg → Affine → SCF → LLVM 这条链上,每一步都丢信息。比如 bufferize 丢 tensor 语义,affine-loop-normalize 丢多面体结构,最后进 LLVM 就只剩 load/store/mul/add。想保优化空间,就得在 Linalg 层做 tiling/fusion/vectorization,而不是等降到循环再折腾。

















