编译原理10——优化

概览

  1. 优化
    对中间代码进行等效变化,以便生成更有效的目标代码
  2. 局部优化
  3. 循环优化

10.1 概述

(关键是了解优化的三大原则(等价、有效、合算),其余内容不用看,在接下来的各个小节中都有详解)

10.2 局部优化

  1. 优化单位:基本块
    1. 划分基本块
  2. 优化方式:DAG无环图
    1. 删除公共子表达式
    2. 复写传播
    3. 删除无用代码

10.3 循环优化

  1. 优化方法
    1. 代码外提
    2. 强度消弱
    3. 删除归纳变量

10.4 数据流分析

10.1 概述

优化原则

  1. 等价原则
    经过优化后不应改变程序运行的结果
  2. 有效原则
    使优化后所产生的目标代码运行时间较短,占用内存空间较小
  3. 合算原则
    应尽可能以较低的代价取得较好的优化效果

删除公共子表达式

避免对一个变量的重复计算

复写传播

如果一个临时变量由另一个变量赋值得到而不修改,则用该变量代替临时变量(大概)

删除无用代码

将对不再使用(运算结果无影响)的变量赋值代码删除

代码外提

将循环中引用的不变的变量提取到循环外

强度消弱

将与I具有线性的变量用加减法在每回合逐次加减替代

删除归纳变量

(和强度消弱一同处理)
利用必须保留的归纳变量(与I有线性关系的变量)替代I

10.2 局部优化

10.2.1 基本块及其流图

  1. 基本块
    程序中一顺序执行的语句序列,只有一个入口和一个出口
  2. 定值
    x : = y + z x:=y+z x:=y+z中的 x x x,为x定值
  3. 引用
    x : = y + z x:=y+z x:=y+z中的 y y y z z z,引用y、z
  4. 活跃的
    一个变量的值在以后被引用(可以跨基本块)
  5. 基本块内的优化/局部优化
    局限于基本块内的优化
  6. 流图
    有向图,按照跳转关系由一个基本块指向另一个基本块(流图即为DAG)

基本块的划分

基本块外的中间代码不会被读取使用,删除(删除无用赋值)

基本块入口的确定
  1. 程序入口
  2. 转移语句的目标语句
  3. 条件转移语句的下一条语句
基本块出口的确定
  1. halt(程序出口)
  2. 转移语句
  3. 另一基本块的入口的上一条语句

10.2.2 基本块的DAG表示及其应用

DAG(有向无环图)是的局部优化的实现基础
1. 如果没必要算的就不算了
2. 如果算过的就不算了

  1. 标记
  2. 附加信息

DAG组成

叶节点 n i n_i ni:标识符(变量名)/常数
内部结点 n i n_i ni:运算符(通常还有注记符T,用于确定其代表的值)

中间代码型式

  1. A := B
  2. A := op B
  3. A := B op C 或 A := B[C]

DAG构造&使用

DAG构造(合并已知变量、删除公共子表达式
  1. 代码含(未知)变量
    引用的变量/常量

    1. 已存在
      不操作,直接引用(合并已知变量
    2. 未存在
      在最低层添加新节点 n i n_i ni表示该变量/常量(注意左右关系,A[B]类似op对顺序有要求,A要在B左侧)

    op操作

    1. 已存在
      不操作,直接引用,添加注释(删除公共子表达式
      (:=赋值操作,直接为用于赋值的节点添加注释)
    2. 未存在
      添加新节点 n i n_i ni表示该op(注意左右关系,理由同上)
  2. 代码含不含变量/变量已知
    在最下一层创建新节点,用新节点直接代表计算后的结果(合并已知变量

删除无用赋值

以基本块的活跃变量为根发展树,删除除树子树覆盖范围外的所有节点(该部分操作不影响基本块的运算结果)

10.3 循环优化

  1. 循环优化
  2. 循环
    确定哪些基本块构成了循环
    基本块在程序流图通过转移语句组成的“单向环”结构

10.3.1 代码外提

(简单说,就是一个不变的量在循环里被算/赋值了好多次,不如直接把它放在循环外,只在循环开始前做一次运算)

  1. 定值到达
    流图中从一点a有一通路到达令一点b且该通路上没有变量C的其他定值
    变量C的某点a的定值到达另一点b
  2. 前置结点
    将常量/不变量有关代码外提,生成前置结点
    ⋆ \star 代码外提生成前置结点时,前置节点一般不包含转移语句,该操作有可能生成新的基本块,也有可能向上一个基本块添加新的元素,因此,可能在上一个基本块产生局部优化可能。
  3. 活跃变量
    A的值在从b开始的某条通路上被引用(可以理解为这个变量出了循环还会被引用)
    变量A的在程序中某点b是活跃变量
    部分代码外提可能导致变量在循环结束后数值不同,若该变量不是活跃变量,则该修改可以接收

代码外提算法

  1. 求出循环L的所有不变运算
  2. 对步骤1求得的每一个不变运算s: A:=B op C 或 A := B,检查它是否满足一下条件
    1. 条件1
      1. s所在的结点是L的所有出口结点的必经结点(必经
      2. A在L中其他地方未再定值(未再定值
      3. L中所有A的引用点只有s中A的定值才能到达(专一到达
    2. 条件2
      1. A在离开L后不再是活跃的
      2. A在L中其他地方未再定值(未再定值
      3. L中所有A的引用点只有s中A的定值才能到达(专一到达
  3. 按步骤(1)所找出的不变运算的顺序,依次把符合条件1/2的不变运算提到L的前直结点中。
    (简单说,就是把定值提出去,再把由全定值变量计算得来的(也是定值)都提出去)

10.3.2 强度消弱

  1. 强度消弱
    把程序中执行时间较长的运算替换为执行时间较短的运算
    1. 加法替换乘法
    2. 加法多用常量

(主要针对的是用于跳出循环判断的变量i及其线性变量)
操作

  1. 寻找每次循环中自增一个常数的变量(i比较常见)
  2. 根据该变量寻找与其有线性关系的变量(T:=A*i+B)
  3. 将线性变量前提,原本代码修改为在相关自增变量后添加前提变量的自增常量指令(前提代码:T:=Ai+B / T:=Ai+B-A,原有位置:T:=T+A)
    (这个前提结点中的代码如何选择根据具体题目判断)

10.3.3 删除归纳变量

(主要针对的是用于跳出循环判断的变量i及其线性变量)

  1. 删除归纳变量
    (简单说,就是一般i在循环中只负责给线性变量赋值,而强调削弱已经把i和线性变量分开了,因此可以把i省去,用一个线性变量来判断跳出循环)
  2. 基本归纳变量(I)
    对变量I只有唯一形如 I : = I ± C I:=I\pm C I:=I±C的赋值,且其中C为循环不变量
  3. 归纳变量(J)
    J = C 1 ∗ I ± C 2 J=C_1*I\pm C_2 J=C1I±C2

强度消弱后,将I基本归纳变量删除,用归纳变量替代,进行循环跳出的判断

10.4 数据流分析

  1. 全局数据流分析

10.4.1 任意路径数据流分析

  1. 向前流

10.4.2 全路径数据流分析

  1. 任意路径
  2. 全路径
  3. 可用性
  4. 可用的

10.4.3 数据流问题的分类

10.4.4 其他主要的数据流问题

  1. Ud-链
  2. Du-链

10.4.5 利用数据流信息进行全局优化

  1. 非常忙表达式
  2. 删除全局公共子表达式
  3. 活跃变量分析
  4. 未初始化变量分析
  5. 常量传播和复写传播
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值