编译器优化那些事儿(3):Lazy Code Motion

0、导语

本文中,我们将介绍通过代码移动(插入)的方式消除冗余计算的一个典型方法。

下图给出的简要程序流图中, ①是我们想要优化的代码,②和③是优化后的代码,让我们先思考下面几个问题:
在这里插入图片描述

  • ②和③哪个优化效果更好一点?

    ③ 更好一点,相比 ② 寄存器生存周期更短
  • ③这种情况,在 p 点直接插入 t=b+c 会带来安全或性能问题吗? 会改变程序的行为吗?

    这里不会引入冗余的计算,也没有改变程序行为。但如果 p 是下文介绍的 非预期的 点,我们就需要使用在 临界边上增加合成块的方式避免这个问题了。
  • 能否由编译器来完成一个算法,找到一个通用的、寻找到合适的插入点的方法以消除冗余计算?

    这是本文要介绍的内容,我们会在下面算法章节引入四个定义,为程序在各个点上打上标签,通过这些点的集合之间的运算,得到插入点的集合。

0.1 开始之前

介绍算法之前,我们来看三个在写应用层代码时可能会遇到的问题。

  1. 我们可以把计算移动到不会重复计算的路径吗?
    在这里插入图片描述

    答案已在图中给出:

    • 左边例子是可以的。这也是下文算法要找的情景。当然实际应用程序中会更复杂,以致我们不能明显看出或不经意间引入冗余的计算,比如 《Lazy code motion》1 里给出的例子。
    • 中间不可以,因为 b 被重新定义了,所以 a = b + c 不是冗余计算了。
    • 右边不可以,因为 a = b + c 可能一次也没执行,移动到循环前可能会改变程序的行为。
  2. 左图到右图的变化有优化效果吗
    在这里插入图片描述

    有的,这也是下面算法中要寻找的情景,左边的路径消除了一次冗余计算,右边为了保持程序正确性插入了一个计算,但并没有引入冗余的计算,所以总体是有优化的.

  3. 下图中,能否在 block d 的父项 p 上插入表达式 t=b+c
    在这里插入图片描述

    不能,因为插入不能改变程序的行为: 这里 t=b+c 可能难以看出问题,但如果表达式换成 b/c (c==0) 或 b^c 就能明显的看到造成了运行问题或性能问题。

    解决方法:可在 临界边(Critical Edge)上增加 合成块(Synthetic Block)

0.2 临界边(Critical Edge)的定义

定义:源基本块有多个后继,目标基本块有多个前驱,连接它们的边就叫临界边(Critical Edge)

在这里插入图片描述

临界边如上图红色部分所示。

打破临界边(Critical Edge)的办法: 增加合成块(Synthetic Block)

步骤:

  1. 为每个指向拥有多个前置的基本块添加一个基本块(不仅仅是在 临界边 上)。
  2. 为了保持算法简单,将每个语句视为其自己的基本块,并将指令的放置限制在基本块的开头。

在这里插入图片描述

上图中我们插入了两个合成块,其中一个是多余的,但不用担心,我们可以在最后消除它。

1、算法

上文中,我们介绍了一个可以放心插入表达式而不会引入安全问题的方法,下面我们将正式介绍导语中提到的算法。

部分冗余消除算法要尽可能延迟计算, 这也是标题中 lazy 的含义。

程序流程图如下:
在这里插入图片描述

算法步骤:

  1. 首先计算预期表达式(Anticipated)集合
  2. 计算将可用的表达式(Will-be-Available)集合
  3. 从 AVAIL 和 ANT ,我们为每个表达式计算出最早的插入位置(Earliest)集合,这最大限度地消除了冗余,但可能会增大寄存器生存期
  4. 再计算延迟表达式(Postponable)集合
  5. 经过上面的计算,引入 Latest 的定义,计算最晚插入的点的集合,实现与 earliest 相同数量的冗余消除,但缩短了保存表达式值的寄存器的生存期
  6. 计算使用表达式(Used)
  7. 计算最后的插入位置的集合,替换冗余表达式

我们会以下图为例,说明整个计算过程。根据以往的经验,下面给出的几个公式,必须结合图例去理解,文字无法阐述清楚准确定义。
在这里插入图片描述

1.1 预期表达式(Anticipated

Anticipated:An expression 𝑒 is said to be anticipated at program point 𝑝 if all paths leading from 𝒑 eventually computes 𝒆 (from the values of 𝑒’s operands that are available at 𝑝).

f b ( x ) = E U s e b ∪ ( x − E K i l l b ) f_b(x) = EUse_b \cup (x -EKill_b) fb(x)=EUseb(xEKill

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值