MaterializeSemanticAliases Pass¶
将语义要求必须是同一块分配的 buffer 归一到同一个 MemRef —— 通过把每个循环
carried 的 iter_arg/initValue MemRef 沿 yield/producer 链向下传播来实现。
概述¶
内存规划区分两种 buffer 共享:
- 强制别名(语义要求): 循环累加器、或原地算子的结果必须落在同一块 buffer——写"下一个"值必须更新 carried buffer,否则循环无法累加。这是正确性, 不是优化。
- 机会别名(可选): 生命周期不冲突的两块独立 buffer 可以共享存储以省内存, 属于优化。
本 pass 只处理强制别名。它从 MemoryReuse 中拆出
(原来是那个 pass 的 "Step 0"),以便机会性的生命周期复用可以被独立跳过 ——
例如 compile(memory_planner=MemoryPlanner.PTOAS) 下由 ptoas 接管生命周期复用时。
使用时机:在 InitMemRef(创建 MemRef)之后、
MemoryReuse 之前运行。它总是运行;只有机会性复用可跳过。
API¶
| C++ | Python | 级别 |
|---|---|---|
pass::MaterializeSemanticAliases() |
passes.materialize_semantic_aliases() |
函数级 |
算法¶
InitMemRef 已经让循环 carried 的 iter_arg 和 return_var 与 initValue
(累加器 buffer)共享同一 MemRef,但 yield 值的生产者 —— 例如计算 acc_next
的 tile.add —— 仍被分配了自己的新 MemRef。本 pass 补上这个缺口:
- 自顶向下重定向(
TopDownRetargeter):对每个ForStmt,取每个iter_arg的规范 MemRef 作为目标,推送到 yield 值及其 producer 链上(跟随原地output-reuses-input算子与 view 输入)。IfStmt的返回值被推送到两个分支的 yield。 - 应用重定型(
RetypeApplier):就地改写收集到的变量类型,使生产者直接写入 carried buffer。
当没有可重定向的内容时(Compute 返回空)本 pass 是 no-op,并跳过
Orchestration 函数(无 TileType 变量)。
与 codegen 的关系¶
PTO codegen 把解析到同一 MemRef 身份(base + byte_offset + size)的变量
渲染成同一个 tile_buf handle,因此本 pass 之后,循环累加器会发出原地的
pto.tadd ins(%acc, %t) outs(%acc),而不是写到独立的 %acc_next。在
memory_planner=PTOAS(不烘焙物理 addr、跳过 MemoryReuse)下,这正是让 ptoas
PlanMemory 把累加器保持在一块 buffer、同时自己完成生命周期复用与地址分配的关键。
参见 PTO 代码生成 — 由谁规划内存。
说明¶
- view / 部分 view 共享
base但byte_offset/size不同,因此不会被并入强制 别名 buffer —— 只有完全同一分配的变量才合并。 - 在默认(
PYPTO)流水线里,本 pass 加上MemoryReuse组合起来等于原来单个MemoryReusepass 的行为(字节级一致)。