8.2.2常数合并和常数传播 ·常数合并是指在编译时就将源程序中常数表达式之值先行 算出,不必生成计算该表达式的代码. ·例如,a+23可翻译成a+6.表达式a+1+3在翻译阶段生成的代 码为:TT1+=T1+=3由于对T1的两次定值未被引用,可将 其修改为:TTt=4 ·常数传播是指在程序运行时某段程序中的一些变量之值保 持不变,故在此范围内对该变量的引用可替换对其值的直接 引用,传播将一直延续到对其重新定值 例如,a=3;-未对a重新定值:b=;可改为:a=3:-3;
8.2.2 常数合并和常数传播 • 常数合并是指在编译时就将源程序中常数表达式之值先行 算出,不必生成计算该表达式的代码. • 例如, a+2*3可翻译成a+6. 表达式a+1+3在翻译阶段生成的代 码为: T1=a; T1+=1; T1+=3;由于对T1的两次定值未被引用,可将 其修改为: T1=a; T1+=4; • 常数传播是指在程序运行时某段程序中的一些变量之值保 持不变,故在此范围内对该变量的引用可替换对其值的直接 引用,传播将一直延续到对其重新定值 • 例如, a=3; …/*未对a重新定值*/; b=a; 可改为: a=3;…;b=3;
8.2.3无用变量与无用代码的删除 。 变量的最后一次引用到下次引用之前的最近一次赋值期间, 可视为无用变量.在变量的无用期内,对其的任何赋值均可 删除. ·例如:t0=a;t0+=5;x=t0;.;t0+=1;.t0=b;其中的赋值 t0+=1可被删除 ·对于那些被赋值后从未被引用的变量,其赋值操作是无用赋 值,可删除之 。 无用代码是指控制永运到达不了的代码:f(0){【},花括号 内为无用代码
8.2.3 无用变量与无用代码的删除 • 变量的最后一次引用到下次引用之前的最近一次赋值期间, 可视为无用变量.在变量的无用期内,对其的任何赋值均可 删除. • 例如: t0=a;t0+=5; x=t0;…;t0+=1;…t0=b;其中的赋值 t0+=1可被删除. • 对于那些被赋值后从未被引用的变量,其赋值操作是无用赋 值,可删除之. • 无用代码是指控制永远到达不了的代码: if(0) {…},花括号 内为无用代码
联合使用常数传播与册除无用代马 ·无用代码的删除还会受常数传播的影响,例如, fool(fint i,j,array[10];i=5;++i;j=array[i];... ·其中,并不是无用变量,但利用常数传播优化后: fool()fint i,j,array[10];i=5;++i;j=array[6];...} ·变为无用变量,删除后程序为 fool()fint j,array[10];j=array[6];...} 注意,对于与硬件相关的量(如监视/0端口的变量),我们不 能使用上述优化方案(见P291-P292的例子).在C中可用关 键字volatile(指明该变量的值不确定)屏蔽这类优化
联合使用常数传播与删除无用代码 • 无用代码的删除还会受常数传播的影响,例如, fool(){int i,j,array[10]; i=5;++i; j=array[i]; …} • 其中,i并不是无用变量,但利用常数传播优化后: fool(){int i,j,array[10];i=5;++i; j=array[6];…} • i变为无用变量,删除后程序为 fool(){int j,array[10]; j=array[6];…} • 注意,对于与硬件相关的量(如监视I/O端口的变量),我们不 能使用上述优化方案 (见P291-P292的例子).在C中可用关 键字volatile(指明该变量的值不确定)屏蔽这类优化
8.2.4窥孔优化实例 ·例对C程序:i=5;++i;return i+1;编译程序产生的中间代 码为: i=5;i+=1;T1=i;T1=i;T1+=1;ret reg=T1;ret; 首先建立一以变量名为关键字的符号表,其中每个变量的登记 项含有当前可确定的内容; 1.第一遍扫描完成计算常数表达式的值,修改符号表相关内容, 将变量引用改为对其值的引用: 读第一行时,表中建立的登记项,初值为5;再读第二行,因1 已登记,修改其值,得代码:=5;=6; 现在,读第三,四行,此时==6,于是将对的引用改为对其值 的引用:T1=6;T1=6;
8.2.4 窥孔优化实例 • 例 对C程序: i=5; ++i; return i+1;编译程序产生的中间代 码为: i=5; i+=1; T1=i; T1=i; T1+=1; ret_reg=T1; ret; 首先建立一以变量名为关键字的符号表,其中每个变量的登记 项含有当前可确定的内容; 1.第一遍扫描完成计算常数表达式的值,修改符号表相关内容, 将变量引用改为对其值的引用: 读第一行时,表中建立 i的登记项,初值为5;再读第二行,因i 已登记,修改其值,得代码:i=5;i=6; 现在,读第三,四行,此时i==6, 于是将对i的引用改为对其值 的引用:T1=6;T1=6;
此时在表中建立T的登记项,值为6;读第五行,变量T被再 定值,修改其登记项内容及输出T=7; 扫描第六行,T,的当前值为7:ret_reg=7; 最后一行无变量,不变.最后得 i=5;i=6;T=6;T=6;T=7;ret_reg=7;ret; 2.第二遍扫描完成无用变量的删除: 清除符号表登记项,扫描代码,对作为源操作数出现的每个 变量,在表中建立相应的项, 显然扫描完后所有以目的操作数形式出现,且在表中无登 记项的变量都是无用的,相应的操作可删去.本例中,T1是无 用的,其相关操作均可删除得: i=5;i=6;ret_reg=7;ret; 注意:由于是用户定义的变量,无法断定其是否不再引用, 不能作为无用变量:
此时在表中建立T1的登记项,值为6;读第五行, 变量T1被再 定值,修改其登记项内容及输出T1=7; 扫描第六行,T1的当前值为7: ret_reg=7; 最后一行无变量,不变.最后得 i=5;i=6;T1=6;T1=6;T1=7;ret_reg=7;ret; 2.第二遍扫描完成无用变量的删除: 清除符号表登记项,扫描代码,对作为源操作数出现的每个 变量,在表中建立相应的项. 显然扫描完后所有以目的操作数形式出现,且在表中无登 记项的变量都是无用的,相应的操作可删去.本例中,T1是无 用的,其相关操作均可删除,得: i=5;i=6;ret_reg=7;ret; 注意:由于i是用户定义的变量,无法断定其是否不再引用, 不能作为无用变量