无环 e-graph:Cranelift 的中端优化器

来源: cfallin.org | Lobsters: 2 points | ★★★★☆

背景:Pass-Ordering 问题

2022年5月,作者在Cranelift中引入了简单的别名分析和相关优化(消除冗余加载、执行store-to-load转发)。这些优化工作正常,但引出了一个新问题:如何将这个Pass与其他优化Pass集成?

问题所在

考虑GVN(全局值编号)和冗余加载消除之间的交互:

完美世界中,应该能够看到v10可以被消除,v10可以变成v2的别名。然后,v11通过GVN的规范化变成v3的等价物,随后v12变成v4的等价物。但这最后两步意味着两个不同优化Pass之间的紧密合作...

这就是编译器研究中的Pass-Ordering问题——只要Pass保持独立、粗粒度的算法,就没有简单的解决方案。

三个构建块

  • 重写 (Rewrites):任何用另一个等效表达式替换一个表达式的优化
  • 代码移动 (Code Motion):移动计算发生的位置,但不改变它
  • 规范化 (Canonicalization):将多个相同计算合并为一个"规范"实例

优化类型映射

Sea-of-Nodes IR

作者提出:如果我们能消除计算"位置"的限制,会怎样?

核心思想

"在纯形式中,可以将每个IR转换表示为图重写,因为图就是一切。"

这就是Sea-of-nodes IR——一种消除指令"顺序"的表示方法,转而构建一个由操作符(节点)和边组成的图。

aegraph 的设计

aegraph(无环e-graph)是Cranelift中端优化器的核心数据结构。它是e-graph的一种变体,专门设计用于:

总结

这篇文章详细介绍了Cranelift团队如何解决编译器优化中的Pass-Ordering问题。通过引入aegraph数据结构,他们实现了:

Compiler Cranelift e-graph Optimizer Rust Wasmtime