控制流分析
发现基本块,构造dom-tree,发现loop(回边:head dom tail)。
控制流分析方法
两种控制流分析方法:
发现基本块,构造流图。
1. 使用dominator发现循环。—— 对于迭代数据流分析,已经足够。
2. interval分析 -> structure分析 -> elimination方法。—— 非常复杂、高级的方法。一般compiler没有实现。
在流图中,添加一个唯一的entry和exit,这样使得编译算法描述起来变得简单。
扩展BB:多个BB构成的tree,单入口、多出口。许多局部优化在EBB上进行更加有效率。
Build_Ebb(r):以基本块r为root,构造一个Ebb。同时手机Ebb_roots。
Build_All_Ebbs(r): 以基本块r为起点,构造所有的Ebb。依次从Ebb_roots中取出节点,以该节点为root获得Ebb。
深度优先遍历和广度优先遍历
深度优先遍历时,对每个节点给一个编号,root节点编号为1。节点n的深度优先编号记为dfn(n)。
dfn(n)就是先序号。
计算深度优先span tree,先序号,后序号。
Depth_First_Search_PP(n)
{
visit[n] = true;
pre[n] = j++;
for (each m = succ(n))
{
if (!visit[m]) {
Depth_First_Search_PP(m);
edgeType(n, m) = tree;
}
else if (pre[n] < pre[m]) // m已经访问过,且先序号较大,forward。
edgeType(n, m) = forward;
else if (post[m] = 0) // m已经访问过,且先序号较小,而后序尚未访问,back。
edgeType(n, m) = back;
else
edgeType(n, m) = cross; // m已经访问过,后序已访问,cross。
}
post[n] = i++;
}
计算dominator
基本算法,计算dom(n)和idom(n)。
复杂算法,计算idom(n)。
循环和强连通组件(Strongly Connected Components)
一个循环有两个entry,该循环不是一个自然循环。
从回边m -> n (n dom m),计算以n为head的自然循环:将m的pred节点依次添加到loop集合。
许多优化需要将代码移动到循环的head之前。为了保证这一位置的唯一性,添加一个prehead节点。
如果两个自然循环共享一个head,则无法判断这两个循环谁嵌套谁。
计算流图中的所有强连通组件算法Strong_Components(root)。
SCC中有一个节点n,lowlink(n)是SCC中节点m的先序号,它的值在SCC中最小。从n ...-> m,要么存在back边,要么存在cross边。
LL(n)就是节点m。
流图的规约性(即结构良好性)
使用某种变换,将流图的子图规约为一个节点,最终将整个流图规约为一个节点。
如果流图中的循环都是自然循环(回边决定一个循环),则是可规约的。循环只能通过head进入,不会有jump语句跳入到循环的中间去。不使用goto语句跳入循环,就不会产生不规约的流图。