从算法实现上来说,代数简化是一种代价极小的优化算法,甚至不需要数据流分析的支持。设计代数简化算法时,有个问题需要注意,就是不要把代数简化过于神化了。事实上,试图运用代数简化解决一切运算化简的问题是徒劳的。这种想法不但会大大增加算法设计的难度,而且也会影响算法执行的效率。这里,Neo Pascal只实现了一个简单的算法框架,并不力求解决那些复杂的运算化简问题。
另外,还应该注意一些特定的代数性质,例如运算的交换律、结合律等。其中,交换律是最常见的代数性质。在很多情况下,如果交换律处理得不好,就会使源代码变得极其冗长。当然,要解决这类问题的方法是非常简单的,笔者将在源代码分析中详述。
程序7-15 IRSimplify.cpp
第3~10行:主要用于初始化Num2Bit映射表。这个表描述的就是乘、除运算中特定常量与相应移位运算的位数之间的关系。例如,n*8=n shl 3,就可以将<8,3>存入Num2Bit备用。有读者可能有疑问,为什么不直接使用log函数计算呢?主要是考虑到log函数的结果是浮点数,而细小误差可能会导致非常严重的错误。
第12行:遍历IR列表。
第14行:获取当前IR。
第16~21行:获取处理方案。
第24~32行:如果运算是满足交换律的,则将IR中常量操作数统一置于操作数2中。这样做可以避免编写许多不必要的判断及处理。当然,这项工作也可以在生成IR时完成。理论上讲,操作数1、操作数2都是常量的IR是不存在的,应该已经被常量折叠优化了。
第35~42行:依据等式i+O=i,将IR转换为赋值形式。这里,不必考虑O+i=i的情况,因为在第24~32行中已经进行了操作数交换。以下满足交换律的等式的处理方法类似。
第46~53行:依据等式i-O=i,将IR转换为赋值形式。
第59~66行:依据等式i*l=i、i div l=i、i mod l=i,将IR转换为赋值形式。(www.daowen.com)
第71~84行:将乘以、除以一个常量2“的IR转换为移位IR。
第89~96行:依据等式i shl O=i、i shr O=i,将IR转换为赋值形式。
第100~108行:依据等式i or i-i,将IR转换为赋值形式。
第109~116行:依据等式i or false=i,将IR转换为赋值形式。
第117~125行:依据等式i or true=true,将IR转换为赋值形式。
第129~137行:依据等式i and i=i,将IR转换为赋值形式。
第138~145行:依据等式i and true=i,将IR转换为赋值形式。
第146~164行:依据等式i and false=false,将IR转换为赋值形式。
关于代数简化的实现,就讨论至此。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。