📜  编译器设计中的代码优化

📅  最后修改于: 2021-06-28 07:10:09             🧑  作者: Mango

综合阶段的代码优化是一种程序转换技术,该技术试图通过使中间代码消耗较少的资源(即CPU,内存)来改进中间代码,以便产生运行速度更快的机器代码。编译器优化过程应满足以下目标:

  • 优化必须正确,不得以任何方式改变程序的含义。
  • 优化应提高程序的速度和性能。
  • 编译时间必须保持合理。
  • 优化过程不应延迟整个编译过程。

何时进行优化?
代码优化通常在开发阶段结束时执行,因为它会降低可读性并添加用于提高性能的代码。

为什么要优化?
优化算法超出了代码优化阶段的范围。因此该程序进行了优化。这可能涉及减少代码的大小。因此,优化有助于:

  • 减少占用的空间并提高编译速度。
  • 手动分析数据集需要很多时间。因此,我们利用Tableau之类的软件进行数据分析。同样,手动执行优化也很繁琐,最好使用代码优化器来完成。
  • 优化的代码通常会提高可重用性。

代码优化的类型–优化过程可以大致分为两种类型:

  1. 机器独立优化–此代码优化阶段尝试改进中间代码,以获得更好的目标代码作为输出。此处转换的中间代码部分不涉及任何CPU寄存器或绝对存储器位置。
  2. 机器相关的优化–机器相关的优化是在生成目标代码之后以及根据目标机器体系结构转换代码时进行的。它涉及CPU寄存器,并且可能具有绝对内存引用,而不是相对引用。依赖于机器的优化器会尽最大努力充分利用内存层次结构。

代码优化通过以下不同方式完成:

  1. 编译时间评估:
    (i)  A = 2*(22.0/7.0)*r 
         Perform 2*(22.0/7.0)*r at compile time.
    (ii)  x = 12.4
          y = x/2.3 
          Evaluate x/2.3 as 12.4/2.3 at compile time.
    
  2. 可变传播:
    //Before Optimization 
    c = a * b                                               
    x = a                                                  
    till                                                           
    d = x * b + 4 
     
     
    //After Optimization 
    c = a * b  
    x = a
    till
    d = a * b + 4
    

    因此,在变量传播之后,a * b和x * b将被标识为公共子表达式。

  3. 消除死代码:变量传播通常会导致将赋值语句变成死代码
    c = a * b                                                
    x = a                                                
    till                                                          
    d = a * b + 4   
     
    //After elimination :
    c = a * b
    till
    d = a * b + 4
    
  4. 代码运动:
    •减少表达式的评估频率。
    •将循环不变语句带出循环。
    a = 200;
     while(a>0)
     {
         b = x + y;
         if (a % b == 0}
         printf(“%d”, a);
       }
     
     
    //This code can be further optimized as
    a = 200;
    b = x + y;
    while(a>0)
     {
         if (a % b == 0}
         printf(“%d”, a);
       }
    
  5. 归纳变量和强度降低:
    •归纳变量用于以下类型的分配i = i +常数。
    •强度降低意味着用低强度代替高强度运算符。
    i = 1;                                                                      
    while (i<10)                                                          
    {                                                                             
        y = i * 4; 
    }
      
      
    //After Reduction
    i = 1
    t = 4
    { 
       while( t<40) 
       y = t; 
       t = t + 4;
    }
    

在哪里应用优化?
现在我们了解了优化的需求及其两种类型,现在让我们看看将这些优化应用于何处。

  • 源程序
    优化源程序包括更改算法或更改循环结构。用户是此处的参与者。
  • 中级代码
    优化中间代码涉及更改地址计算和转换所涉及的过程调用。在这里,编译器是角色。
  • 目标代码
    优化目标代码是由编译器完成的。寄存器,选择和移动指令的使用是目标代码中涉及的优化的一部分。
    优化阶段
    优化通常分为两个阶段:
  • 全局优化:
    转换应用于包括功能,过程和循环的大型程序段。
  • 局部优化:
    转换将应用于小的语句块。在全局优化之前先进行局部优化。

参考– https://en.wikipedia.org/wiki/Optimizing_compiler