/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.compilers.opt.controlflow;
import java.util.Enumeration;
import org.jikesrvm.VM;
import org.jikesrvm.compilers.opt.dfsolver.DF_LatticeCell;
import org.jikesrvm.compilers.opt.dfsolver.DF_System;
import org.jikesrvm.compilers.opt.ir.BasicBlock;
import org.jikesrvm.compilers.opt.ir.IR;
/**
* Implementation of the dataflow equation system to calculate dominators.
*/
class DominatorSystem extends DF_System {
/**
* The governing IR.
*/
private final IR ir;
/**
* Default constructor.
* @param ir the governing IR
*/
DominatorSystem(IR ir) {
this.ir = ir;
setupEquations();
}
/**
* Go through each basic block in the IR, and add equations
* to the system as required.
* <p> Uses the algorithm contained in Dragon book, pg. 670-1.
* <pre>
* D(n0) := { n0 }
* for n in N - { n0 } do D(n) := N;
* while changes to any D(n) occur do
* for n in N - {n0} do
* D(n) := {n} U (intersect of D(p) over all predecessors p of n)
* </pre>
*/
void setupEquations() {
// loop through each basic block in the IR
for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements();) {
BasicBlock bb = e.nextElement();
// add a data-flow equation for this basic block
// DOM(n) = {n} MEET {pred(n)}
DF_LatticeCell dom = findOrCreateCell(bb);
DF_LatticeCell[] pred = getCellsForPredecessors(bb);
newEquation(dom, DominatorOperator.MEET, pred);
}
}
/**
* Initialize the lattice variables (Dominator sets) for
* each basic block.
*/
@Override
protected void initializeLatticeCells() {
if (Dominators.COMPUTE_POST_DOMINATORS) {
BasicBlock exit = ir.cfg.exit();
DominatorCell last = (DominatorCell) getCell(exit);
for (final DF_LatticeCell latticeCell : cells.values()) {
DominatorCell cell = (DominatorCell) latticeCell;
if (cell == last) {
cell.addSingleBlock(cell.block);
} else {
cell.setTOP(ir);
}
}
} else {
BasicBlock start = ir.cfg.entry();
DominatorCell first = (DominatorCell) getCell(start);
for (final DF_LatticeCell latticeCell : cells.values()) {
DominatorCell cell = (DominatorCell) latticeCell;
if (cell == first) {
cell.addSingleBlock(cell.block);
} else {
cell.setTOP(ir);
}
}
}
}
/**
* Initialize the work list for the dataflow equation system.
* <p> The initial work list is every equation containing the start
* node.
*/
@Override
protected void initializeWorkList() {
if (Dominators.COMPUTE_POST_DOMINATORS) {
// Add every equation to work list (to be safe)
// WARNING: an "end node" may be part of a cycle
for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements();) {
BasicBlock bb = e.nextElement();
addCellAppearancesToWorkList(getCell(bb));
}
} else {
DominatorCell first = (DominatorCell) getCell(ir.cfg.entry());
addCellAppearancesToWorkList(first);
}
}
/**
* Get the DF_LatticeCell key corresponding to a basic block
* @param bb the basic block
* @return the key (just the block itself)
*/
Object getKey(BasicBlock bb) {
return bb;
}
/**
* Make a new DF_LatticeCell key corresponding to a basic block
* @param key the basic block
* @return the new cell
*/
@Override
protected DF_LatticeCell makeCell(Object key) {
return new DominatorCell((BasicBlock) key, ir);
}
/**
* @param bb the basic block
* @return a list of lattice cells corresponding to the
* predecessors of a basic block
*/
DF_LatticeCell[] getCellsForPredecessors(BasicBlock bb) {
if (Dominators.COMPUTE_POST_DOMINATORS) {
/****
if ( bb.mayThrowUncaughtException() ) {
if (Dominators.DEBUG) VM.sysWriteln("LOCATION #1 ...");
// Include exit node as an output node
DF_LatticeCell s[] = new DF_LatticeCell[bb.getNumberOfOut()+1];
Enumeration<BasicBlock> e = bb.getOut();
for (int i=0; i<s.length-1; i++ ) {
BasicBlock p = e.next();
s[i] = findOrCreateCell(getKey(p));
}
s[s.length-1] = findOrCreateCell(getKey(ir.cfg.exit()));
return s;
}
else
****/
{
if (Dominators.DEBUG) {
VM.sysWriteln("LOCATION #2 ...");
}
DF_LatticeCell[] s = new DF_LatticeCell[bb.getNumberOfOut()];
Enumeration<BasicBlock> e = bb.getOut();
for (int i = 0; i < s.length; i++) {
BasicBlock p = e.nextElement();
s[i] = findOrCreateCell(getKey(p));
}
return s;
}
} else {
if (Dominators.DEBUG) {
System.out.println("LOCATION #3 ...");
}
DF_LatticeCell[] s = new DF_LatticeCell[bb.getNumberOfIn()];
Enumeration<BasicBlock> e = bb.getIn();
for (int i = 0; i < s.length; i++) {
BasicBlock p = e.nextElement();
s[i] = findOrCreateCell(getKey(p));
}
return s;
}
}
}