Optimization 编译器优化问题 编译器消除重复子表达式重新计算的一些方法是什么?如何跟踪子表达式?如何识别重复出现的问题 除了使用逐位运算符外,常见编译器使用的强度降低技术有哪些

Optimization 编译器优化问题 编译器消除重复子表达式重新计算的一些方法是什么?如何跟踪子表达式?如何识别重复出现的问题 除了使用逐位运算符外,常见编译器使用的强度降低技术有哪些,optimization,compiler-construction,compiler-development,Optimization,Compiler Construction,Compiler Development,我相信许多编译器使用SSAPRE(静态单赋值部分冗余消除)来消除重复表达式。这就需要代码在其中,允许进行更多的优化 我不是很确定,但是看看。是编译器的优化IR,通常比GCC更快。每个过程都有一个小的解释。如果需要更多信息,请查看LLVM源代码以了解这些过程。它是用C++编写的,但是非常干净易懂。 编辑:顺便说一下,如果您正在开发编译器,我强烈推荐LLVM,它非常易于使用并生成高度优化的代码。对于1,您正在寻找的优化名称是公共子表达式消除(common subexpression eliminat

我相信许多编译器使用SSAPRE(静态单赋值部分冗余消除)来消除重复表达式。这就需要代码在其中,允许进行更多的优化

  • 我不是很确定,但是看看。是编译器的优化IR,通常比GCC更快。每个过程都有一个小的解释。如果需要更多信息,请查看LLVM源代码以了解这些过程。它是用C++编写的,但是非常干净易懂。
    编辑:顺便说一下,如果您正在开发编译器,我强烈推荐LLVM,它非常易于使用并生成高度优化的代码。

    对于1,您正在寻找的优化名称是公共子表达式消除(common subexpression elimination,CSE)。根据您的表现,这可能相当容易。通常,编译器会有一些程序的中间表示,其中操作会被尽可能地分解并线性化。例如,表达式
    c=a*b+a*b
    可以分解为:

    v1 = a * b
    v2 = a * b
    c = v1 + v2
    
    因此,通过寻找具有相同运算符和操作数的操作,可以在非常低的级别上执行CSE。当您遇到一个重复的实例(在本例中为v2)时,您将用原始实例替换它的所有实例。因此,我们可以将上面的代码简化为:

    v1 = a * b
    c = v1 + v1
    
    这通常假设每个变量只分配一次(单个静态分配形式),但您可以实现类似的内容,而不受该限制。当您尝试跨分支执行此优化时,这会变得更加复杂。正如Zifre提到的,研究部分冗余消除

    无论哪种方式,您都会得到一些基本的改进,您需要跟踪的只是基本表达式。您可能想更进一步,寻找算术恒等式。例如,
    a*b
    b*a
    相同。另外,
    x*(y+z)=x*y+x*z
    。这会使您的优化更加复杂,而且不清楚它是否会给您带来如此多的性能改进。有趣的是,CSE优化的大部分好处来自于地址计算,比如数组访问,并且您不需要像上面那样的复杂身份


    对于2,什么样的强度降低是有用的实际上取决于您编译的体系结构。通常这只是将乘法和除法转换为移位、加法和减法

    我强烈推荐关于这些主题的两份印刷参考文献:

  • 史蒂文·S·穆奇尼克
  • 罗伯特·摩根

  • Muchnick的书是正式的,但可读性很强,对所有重要的优化技术都有很好的描述。摩根的这本书有着更多的亲身体验,将是一个专注于优化技术的编译器项目的良好基础。这两本书都没有太多关于词法分析或句法分析的内容,这些主题的知识都是假定的。

    要在推荐书列表中再增加一本书,请查阅亨利·S·沃伦的著作。这是一本优化常见运算的技术精粹,例如将整数除法转换为乘法。

    您正在寻找部分冗余消除(PRE)。CSE(来自其他答案)和循环不变代码运动都包含在PRE中。(PRE的一个变体是惰性代码运动,我认为这是最佳的)

    看看,这似乎很好地描述了这些技术

    不要使用SSAPRE。此外,这需要一种特殊形式的SSA,称为HSSA,它有几个缺点:

    • 这相当复杂
    • 它需要全局值编号(因此SSAPRE不提供值编号,因为它预期已经存在)
    • 如果您的语言不支持指向堆栈变量的指针,那么它不会提供任何东西(如果它支持,请停止编写您自己的分析并使用LLVM或gcc)
    • gcc使用HSSA有一段时间了,但他们已经不再使用了
    • LLVM曾用它做过实验,但他们似乎不再使用它了
    编辑:
    穆奇尼克的书有一个详细的描述,另一个答案与之相连。

    哇,谢谢。这些链接真的很有帮助。绝对同意LLVM。我们在我的研究小组中使用它。太好了,不要推荐SSAPRE。它需要HSSA,而您的编译器几乎肯定不会提供HSSA。如果重复的HSSA不在同一个表达式中怎么办?例如x=a*b,下面某处y=a*b。有什么方法可以检测出重复的a*b吗?这是重复的。在这种情况下,您将用x替换y的所有未来用法。您应该将此问题分为两部分,并修复标题。(我还没有权力)。你知道为什么GCC已经离开HSSA,为什么LLVM决定不使用它吗?当前版本的GCC(7.0)使用
    VDEF
    VUSE
    标记变量,这在我看来类似于HSSA。你知道他们是否有亲戚关系吗?对不起,已经很久了,我没有参与。我真的不记得这件事了:(。