980 likes | 1.11k Views
第九章 代 码 优 化. 通过程序变换(局部变换和全局变换)来改进程序,称为优化 介绍独立于机器的优化,即不考虑任何目标机器性质的优化变换 流图中循环的识别 数据流分析 代码改进变换. 9.1 优化的主要种类. 9.1.1 代码改进变换的标准 代码变换必须保程序的含义 采取安全稳妥的策略 变换减少程序的运行时间平均达到一个可度量的值 变换所作的努力是值得的. 9.1 优化的主要种类. 本节所用的例子 i = m 1; j = n; v = a[n]; (1) i := m 1 while (1) { (2) j := n
E N D
第九章 代 码 优 化 通过程序变换(局部变换和全局变换)来改进程序,称为优化 • 介绍独立于机器的优化,即不考虑任何目标机器性质的优化变换 • 流图中循环的识别 • 数据流分析 • 代码改进变换
9.1优化的主要种类 9.1.1代码改进变换的标准 • 代码变换必须保程序的含义 • 采取安全稳妥的策略 • 变换减少程序的运行时间平均达到一个可度量的值 • 变换所作的努力是值得的
9.1优化的主要种类 本节所用的例子 i = m 1; j = n; v = a[n]; (1) i := m 1 while (1) { (2) j := n do i = i +1; while(a[i]<v); (3) t1 := 4 * n do j =j 1;while (a[j]>v); (4) v := a[t1] if (i >= j) break; (5) i := i + 1 x=a[i]; a[i]=a[j]; a[j]=x; (6) t2 := 4 * i } (7) t3 := a[t2] x=a[i]; a[i]=a[n]; a[n]=x; (8) if t3>v goto (5)
9.1优化的主要种类 本节所用的例子 i = m 1; j = n; v = a[n]; (9) j := j 1 while (1) { (10) t4 := 4 * j do i = i +1; while(a[i]<v); (11) t5 := a[t4] do j =j 1;while (a[j]>v); (12) if t5>v goto (9) if (i >= j) break; (13) if i >=j goto (23) x=a[i]; a[i]=a[j]; a[j]=x; (14) t6 := 4 * i } (15 ) x := a[t6] x=a[i]; a[i]=a[n]; a[n]=x; . . .
B1 i := m 1 j := n t1 := 4 * n v := a[t1] B2 i := i + 1 t2 := 4 * i t3 := a[t2] if t3 > v goto B2 B3 j := j 1 t4 := 4 * j t5 := a[t4] if t5 > v goto B3 B4 if i >= j goto B6 B5 B6 9.1优化的主要种类
9.1优化的主要种类 9.1.2 公共子表达式删除 B5 x=a[i]; a[i]=a[j]; a[j]=x; t6 := 4 * i x := a[t6] t7 := 4 * i t8 := 4 * j t9 := a[t8] a[t7] := t9 t10 := 4 * j a[t10] := x goto B2
9.1优化的主要种类 B5 x=a[i]; a[i]=a[j]; a[j]=x; t6 := 4 * i x := a[t6] t7 := 4 * i t8 := 4 * j t9 := a[t8] a[t7] := t9 t10 := 4 * j a[t10] := x goto B2
9.1优化的主要种类 B5 x=a[i]; a[i]=a[j]; a[j]=x; t6 := 4 * i x := a[t6] t7 := 4 * i t8 := 4 * j t9 := a[t8] a[t7] := t9 t10 := 4 * j a[t10] := x goto B2 t6 := 4 * i x := a[t6] t8 := 4 * j t9 := a[t8] a[t6] := t9 a[t8] := x goto B2
B1 i := m 1 j := n t1 := 4 * n v := a[t1] B2 i := i + 1 t2 := 4 * i t3 := a[t2] if t3 > v goto B2 B3 j := j 1 t4 := 4 * j t5 := a[t4] if t5 > v goto B3 B4 if i >= j goto B6 B5 B6 9.1优化的主要种类
9.1优化的主要种类 B5 x=a[i]; a[i]=a[j]; a[j]=x; t6 := 4 * i x := a[t6] t7 := 4 * i t8 := 4 * j t9 := a[t8] a[t7] := t9 t10 := 4 * j a[t10] := x goto B2 t6 := 4 * i x := a[t6] t8 := 4 * j t9 := a[t8] a[t6] := t9 a[t8] := x goto B2
9.1优化的主要种类 B5 x=a[i]; a[i]=a[j]; a[j]=x; t6 := 4 * i x := a[t6] t7 := 4 * i t8 := 4 * j t9 := a[t8] a[t7] := t9 t10 := 4 * j a[t10] := x goto B2 t6 := 4 * i x := a[t6] t8 := 4 * j t9 := a[t8] a[t6] := t9 a[t8] := x goto B2 x := a[t2] t9 := a[t4] a[t2] := t9 a[t4] := x goto B2
B1 i := m 1 j := n t1 := 4 * n v := a[t1] B2 i := i + 1 t2 := 4 * i t3 := a[t2] if t3 > v goto B2 B3 j := j 1 t4 := 4 * j t5 := a[t4] if t5 > v goto B3 B4 if i >= j goto B6 B5 B6 9.1优化的主要种类
9.1优化的主要种类 B5 x=a[i]; a[i]=a[j]; a[j]=x; t6 := 4 * i x := a[t6] t7 := 4 * i t8 := 4 * j t9 := a[t8] a[t7] := t9 t10 := 4 * j a[t10] := x goto B2 t6 := 4 * i x := a[t6] t8 := 4 * j t9 := a[t8] a[t6] := t9 a[t8] := x goto B2 x := a[t2] t9 := a[t4] a[t2] := t9 a[t4] := x goto B2
9.1优化的主要种类 B5 x=a[i]; a[i]=a[j]; a[j]=x; t6 := 4 * i x := a[t6] t7 := 4 * i t8 := 4 * j t9 := a[t8] a[t7] := t9 t10 := 4 * j a[t10] := x goto B2 t6 := 4 * i x := a[t6] t8 := 4 * j t9 := a[t8] a[t6] := t9 a[t8] := x goto B2 x := a[t2] t9 := a[t4] a[t2] := t9 a[t4] := x goto B2 x := t3 a[t2] := t5 a[t4] := x goto B2
9.1优化的主要种类 B6 x = a[i]; a[i] = a[n]; a[n] = x; t11 := 4 * i x := a[t11] t12 := 4 * i t13 := 4 * n t14 := a[t13] a[t12] := t14 t15 := 4 * n a[t15] := x x := t3 t14 := a[t1] a[t2] := t14 a[t1] := x
9.1优化的主要种类 B6 x = a[i]; a[i] = a[n]; a[n] = x; a[t1]能否作为公共子表达式? t11 := 4 * i x := a[t11] t12 := 4 * i t13 := 4 * n t14 := a[t13] a[t12] := t14 t15 := 4 * n a[t15] := x x := t3 t14 := a[t1] a[t2] := t14 a[t1] := x
B1 i := m 1 j := n t1 := 4 * n v := a[t1] 把a[t1]作为公共子表达式是不稳妥的 B2 i := i + 1 t2 := 4 * i t3 := a[t2] if t3 > v goto B2 B3 j := j 1 t4 := 4 * j t5 := a[t4] if t5 > v goto B3 B4 if i >= j goto B6 B5 B6 9.1优化的主要种类
t := d + e a := t t := d + e b := t a := d + e b := d + e c := d + e c := t 删除局部公共子表达式期间引进复写 9.1优化的主要种类 9.1.3 复写传播 • 形成为f := g的赋值叫做复写语句 • 优化过程中会大量引入复写
9.1优化的主要种类 9.1.3 复写传播 • 形成为f := g的赋值叫做复写语句 • 优化过程中会大量引入复写 • 复写传播变换的做法是在复写语句f := g后,尽可能用g代表f x := t3 a[t2] := t5 a[t4] := x goto B2 x := t3 a[t2] := t5 a[t4] := t3 goto B2
9.1优化的主要种类 9.1.3 复写传播 • 形成为f := g的赋值叫做复写语句 • 优化过程中会大量引入复写 • 复写传播变换的做法是在复写语句f := g后,尽可能用g代表f • 复写传播变换本身并不是优化,但它给其它优化带来机会 • 常量合并 • 死代码删除
9.1优化的主要种类 9.1.4 死代码删除 • 死代码是指计算的结果决不被引用的语句 • 一些优化变换可能会引起死代码 例: debug := true; debug := false; . . . 测试后改成 . . . if (debug) print … if (debug) print …
9.1优化的主要种类 9.1.4 死代码删除 • 死代码是指计算的结果决不被引用的语句 • 一些优化变换可能会引起死代码 例:复写传播可能会引起死代码删除 x := t3 a[t2] := t5 a[t4] := t3 goto B2 a[t2] := t5 a[t4] := t3 goto B2
9.1优化的主要种类 9.1.5 代码外提 • 代码外提是循环优化的一种 • 循环优化的其它重要技术 • 归纳变量删除 • 强度削弱 例:while (i<= limit 2 ) … 变换成 t = limit 2; while (i <= t ) …
B3 j := j 1 t4 := 4 * j t5 := a[t4] if t5 > v goto B3 9.1优化的主要种类 9.1.6 强度削弱和归纳变量删除 • j和t4的值步伐一致地变化 • 这样的变量叫做归纳变量 • 在循环中有多个归纳变量时, 也许只需要留下一个 • 这个操作由归纳变量删除 过程来完成 • 对本例可以先做强度削弱 它给删除归纳变量创造机会
B1 i := m 1 j := n t1 := 4 * n v := a[t1] t4 := 4 * j B2 B3 j := j 1 t4 := t4 4 t5 := a[t4] if t5 > v goto B3 B4 if i >= j goto B6 B6 B5 9.1优化的主要种类 j := j 1 t4 := 4 * j t5 := a[t4] if t5 > v goto B3 B3 除第一次外, t4 = 4 * j在B3的入口 一定保持 在j := j 1后, 关系t4 = 4 * j + 4也 保持
B1 i := m 1 j := n t1 := 4 * n v := a[t1] B2也可以进行类似的变换 循环控制条件可以用t2和t4来表示 B2 i := i + 1 t2 := 4 * i t3 := a[t2] if t3 > v goto B2 B3 j := j 1 t4 := 4 * j t5 := a[t4] if t5 > v goto B3 B4 if i >= j goto B6 B5 B6 9.1优化的主要种类
i := m 1 j := n t1 := 4 * n v := a[t1] t2 := 4 * i t4 := 4 * j B1 B2 t2 := t2 + 4 t3 := a[t2] if t3 > v goto B2 B3 t4 := t4 4 t5 := a[t4] if t5 > v goto B3 B4 if t2 >= t4 goto B6 B5 B6 t14 := a[t1] a[t2] := t14 a[t1] := t3 a[t2] := t5 a[t4] := t3 goto B2 9.1优化的主要种类
代 码 生成器 前 端 代 码 优化器 控制流 分 析 数据流 分 析 变 换 9.1优化的主要种类 9.1.7 优化编译器的组织 • 实现高级结构的操作在中间代码中是显式的 • 中间代码基本上独立于目标机器
1 2 3 4 5 6 7 8 9 10 9.2流图中的循环 9.2.1 必经结点 结点d是结点n的必经结点, 如果从初始结点起,每条 到达n的路径都要经过d, 写成ddomn 每个结点是它本身的必经 结点 循环的入口是循环中所有 结点的必经结点
9.2流图中的循环 9.2.2自然循环 • 循环 • 循环必须有唯一的入口点,叫做首结点,首结点是循环中所有结点的必经结点 • 至少有一种办法重复循环,也就是至少有一条路径回到首结点 • 回边 • 如果有adom b ,那么边b a叫做回边 • 寻找流图中所有循环的一个办法是找出流图的回边
1 2 3 4 5 6 7 8 9 10 9.2流图中的循环 自然循环 • 回边10 7 循环{7, 8, 10} • 回边7 4 循环{4, 5, 6, 7, 8, 10} • 回边4 3和8 3 循环{3, 4, 5, 6, 7, 8, 10} • 回边9 1 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
B0 B1 B2 B3 有相同首节点的两个循环 9.2流图中的循环 内循环 若一个循环的结点集合是另一个循环的结点集合的子集。 两个循环有相同的首结点, 但并非一个结点集是另一个 的子集,则看成一个 循环。
B0 B0 B0 循环L 循环L (a) 整理前,B0是首结点 (b) 整理后,增加前置结点B0 9.2流图中的循环 9.2.3 前置结点 某些变换要求我们移动语句到首结点的前面
9.2流图中的循环 9.2.4 可归纳流图 一个流图G是可归约的,当且仅当 有向边集合=正向边子集回边子集,并有性质: • 正向边子集形成有向无环图,在这个图中,每个结点可以从G的初始结点到达 • 回边子集仅由前面所讲的回边组成
1 1 2 2 3 3 4 4 5 6 5 6 7 7 8 8 9 10 9 10 9.2流图中的循环
1 3 2 9.2流图中的循环 非归约流图的例子 • 初始结点是1 • 2 3和3 2都不是回边 • 该图不是无环的 • 从结点2和3两处进入由 它们构成的环
9.3全局数据流分析介绍 • 编译器需要把程序流图作为一个整体来收集信息 • 并把这些信息分配给流图的各个基本块 • 数据流信息可以通过建立和解数据流方程来收集 • 典型方程 out [B] = gen [B] (in [B] kill [B] )
9.3全局数据流分析介绍 建立和解数据流方程依赖三个因素 out [B] = gen [B] (in [B] kill [B] ) • 产生和注销的概念依赖于数据流方程所要解决的问题,也会出现反向前进,由out[B]来定义in[B] • 数据流分析受程序控制结构影响 • 过程调用、通过指针赋值、甚至对数组变量的赋值等的存在使得数据流分析大大复杂
9.3全局数据流分析介绍 9.3.1 点和路径 • 点 • 基本块中,两个相邻的语句之间为程序的一个点 • 基本块的开始点和结束点 • 路径 点序列p1, p2, …, pn,对1和n - 1间的每个i,满足 • pi是先于一个语句的点,pi+1是同一块中位于该语句后的点,或者 • pi是某块的结束点,pi+1是后继块的开始点
9.3全局数据流分析介绍 9.3.2 到达-定值 • 确切定值:赋值语句或读语句 • 可能定值:过程调用,别名,通过指针来赋值 • 确切引用 • 可能引用 • 在给出简单的例子加以区别后,我们将不考虑过程调用,别名,通过指针来赋值等引起不确定性的情况。
9.3全局数据流分析介绍 x的定值语句d能到达点p d: x := … d: x := … d: x := … . . . . d1: x := … d1: *y := … . . . p p p d到达p d不能到达p d到达p d被注销 d1也能到达p
B1 d1: i := m 1 d2: j := n d3: a := u1 B2 d4: i := i + 1 B3 d5: j := j 1 B4 B6 B5 d6: a := u2 9.3全局数据流分析介绍 • i := m 1和j := n 都能到达B2的开始点 • j := j 1也能到达 B2的开始点 • j := n不能到 B4
9.3全局数据流分析介绍 d: x := … d: x := … d: x := … . . . . d1: x := … d1: *y := … . . . p p p D可以到达p d不能到达p d能到达p d被注销 d1也能到达p 到达-定值是不精确的,但是稳妥的 会使我们失去某些实际是安全的变换
9.3全局数据流分析介绍 到达-定值的迭代算法 gen [B]:B中能到达B的结束点的定值语句 kill [B]:整个程序中决不会到达B结束点的定值 in [B]:能到达B的开始点的定值集合 out [B]:能到达B的结束点的定值集合 两组方程(根据gen和kill求解in和out) in [ B ] = out [P] P是B的前驱 out [B] = gen [B] (in [B] kill [B])
B1 d1: i := m 1 d2: j := n d3: a := u1 B2 d4: i := i + 1 d5: j := j 1 B3 d6: a := u2 B4 d7: i := u3 9.3全局数据流分析介绍 in [B] B1000 0000 B2 000 0000 B3 000 0000 B4 000 0000 gen [B1] = {d1, d2, d3} kill [B1]={d4, d5, d6, d7} gen [B2] = {d4, d5} kill [B2] = {d1, d2, d7} gen [B3] = {d6} kill [B3] = {d3} gen [B4] = {d7} kill [B4] = {d1, d4}
B1 d1: i := m 1 d2: j := n d3: a := u1 B2 d4: i := i + 1 d5: j := j 1 B3 d6: a := u2 B4 d7: i := u3 9.3全局数据流分析介绍 in [B] out [B] B1000 0000 111 0000 B2 000 0000 000 1100 B3 000 0000000 0010 B4 000 0000000 0001 gen [B1] = {d1, d2, d3} kill [B1]={d4, d5, d6, d7} gen [B2] = {d4, d5} kill [B2] = {d1, d2, d7} gen [B3] = {d6} kill [B3] = {d3} gen [B4] = {d7} kill [B4] = {d1, d4}
B1 d1: i := m 1 d2: j := n d3: a := u1 B2 d4: i := i + 1 d5: j := j 1 B3 d6: a := u2 B4 d7: i := u3 9.3全局数据流分析介绍 in [B] out [B] B1000 0000 111 0000 B2 111 0001 000 1100 B3 000 0000000 0010 B4 000 0000000 0001 gen [B1] = {d1, d2, d3} kill [B1]={d4, d5, d6, d7} gen [B2] = {d4, d5} kill [B2] = {d1, d2, d7} gen [B3] = {d6} kill [B3] = {d3} gen [B4] = {d7} kill [B4] = {d1, d4}
B1 d1: i := m 1 d2: j := n d3: a := u1 B2 d4: i := i + 1 d5: j := j 1 B3 d6: a := u2 B4 d7: i := u3 9.3全局数据流分析介绍 in [B] out [B] B1000 0000 111 0000 B2 111 0001 001 1100 B3 000 0000000 0010 B4 000 0000000 0001 gen [B1] = {d1, d2, d3} kill [B1]={d4, d5, d6, d7} gen [B2] = {d4, d5} kill [B2] = {d1, d2, d7} gen [B3] = {d6} kill [B3] = {d3} gen [B4] = {d7} kill [B4] = {d1, d4}
B1 d1: i := m 1 d2: j := n d3: a := u1 B2 d4: i := i + 1 d5: j := j 1 B3 d6: a := u2 B4 d7: i := u3 9.3全局数据流分析介绍 in [B] out [B] B1000 0000 111 0000 B2 111 0001 001 1100 B3 001 1100 000 0010 B4 000 0000000 0001 gen [B1] = {d1, d2, d3} kill [B1]={d4, d5, d6, d7} gen [B2] = {d4, d5} kill [B2] = {d1, d2, d7} gen [B3] = {d6} kill [B3] = {d3} gen [B4] = {d7} kill [B4] = {d1, d4}
B1 d1: i := m 1 d2: j := n d3: a := u1 B2 d4: i := i + 1 d5: j := j 1 B3 d6: a := u2 B4 d7: i := u3 9.3全局数据流分析介绍 in [B] out [B] B1000 0000 111 0000 B2 111 0001 001 1100 B3 001 1100 000 1110 B4 000 0000000 0001 gen [B1] = {d1, d2, d3} kill [B1]={d4, d5, d6, d7} gen [B2] = {d4, d5} kill [B2] = {d1, d2, d7} gen [B3] = {d6} kill [B3] = {d3} gen [B4] = {d7} kill [B4] = {d1, d4}