All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dragome.compiler.graph.DominatorTree Maven / Gradle / Ivy

There is a newer version: 0.96-beta4
Show newest version
package com.dragome.compiler.graph;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

import com.dragome.compiler.utils.Log;

public class DominatorTree
{

	private ControlFlowGraph graph;

	public DominatorTree(ControlFlowGraph theGraph)
	{
		graph= theGraph;
	}

	/**
	 * Sets the pre-order index of a node.
	 */
	private void visit(Node node, Collection visited)
	{
		// Establish preorder index.
		node.setPreOrderIndex(visited.size());
		visited.add(node);

		for (Node succ : node.succs())
		{
			if (!visited.contains(succ))
			{
				visit(succ, visited);
			}
		}

	}

	/**
	 * Builds the dominator tree and store it in the respective nodes. It will
	 * remove all unreachable nodes on the way!
	 */
	public void build()
	{

		// Construct list of nodes in pre-order order.
		ArrayList preOrder= new ArrayList();

		visit(graph.getSource(), preOrder);

		// Remove unreachable nodes.
		for (Node node : new ArrayList(graph.getNodes()))
		{
			if (!preOrder.contains(node))
			{
				Log.getLogger().warn("Unreachable code detected and removed");
				// Logger.getLogger().info("Removed " + node);
				graph.removeInEdges(node);
				graph.removeOutEdges(node);
				graph.removeNode(node);
			}
			else if (node.getPreOrderIndex() == -1)
			{
				throw new RuntimeException("Pre-order not set for " + node);
			}
		}

		int size= graph.size(); // The number of vertices in the cfg

		Map snkPreds= new LinkedHashMap(); // The predacessor vertices from the sink

		// Determine the predacessors of the cfg's sink node

		int rootIndex= graph.getSource().getPreOrderIndex();

		if (rootIndex < 0 || rootIndex >= size)
			throw new RuntimeException("Root index out of range");

		BitSet[] domMatrix= new BitSet[size];

		for (int i= 0; i < size; i++)
		{
			BitSet domVector= new BitSet(size);

			if (i == rootIndex)
			{

				domVector.set(rootIndex);
			}
			else
			{

				domVector.set(0, size);
			}

			domMatrix[i]= domVector;
		}

		boolean changed;

		do
		{
			changed= false;

			Iterator nodes= preOrder.iterator();

			while (nodes.hasNext())
			{
				Node node= (Node) nodes.next();

				int i= node.getPreOrderIndex();

				if (i < 0 || i >= size)
					throw new RuntimeException("Unreachable node " + node);

				if (i == rootIndex)
				{
					continue;
				}

				BitSet oldSet= domMatrix[i];

				BitSet domVector= new BitSet(size);
				domVector.or(oldSet);

				Collection preds= node.preds();

				Iterator e= preds.iterator();

				// predacessors.
				while (e.hasNext())
				{
					Node pred= (Node) e.next();

					int j= pred.getPreOrderIndex();
					if (j == -1)
						throw new RuntimeException("Unreachable node " + pred);

					domVector.and(domMatrix[j]);
				}

				// Don't forget to account for the sink node if node is a

				preds= (Collection) snkPreds.get(node);

				if (preds != null)
				{
					e= preds.iterator();

					while (e.hasNext())
					{
						Node pred= (Node) e.next();

						int j= pred.getPreOrderIndex();

						domVector.and(domMatrix[j]);
					}
				}

				domVector.set(i);

				if (!domVector.equals(oldSet))
				{
					changed= true;
					domMatrix[i]= domVector;
				}
			}
		}
		while (changed);

		for (Node node : graph.getNodes())
		{
			node.setDomParent(null);
			node.getDomChildren().clear();
		}

		// A node's immediate dominator is its closest dominator. So, we

		for (Node node : graph.getNodes())
		{
			int i= node.getPreOrderIndex();

			if (i < 0 || i >= size)
				throw new RuntimeException("Unreachable node " + node);

			if (i == rootIndex)
			{
				continue;
			}

			BitSet domVector= domMatrix[i];

			BitSet idom= new BitSet(size);
			idom.or(domVector);
			idom.clear(i);

			for (int j= 0; j < size; j++)
			{
				if (i != j && domVector.get(j))
				{

					BitSet b= new BitSet(size);

					b.or(domMatrix[j]);
					b.flip(0, size);
					b.set(j);
					idom.and(b);
				}
			}

			Node parent= null;

			for (int j= 0; j < size; j++)
			{
				if (idom.get(j))
				{
					Node p= preOrder.get(j);
					if (parent != null)
						throw new RuntimeException(node + " has more than one immediate dominator: " + parent + " and " + p);
					parent= p;
				}
			}

			if (parent == null)
				throw new RuntimeException(node + " has 0 immediate dominators");

			node.setDomParent(parent);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy