编译原理 第八章

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

② for(i=6,j=0; j<i; ++j) fun(i); 在六次循环中,i的值保持为6,则可优化为: for(i=6,j=0;j<6; ++j) fun(6);
3. 综合使用常数传播和常数合并进行优化处理 为了对保持定值的所有变量之值进行跟踪,建立一个局部符号表,使 每一个活动的变量在该表中有一个登记项,每当对这些变量进行再定 值时,就相应的修改其登记项中的内容。 例: t1=1; t1+=5; 优化为: t1=6; t2=t1; t2=6;
一. 强度削弱
用一种(或一串)执行时间较短的操作去等价的代替一个操作。 1. x*2n 替换为 x<<n (乘法用左移运算替换) x/2n 替换为 x>>n x%2n 替换为 x&(2n-1) 2. 乘以一个较小的整数可以用多个加法代替 x*=3 替换为 x1=x; x+= x1; x+= x1; 3. 较大整数的乘法可以联合使用位移和加法进行强度削弱优化 x*=9 替换为 x1=x; x*=27 替换为 x1=x; x1<<=3; x1<<=1; x+= x1; x+= x1; x1<<=2; x+= x1; x1<<=1; 4. 对于非算术运算进行强度削弱的情形 x+= x1; 例如:许多机器有多种形式的转移指令, 优化程序可以从其中选择效率更高的指令。
三. 无用变量与无用代码的删除
1. 无用变量:变量的最后一次引用到对该变量再置初值期间,可视为无用 变量。在变量的无用期间,对该变量的所有定值(如赋值)指令均可删去。 例: t=a; t+=5; x=t; …… /*此后的一个时间间隔内,t成为无用变量*/ t=c; /*在t的无用期内,对t的定值可以删除*/ …… t=b; /*t被再次置初值,无用期结束*/ y=t+a;
i=5; ++i; return i+1;
编译器产生 的中间代码
删除无 用变量
i=5; i=6; ret_reg=7; ret;
删除无 用赋值
i=6; ret_reg=7; ret;
§8.3 基于结构信息的优化
8.3.1 基本块及其优化


基本块:具有唯一入口和唯一出口的中间代码序列,入口和出口分别是 块中第一个和最后一个操作,块中各操作顺序执行,不出现任何分叉。 划分基本块的算法:(算法8.1将一个四元式序列划分为基本块) 基本块的DAG表示 利用DAG进行基本块上的优化处理
§8.1 语法制导翻译阶段的优化
遇有函数调用语句,特别是一些常用的代码较短的函数(如内部数学函 数),可以采用直接插入函数代码的方式,从而避免在代码调用过程中 所需的现场保护等附加动作,以提高效率。 语法制导翻译阶段的优化只能局限于单个产生式,难以结合前后文环境一段相邻的中间代码(或目标代码)指令,将其中 的某些组合替换为效率更高的指令组。 线性窥孔优化的特点: ① 对优化对象进行线性扫描 ② 每次处理得是一组相邻指令(暴露在一个观察窗口内的指令) ③ 优化对象即可以是中间代码,也可以是最终的目标代码
四. 消除公共子表达式
T1=A*B; T2=B/C; T3=T1-T2; T4=A*B; T5=T4+D; …… 优化为 T1=A*B; T2=B/C; T3=T1-T2; T5=T1+D; ……
五. 窥孔优化实例
窥孔优化的特点是每个改进都可能引发新的改进机会,为了得到最好的 改进结果,一般可能需要对待优化的代码重复扫描进行窥孔优化。 i=5; i+=1; 计算表达式之值 T1=i; 及常数传播优化 T1=i; T1+=1; ret_reg=T1; ret; i=5; i=6; T1=6; T1=6; T1=7; ret_reg=7; ret;
8.3.2 数据流分析方法 8.3.3 循环优化
二. 常数合并和常数传播
1. 常数合并:在编译阶段就将源程序中常数表达式之值算出,而不必生成 用于计算该常数表达式的代码。 例如:① a+2*3翻译成a+6(在语法制导翻译时可以完成) ② a+2+3由于产生式归约顺序方面的原因,在语法分析时不可 能进行常数合并,而产生如下代码: T1=a; T1+=2; 替换为 T1=a; T1+=3; T1+=5; ③ 删除形如a+=0; a*=1;等操作。
第八章 代码优化
代码优化是编译程序为了产生高质量的目标代码而对源程序的中间代码进 行等价变换,或制定某种策略以使所产生的目标代码能合理地利用目标计 算机的资源的工作。 (减少目标程序占用的空间,并尽可能的提高运行速度,从而提高效率。) 按范围可分为: ①局部优化:指优化工作在程序的一个局部范围内进行。 (例如:线性窥孔优化;基本块的优化) ②全局优化:全局范围内控制流程和数据流程的分析 按阶段可分为: ①语法制导翻译阶段的优化 ②中间代码优化:中间代码序列一些代码的挪动或删除 ③目标代码优化:寄存器的分配,机器指令的使用和选择 另外,优化又可分时间优化和空间优化等 合算原则:以较低的代价取得较好的优化效果, 为值得优化的程序进行优化。
2. 无用代码:是控制无法达到或不进行任何有用操作的代码。 例: 对于 if(0) fun(); 编译器将其翻译成如下的中间代码指令序列: (jz, 0, 0, label) 测试条件总是真 (call_sub,0,0,_fun) 无用代码(删除) (:=,ret_reg,0,T1 ) 无用赋值(删除) (将fun的返回值存储到临时单元T1中) label: ……
无用代码的删除可能会受到常数传播的影响 常数传播到达数组元素,修改为j=a[6]; 这样 i 就变 fun( ) { int i, j, a[10]; 为无用变量,删除无用变量和无用赋值后,程序变为: fun() i=5; { int j,a[10]; ++i; j=a[6]; j=a[i]; …… …… } } 注:一般由用户定义的变量不予删除 3. 在涉及到硬件接口时,上述几种优化方法可能会产生不可预料的错误。 ANSI C中用关键字volatile来屏蔽编译程序对此类变量进行上述优化处理。 char *port; /* volatile char *port; */ port=(char *) 0x10; /* 将物理地址0x10处的8位内存单元映射为某个I/O端口 */ *port=0; /* 用*port访问该端口 */ *port=1; /* 在输出端口产生高电平 */ delay( ); *port=0;
2. 常数传播:若在程序运行时,一些变量的值在某一段程序范围内保持不 变,则对该变量的引用可以替换为对其值的直接引用。 这种常数传播可以一直延续到该变量被重新定值为止。 例: ① a=3; a=3; …… /*未对a重新定值*/ 替换为 …… b=a; b=3;
因为在多数机器上,用常数对变量赋值比内存单元间的复制有更高的效率。
相关文档
最新文档