【编译之美】【5. 代码优化:数据流分析】

2023-11-18

有些优化只能在全局优化中做,在本地优化中做不了,比如:

  • 代码移动(Code motion)能够将代码从一个基本块挪到另一个基本块,比如从循环内部挪到循环外部,来减少不必要的计算。(循环剥离)
  • 部分冗余删除(Partial Redundancy Elimination),把一个基本块给删除。

在做全局优化时,情况就要复杂一些:代码不是在一个基本块里简单地顺序执行,而可能经过控制流图(CFG)中的多条路径。我们来看一个例子(例子由 if 语句形成了两条分支语句):
在这里插入图片描述
基于这个 CFG,我们可以做全局的活跃性分析,从最底下的基本块开始,倒着向前计算活跃变量的集合(也就是从基本块 5 倒着向基本块 1 计算)。

这里需要注意,对基本块 1 进行计算的时候,它的输入是基本块 2 的输出,也就是{a, b, c},和基本块 3 的输出,也就是{a, c},计算结果是这两个集合的并集{a, b, c}。也就是说,基本块 1 的后序基本块,有可能用到这三个变量。这里就是与本地优化不同的地方,我们要基于多条路径来计算。

我们发现:全局优化总体来说跟本地优化很相似,唯一的不同,就是要基于多个分支计算集合的内容(也就是 V 值)。在进入基本块 1 时,2 和 3 两个分支相遇(meet),我们取了 2 和 3V 值的并集。这就是数据流分析的基本特征,你可以记住这个例子,建立直观印象。

不动点法

对于有环的情况,我们可以给每个基本块的 V 值都分配初始值,也就是空集合。
在这里插入图片描述
然后对所有节点进行多次计算,直到所有集合都稳定为止。第一遍的时候,我们按照 5-4-3-2-1 的顺序计算(实际上,采取任何顺序都可以),计算结果如下:
在这里插入图片描述
如果现在计算就结束,我们实际上可以把基本块 2 中的 d 变量删掉。但如果我们再按照 5-4-3-2-1 的顺序计算一遍,就会往集合里增加一些新的元素(在图中标的是橙色)。这是因为,在计算基本块 4 的时候,基本块 1 的输出{b, c, d}也会变成 4 的输入。这时,我们发现,进入基本块 2 时,活变量集合里是含有 d 的,所以 d 是不能删除的。
在这里插入图片描述
你再仔细看看,这个 d 是哪里需要的呢?是基本块 3 需要的:它会跟 1 去要,1 会跟 4 要,4 跟 2 要。所以,再次证明,1、2、3、4 四个节点是互相依赖的。

我们再来看一下,对于活变量集合的计算,当两个分支相遇的情况下,最终的结果我们取了两个分支的并集。
在这里插入图片描述
在上一讲,我们说一个本地优化分析包含四个元素:方向(D)、值(V)、转换函数(F)和初始值(I)。在做全局优化的时候,我们需要再多加一个元素,就是两个分支相遇的时候,要做一个运算,计算他们相交的值,这个运算我们可以用大写的希腊字母Λ(lambda)表示。包含了 D、V、F、I 和Λ的分析框架,就叫做数据流分析。

那么Λ怎么计算呢?研究者们用了一个数学工具,叫做“半格”(Semilattice),帮助做Λ运算。

半格可以画成图形,理解起来更直观,假设我们的程序只有 a, b, c 三个变量,那么这个半格画成图形是这样的:
在这里插入图片描述
沿着上面图中的线,两个值是可以比较大小的,按箭头的方向依次减少:{}>{a}>{a, b}> {a, b, c}。如果两个值之间没有一条路径,那么它们之间就是不能比较大小的,就像{a}和{b}就不能比较大小。

对于这个半格,我们把{}(空集)叫做 Top,Top 大于所有的其他的值。而{a, b, c}叫做 Bottom,它是最小的值。

在做活跃性分析时,我们的Λ运算是计算两个值的最大下界(Greatest Lower Bound)。怎么讲呢?就是比两个原始值都小的值中,取最大的那个。{a}和{b}的最大下界是{a, b},{a, b, c} 和{a, c}的最大下界就是{a, b, c} 。

常数传播

