Optimization 编译器中间阶段代码优化的目的是什么?

Optimization 编译器中间阶段代码优化的目的是什么?,optimization,compiler-construction,compiler-optimization,intermediate-code,Optimization,Compiler Construction,Compiler Optimization,Intermediate Code,对中间代码执行一些代码优化,因为 它们增强了编译器到目标处理器的可移植性 程序分析在中间代码上比在机器代码上更精确 数据流分析中的信息不能用于优化 前端的信息不能用于优化 IMO:中间代码是与机器无关的代码。所以,中间代码可以用于代码优化,因为给定的源代码可以转换为目标机器代码。因此,选项(1)和选项(2)也是正确的 在编译器的中间阶段,代码优化的目的和好处是什么?编译器优化可移植性并不是对中间代码执行许多优化的原因。然而,这是一个优势,我们得到免费的结果。你所说的其他三点是含糊不清的。无论

对中间代码执行一些代码优化,因为

  • 它们增强了编译器到目标处理器的可移植性
  • 程序分析在中间代码上比在机器代码上更精确
  • 数据流分析中的信息不能用于优化
  • 前端的信息不能用于优化

  • IMO:中间代码是与机器无关的代码。所以,中间代码可以用于代码优化,因为给定的源代码可以转换为目标机器代码。因此,选项(1)和选项(2)也是正确的



    在编译器的中间阶段,代码优化的目的和好处是什么?

    编译器优化可移植性并不是对中间代码执行许多优化的原因。然而,这是一个优势,我们得到免费的结果。你所说的其他三点是含糊不清的。无论如何,我们不必讨论它们

    为了回答您的问题,我必须经历一个典型编译器的操作(这个问题只适用于这种类型的编译器)。在编译过程中,编译器通常处理源代码的五种表示形式:

  • 文本表示(这是您编写的代码)
  • 语法分析器生成的
  • 语法分析器生成的
  • 由IR代码生成器生成的中间表示(IR)。这将是前端执行的最后一个操作
  • 二进制代码生成器生成的二进制表示(由目标ISA指定)
  • 现在让我们看看哪种表示最适合执行优化。使用前三种表示法中的任何一种都会导致编译器速度极慢,因为几乎所有优化都需要广泛地分析和修改输入表示法。我这么说几乎是因为前端很少执行优化(通常是在AST上)。一个常见的例子是常数折叠。在这个级别执行此类优化的原因是它们所做的所有修改都是局部的(在表达式中)。因此,它们很便宜。此外,它们还使生成的IR代码更干净,更适合用户使用。另一方面,AST非常适合执行语义分析,因此编译器可以尽快发现任何错误,并在发现任何错误时中止进一步的处理

    大多数编译器优化都接受IR代码作为输入,并生成(希望是优化的)IR代码作为输出(有些编译器可能会逐渐降低IR,直到一个优化发出二进制代码)。专门为应用优化而设计的。首先,它有一个(类似于二进制代码)可以很容易地修改。其次,IR保留AST中的大部分可用信息。这包括全局、局部和临时变量定义和类型。这种表达能力使编译器能够更有效地优化代码。第三,它是低级的,因此它的指令是基本指令,只有一条或几条连续的IL指令映射到少数目标ISA指令。这有助于代码生成器快速实现其目的

    对二进制代码执行的优化很少。这些包括第一过程或第二过程指令调度和第二过程寄存器分配

    在所有这些之后,链接器(如果需要)开始它的工作,其中可能包括一些其他的优化

    请注意,大多数编译器优化也可以在二进制代码上执行(尽管没有那么有效)。这种类型的优化称为动态二进制优化,它们用于动态二进制转换和插装


    我想就便携性说几句话。IL使我们能够对多种源语言使用相同的后端。然而,即使我们确信只有一种语言会得到支持,正如我刚才解释的,IL仍然非常重要。此外,很少有非常重要的优化依赖于目标ISA。有许多优化可以将代码从IR转换为IR。这些显然是独立于目标的。这些优化确实是可移植的,可以在不同目标体系结构的后端之间共享。

    您可以查看更多信息。LLVM是优化编译器的一个很好的例子,它(在某种意义上)只在中间阶段运行。其思想是,通过以特定方式(如静态单赋值)转换代码表示,可以更可靠、更系统地确定是否允许进行优化。另请参见:因为许多优化可以在那里以独立于处理器的方式执行。