【问题标题】:Compiler code optimization: AST vs. IR编译器代码优化:AST 与 IR
【发布时间】:2018-04-26 06:03:17
【问题描述】:

,我将 IR 定义为 3 地址代码类型表示(我意识到它也可以表示 AST 表示)。

据我了解,在为 命令式语言 编写最佳实践编译器时,代码优化发生在 AST(可能最好使用访问者模式)和生成的 IR 上AST。

(a) 对吗?

(b) 在生成 IR 之前,哪种类型的优化步骤最好在 AST 上处理? (也欢迎参考文章/在线列表,只要它涉及命令式语言)

我正在开发的编译器是用于 Decaf(有些人可能知道)的,它具有相当深的 CFG 直至(单个)类继承;我将添加不属于它的功能,例如类型强制。它将完全手动编码(不使用任何工具)。这不是家庭作业;写它是为了好玩。

【问题讨论】:

    标签: optimization compiler-construction abstract-syntax-tree


    【解决方案1】:

    IR 是 AST 的一种形式(通常它是“扁平化的”,但也有深树 IR),可能不容易区分它们,特别是如果编译器被实现为一个非常小的序列从原始 AST 一直重写到适合指令选择的最终 IR。

    优化可能发生在这条链上的任何地方,但有些表示更适合广泛的优化,最值得注意的是,大多数现代编译器都使用 SSA 形式来进行几乎所有优化。

    【讨论】:

      【解决方案2】:

      (a) 是的。

      (b) 常量折叠就是一个例子; CSE 是另一个;实际上几乎与表达式评估有关。 IR 相位优化更多的是关于流动分析的结果。

      【讨论】:

      • 在表达式树级别上进行适当的常量折叠非常困难。 SSA 更适合它。使用 SSA,您仍然可以免费获得所有表达方式,以及适当的流量信息。必须结合 DCE 进行常量折叠,否则不会完整,并且 DCE 在 SSA 之上更容易完成。
      【解决方案3】:

      优化(创造一个短语)永远不会太早。因此,在 AST 创建之前和期间、AST 本身、IR(如果有的话)和生成代码时都会进行优化。在类 C 语言和那些编译成机器代码的语言中,工作进入了后期阶段。在针对 VM 的编译器中,我认为在那个阶段改进的空间较小。

      一些早期的优化显然比其他的效果更好。我对 Decaf 了解不多,但有一些显而易见的事情,比如常量折叠和常量表达式求值。如果在生成任何代码之前将整个程序以树的形式获得,您可以找到常见的子表达式、进行代码迁移、消除死代码/死存储、提升不变量、消除尾递归和某些强度降低。

      这在很大程度上取决于您想要工作的努力程度以及您的目标是什么。你没有说太多。

      【讨论】:

      • 您提到的所有优化在 SSA 级别上都非常容易实现,而在树级别上几乎不可能正确完成。在高级树上唯一值得做的优化是特定领域的优化,它依赖于在翻译、脱糖等过程中可能已经丢失的信息。
      • 我的计划是一路走到 x86 32b 组装,从基本的 AST/Visitor 对到 SSA 样式的 IR(可能是几个中间 AST 和 IR) 目前我完全不知道什么是我将执行哪些优化以及执行多少次优化、在哪个对象上执行以及经过多少次。至于 Decaf,这是 Java light 的双关语,也是我在布朗、麻省理工学院和斯坦福大学的课堂上看到的一种语言。 (另外,谢谢:))
      • 编译器语言为 C++。
      • 我担心的是,树重写的成本相对较低,但 SSA 需要大量投资才能获得回报,而且没有明确的终点。也许这就是您的想法,但我更喜欢有人可能实际使用的语言。我得到了 Decaf 参考,我想知道你为什么不选择一个新编译器可能真正解决某人问题的目标。
      • @SK-logic:SSA 相对较新,文献参差不齐,工作量不确定,但我遵从您的经验。如果有其他原因限制后期优化(例如 VM 目标、通用后端、缺乏兴趣),我的回答更倾向于在树级别可以合理地完成什么。
      猜你喜欢
      • 2016-02-14
      • 1970-01-01
      • 2016-04-22
      • 1970-01-01
      • 1970-01-01
      • 2011-10-27
      • 1970-01-01
      • 2011-08-27
      • 1970-01-01
      相关资源
      最近更新 更多