ack/util/ego/cf/cf_idom.c
1987-03-10 11:49:39 +00:00

144 lines
2.9 KiB
C

/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* 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 */
}