常数传播,就是如果知道某个变量的值是个常数,那么就把用到这个变量的表达式,都用常数去替换。看看下面的例子,在基本块 4 中,a 的值能否用一个常数替代?
在这里插入图片描述
答案是不能。到达基本块 4 的两条路径,一条 a=3,另一条 a=4。我们不知道在实际运行的时候,会从哪条路径过来,所以这个时候 a 的取值是不确定的,基本块 4 中的 a 无法用常数替换。

那么,运用数据流分析的框架怎么来做常数传播分析呢?

在这种情况下,V 不再是一个集合,而是 a 可能取的常数值,但 a 有可能不是一个常数啊,所以我们再定义一个特殊的值:Top(T)。

除了 T 之外,我们再引入一个与 T 对应的特殊值:Bottom(它的含义是,某个语句永远不会被执行)。总结起来,常数传播时,V 的取值可能是 3 个:

  • 常数 c
  • Top:意思是 a 的值不是一个常数
  • Bottom:某个语句不会被执行。

这些值是怎么排序的呢?最大的是 Top,中间各个常数之间是无法比较的,Bottom 是最小的。

在这里插入图片描述
接下来,我们看看如何计算多个 V 值相交的值。

我们再把计算过程形式化一下。在这个分析中,当我们经过每个语句的时候,V 值都可能发生变化,我们用下面两个函数来代表不同地方的 V 值:

  • C(a, s, in)。表示在语句 s 之前 a 的取值,比如,C(a, b:=a+2, in) = 3。
  • C(a, s, out)。表示在语句 s 之后 a 的取值,比如,C(a, a:=4, out) = 4。
  1. 如果输入是 Bottom,那么输出也是 Bottom。也就是这条路径不会经过。
  2. 如果该 Statement 就是“ a := 常数”,那么输出就是该常数。3. 如果该 Statement 是 a 赋予的一个比较复杂的表达式,而不是常数,那么输出就是 Top。
  3. 如果该 Statement 不是对 a 赋值的,那么 V 值保持不变。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【编译之美】【5. 代码优化:数据流分析】 的相关文章

