在Neo Pascal中,常量传播是基于过程内讨论的。下面将详细分析Neo Pascal中常量传播算法的源代码实现。
程序7-11 Const_Prop.cpp
第3行:初始化常量传播的结束标志。与许多优化算法一样,常量传播通常也会进行多遍处理,直到进入稳定状态为止。所谓“稳定状态”就是指在一遍扫描过程中,代码没有发生任何改进的状态。实际上,多遍扫描处理的目的就是为了使常量传播的范围更广,效果更显著。
第4行:判断常量传播是否结束。
第7~31行:遍历IR列表。
第9行:获取当前IR。
第11~16行:获取处理方案。
第19、20行:判断m_Op2操作数是否需要进行常量传播优化。通常,要满足如下三个条件:
(1)操作数必须为变量,即m_iType==OpInfo::VAR。
(2)操作数不允许是间接寻址,即m_bRef为false。
(3)不允许存在未初始化的路径,即m_bUninit为false。
第22行:调用GenConstOp函数进行常量传播。GenConstOp函数声明形式如下:
【声明7-10】
注意,参数Op为引用传递,也就是说,如果给定操作数的所有ud点都满足常量传播的要求,那么,GenConstOp将通过修改Op的属性,以实现常量传播的目的。函数的返回值用于标识实参操作数在常量传播过程中是否被修改。关于GenConstOp函数的实现稍后详解。
第24~28行:判断m_Opl操作数是否需要进行常量传播优化。如满足以上三个条件,即调用GenConstOp函数进行常量传播。
下面来看看GenConstOp函数的实现,这是常量传播的核心。(www.daowen.com)
程序7-12 Const_Prop.cpp
第7行:遍历操作数的ud链信息。
第9行:根据ud链中的定值点信息,获取相应的IR。
第11~16行:获取处理方案。
第19~54行:逐一判断ud链各定值点是否满足常量传播的基本要求,主要判断如下三个条件:
(1)第19行:判断定值点IR的m_Opl是否为常量。
(2)第21行:判断定值点IR的m_Rslt是否为间接寻址方式。
(3)第23~53行:判断各定值点的常量值是否相同。这里,值得注意的是,整型、实型常量比较m_fVal属性,而其他类型常量直接比较m_szName属性。除了比较常量值之外,编译器还严格比较常量的类型信息,即m_ConstType属性。
在逐一判断比较的过程中,如出现不满足常量传播要求的情形,则立刻返回false。也就是说,这个for循环能够正常结束即表明给定操作数ud链的各定值点完全满足常量传播的要求。
第61、62行:这个if结构主要用于处理操作数的ud链为空的情况。这种情况是不需要进行常量传播的。
第63~112行:通过改变参数Op的属性,完成常量传播。
第63行:设置m_iType属性为OpInfo::CONST。
第64~71行:设置m_iLink属性。根据常量传播的特点,操作数定值点的IR的操作符可能有两种情况,即赋值运算或类型转换运算。如果IR是赋值运算,那么,只需将m_iLink直接指向该常量符号即可。如果IR是类型转换运算,就必须由编译器完成常量类型的转换,即生成一个新的常量符号用于存储转换结果。并且将m_iLink属性指向新的常量符号,以保证常量传播后IR操作数的类型仍然是兼容的。
第73~112行:根据定值点的IR操作符,设置新生成常量符号的类型信息。
至此,已经详细讨论了Neo Pascal中常量传播的实现细节。然而,常量传播的一些理论问题并未作深入阐述。有兴趣的读者可以参考“龙书”的相关章节。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。