/* C O N T R O L F L O W * * C F _ I D O M . C */ #include "../share/types.h" #include "../share/debug.h" #include "../share/lset.h" #include "../share/alloc.h" #include "cf.h" /* The algorithm for finding dominators in a flowgraph * that is used here, was developed by Thomas Lengauer * and Robert E. Tarjan of Stanford University. * The algorithm is described in their article: * A Fast Algorithm for Finding Dominators * in a Flowgraph * which was published in: * ACM Transactions on Programming Languages and Systems, * Vol. 1, No. 1, July 1979, Pages 121-141. */ #define UNREACHABLE(b) (b->B_SEMI == (short) 0) short dfs_nr; bblock_p *vertex; /* dynamically allocated array */ STATIC dfs(v) bblock_p v; { /* Depth First Search */ Lindex i; bblock_p w; v->B_SEMI = ++dfs_nr; vertex[dfs_nr] = v->B_LABEL = v; v->B_ANCESTOR = (bblock_p) 0; for (i = Lfirst(v->b_succ); i != (Lindex) 0; i = Lnext(i,v->b_succ)) { w = (bblock_p) Lelem(i); if (w->B_SEMI == 0) { w->B_PARENT = v; dfs(w); } } } STATIC compress(v) bblock_p v; { if (v->B_ANCESTOR->B_ANCESTOR != (bblock_p) 0) { compress(v->B_ANCESTOR); if (v->B_ANCESTOR->B_LABEL->B_SEMI < v->B_LABEL->B_SEMI) { v->B_LABEL = v->B_ANCESTOR->B_LABEL; } v->B_ANCESTOR = v->B_ANCESTOR->B_ANCESTOR; } } STATIC bblock_p eval(v) bblock_p v; { if (v->B_ANCESTOR == (bblock_p) 0) { return v; } else { compress(v); return v->B_LABEL; } } STATIC linkblocks(v,w) bblock_p v,w; { w->B_ANCESTOR = v; } dominators(r,n) bblock_p r; short n; { /* Compute the immediate dominator of every basic * block in the control flow graph rooted by r. */ register short i; Lindex ind, next; bblock_p v,w,u; dfs_nr = 0; vertex = (bblock_p *) newmap(n); /* allocate vertex (dynamic array). All remaining * initializations were done by the routine * nextblock of get.c. */ dfs(r); for (i = dfs_nr; i > 1; i--) { w = vertex[i]; for (ind = Lfirst(w->b_pred); ind != (Lindex) 0; ind = Lnext(ind,w->b_pred)) { v = (bblock_p) Lelem(ind); if (UNREACHABLE(v)) continue; u = eval(v); if (u->B_SEMI < w->B_SEMI) { w->B_SEMI = u->B_SEMI; } } Ladd(w,&(vertex[w->B_SEMI]->B_BUCKET)); linkblocks(w->B_PARENT,w); for (ind = Lfirst(w->B_PARENT->B_BUCKET); ind != (Lindex) 0; ind = next) { next = Lnext(ind,w->B_PARENT->B_BUCKET); v = (bblock_p) Lelem(ind); Lremove(v,&w->B_PARENT->B_BUCKET); u = eval(v); v->b_idom = (u->B_SEMI < v->B_SEMI ? u : w->B_PARENT); } } for (i = 2; i <= dfs_nr; i++) { w = vertex[i]; if (w->b_idom != vertex[w->B_SEMI]) { w->b_idom = w->b_idom->b_idom; } } r->b_idom = (bblock_p) 0; oldmap(vertex,n); /* release memory for dynamic array vertex */ }