随机推荐

  • CSDN竞赛-第六期

    CSDN编程竞赛报名地址 https edu csdn net contest detail 16 前言 背景 不知不觉 CSDN编程竞赛已经进行六期了 从我知道有这个竞赛的时候已经进行了两期 所以我是从第三期开始的 期间参与过三次 成绩在
  • 4,引擎初始化--(4)加载地图--2,创建world(学习资料来源于UE4游戏框架)

    加载地图时 创建完默认GameMode 就要创建world了 首先读取到package 创建world 从这里可以看到 地图是可以在初始化建立的 GameInstance是在运行起来后建立 两者是独立的 设为当前World 并设定为全局GW
  • leetcode:1905. 统计子岛屿

    题目来源 leetcode 1905 统计子岛屿 题目描述 class Solution public int countSubIslands vector
  • 漏洞情报

    点击上方 订阅话题 第一时间了解漏洞威胁 0x01 漏洞描述 WordPress ProfilePress 原 WP User Avatar 是一个轻量级会员插件 可用于创建用户画像 会员目录和用于用户注册 登录 密码重置及用户信息编辑的前
  • C++57个入门知识点_40 常成员函数(用于定义不可修改类内部成员变量的函数,一般用来修饰Get函数;常成员函数this指针:const T* const;常成员函数内部变量修改方法:强转/关键字)

    前面我们已经学习了C 中重要的知识点 特别是虚函数可能会有些懵逼 但是需要我们在实践中不断的理解和尝试 写代码是进步最快的方式 接下来将会介绍一些简单但很重要的知识点 本篇介绍常成员函数 总结 1 常成员函数 用于在程序中定义不可修改内部成
  • 关于红楼梦Python文本分析

    1 获取小说文本 读取文件 获取小说文本 读取文件 fn open prepare 红楼梦 曹雪芹 txt encoding utf 8 string data fn read 读出整个文件 fn close 关闭文件 2 对文本进行处理
  • oralce的判断语句

    大家对 IF ELSE 语句应该都很熟悉吧 它是用来对过程进行控制的 在 SQL 的世界中 CASE 语句有类似的效果 下面简单的介绍 CASE 语句的用法 CASE 语句的形式 事实上 CASE 语句有两种形式 1 SELECT 2 简单
  • 10. 微积分 - 微分&链式法则

    文章目录 微分 链式法则 Hi 大家好 我是茶桁 我们上节课讲了导数 并且在最后预告了今天的内容 今天将会是两部分 一部分是 微分 一部分是 链式法则 微分 微分 我们在导论里面提过 它和导数比较像 但是还是有差别的 实际的定义和内容都比较
  • 来吧!一文彻底搞定Vue组件!

    作者 Jeskson 来源 达达前端小酒馆 Vue组件的概述 组件是什么呢 了解组件对象的分析 Vue组件中的data属性 props传递数据的原理到底是什么 事件通信的那些事 如何了解父子组件事件通信 和遇到非父子组件事件通信如何处理 组
  • IP地址与用户行为

    IP地址能够解决网络风险和提高网络安全的原因是 所有的网络请求都会带有IP信息 是访问者的独立标识 另外ip地址的分配和管理比较严格 难以造假 另外ip属于网络层 可以轻松的对其进行阻断 现有的各种网络安全 负载均衡的设备和软件 都是以ip
  • 校园网上报修系统/宿舍报修系统的设计与实现

    摘要 随着科学技术的飞速发展 社会的方方面面 各行各业都在努力与现代的先进技术接轨 通过科技手段来提高自身的优势 校园网上报修系统当然也不能排除在外 从报修信息的统计和分析 在过程中会产生大量的 各种各样的数据 本文以校园网上报修系统为目标
  • 直流电路中升降压(Buck-Boost)变换电路的设计、参数选取及Matlab/Simulik仿真

    创作不易 感谢大家点赞关注支持 感兴趣的可以点击收藏 这一篇文章给大家介绍一种升降压 Buck Boost 直流变换电路 喜欢的可以点击收藏 升降压 Buck Boost 直流变换电路是通过调节开关管占空比的大小 占空比越小 输出电压越小
  • QT 之键盘事件(捕获键盘按下、松开事件)

    我们在做软件时候 经常会碰到这样的场景 比如按下F5进行刷新功能 按下F1进行帮助之类的快捷键方式 那么在QT中该怎样做呢 查阅文档 QT已经实现了这一系列的键盘事件 void QWidget keyPressEvent QKeyEvent
  • 拷贝构造和拷贝赋值

    拷贝构造表示有新的对象被定义 Object obj1 obj2 新的Object对象obj1被定义 此时调用拷贝构造函数 copy construction 拷贝赋值表示没有新的对象被定义 obj1 obj2 obj1是一个已经被声明过的对
  • WebSocket学习

    一 简介 WebSocket 是一种网络通信协议 RFC6455 定义了它的通信标准 WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议 HTTP 协议是一种无状态的 无连接的 单向的应用层协议 它
  • Pythonの类

    Python是一种面向对象编程语言 因此类在Python中是很重要的概念 类是一种定义数据和行为的模板 可以创建对象并针对特定的问题对其进行操作 在Python中 类的定义以关键字 class 开头 后跟类的名称 类可以包含方法和属性 方法
  • mpvue实现微信小程序样式切换以及本地缓存

    功能描述 在页面A的添加应用中点击 添加 跳转到展示所有应用的页面B 通过点击开关 在页面A中展示所开启的应用 效果展示 代码 页面B代码 div class itembox div class boxhead img div class
  • [HDU 5079][2014 Asia AnShan Regional Contest]Square(DP套DP)

    题目链接 http acm hdu edu cn showproblem php pid 5079 题目大意 给你一个 n n n 8 n middot n n le 8 的棋盘 上面有一些格子必须是黑色 其它可以染黑或者染白 对于一个棋盘
  • python实现逻辑回归三种方法_纯Python实现逻辑回归

    前几天使用后sklearn实现了逻辑回归 这里用纯python实现逻辑回归 首先 我们定义一个sigmoid函数 def sigmoid inX sigmoid函数 return 1 0 1 exp inX 这里使用梯度上升进行逻辑回归 梯
  • 【编译之美】【5. 代码优化:数据流分析】

    有些优化只能在全局优化中做 在本地优化中做不了 比如 代码移动 Code motion 能够将代码从一个基本块挪到另一个基本块 比如从循环内部挪到循环外部 来减少不必要的计算 循环剥离 部分冗余删除 Partial Redundancy E