在现代编译技术中,SSA是一个不得不提及的话题。对于初学者而言,深入讨论SSA可能并不太适合。不过,笔者觉得领略一下SSA的魅力还是非常有必要的。这里,笔者并不打算讨论基于SSA的优化技术,只想结合GCC的实现,简单介绍一下SSA的基本概念与形式。
1991年,在R.Cytron、J.Ferrante、B.Rosen、M.Wegman、K.Zadeck撰写的《EfficientlyComputing Static Single Assignment Form and Control Dependence Graph》一文中首先提出了SSA(static single assignment form)的概念。因此,与其他IR方案相比,SSA是相对较新的IR形式。所谓SSA就是指一个函数内每个被赋值的变量只存在一次赋值,那么,这个函数满足SSA的形式。SSA的形式有效地将程序中运算的值与它们的存储位置分离,对数据流分析及某些优化算法的实现是有利的,例如,常量传播、值编号、冗余删除、强度削弱等。
事实上,真正满足SSA形式的实例几乎是不存在的,也就是说,在实际程序中对一个变量多次赋值的情况是不可避免的。那么,如何将普通的程序转换成SSA的形式呢?事实上,当需要对某个变量进行多次赋值时,编译器会为其生成该变量的新副本。当然,这些关于同一个变量的副本集合最终仍然会被合并。在GCC中,SSA是基于GIMPLE实现的,可以使用“-fdump-tree-ssa”将程序的ssa形式输出。下面,笔者就来举一个SSA的实例,以便读者理解。
例10-11 SSA实例分析。(www.daowen.com)
分析本例后,不难发现,SSA的转换就是为每一个赋值的变量带上一个下标,并在汇合入口处(例如,标号Ll处)使用一个PHI函数(在书面资料上通常写作“Φ”),以标识对一个变量的多次赋值形式。每个PHI函数的参数个数与其所处点的关于该变量的版本个数一致。值得注意的是,本例中所有的被赋值变量只可能存在一次被赋值的情形,这是SSA的基本要求。然而,读者不要理解成SSA中的所有变量只存在一次被引用的情况,显然,SSA并没有对引用的次数作限制,在本例中,Zj就被多次引用了。
SSA的形式对于优化是非常有利的,其中,最令人满意的是,许多基于SSA设计的块内局部优化可以很方便地被移植到过程内使用。当然,笔者对这个话题就不再展开了,有兴趣的读者可以参考《编译器工程》及《高级编译器设计》。
在处理完成后,编译器最终还会将SSA的形式还原到原始状态。实际上,这个过程就需要删除PHI函数,因为它们只是一个形式上的工具而己,并不具有实际的作用。这里,必须明确一点,SSA中的程序赋值个数通常会比原始形式的赋值个数多一些,一般是1.3---3.8倍左右。不过,SSA的优化效果较好,因此这种影响并不太明显。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。