public HashMap<PLIRBasicBlock, PLIRBasicBlock> generateDominatorTree(PLIRBasicBlock r)
	{
		// step 1
		nid = 0;
		for (PLIRBasicBlock block : r.treeVertexSet)
		{
			pred.put(block, new ArrayList<PLIRBasicBlock>());
			semi.put(block, 0);
		}
		visited = new ArrayList<PLIRBasicBlock>();
		DomDFS(r);
		
		// Steps 2/3 (p.129 of [1])
		for (int i = r.treeSize; i >= 2; i--)
		{
			// ***step 2
			PLIRBasicBlock w = idMap.get(i);
			for (PLIRBasicBlock v : pred.get(w))
			{
				PLIRBasicBlock u = DomEval(v);
				if (semi.get(u) < semi.get(w))
				{
					semi.put(w, semi.get(u));
				}
			}
			
			// Add w to the bucket
			PLIRBasicBlock vertex = idMap.get(semi.get(w));
			if (bucket.containsKey(vertex) == false)
			{
				bucket.put(vertex, new ArrayList<PLIRBasicBlock>());
			}
			bucket.get(vertex).add(w);
			
			// Link
			DomLink(parent.get(w), w);
			
			// ***step 3
			for (PLIRBasicBlock v : bucket.get(parent.get(w)))
			{
				bucket.get(parent.get(w)).remove(v);
				PLIRBasicBlock u = DomEval(v);
				
				if (semi.get(u) < semi.get(v))
				{
					dom.put(v, u);
				}
				else
				{
					dom.put(v,  parent.get(w));
				}
			}
		}
		
		// Step 4
		for (int i = 2; i <= r.treeSize; i++)
		{
			PLIRBasicBlock w = idMap.get(i);
			if (dom.get(w).equals(idMap.get(semi.get(w))) == false)
			{
				dom.put(w, dom.get(dom.get(w)));
			}
		}
		dom.put(r, null);
		
		return dom;
	}