/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Common Public License (CPL);
* 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/cpl1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.compilers.opt;
import org.jikesrvm.VM;
import org.jikesrvm.compilers.opt.ir.OPT_BasicBlock;
import org.jikesrvm.compilers.opt.ir.OPT_BasicBlockEnumeration;
import org.jikesrvm.compilers.opt.ir.OPT_IR;
/**
* Implementation of the dataflow equation system to calculate dominators.
*/
class OPT_DominatorSystem extends OPT_DF_System {
/**
* The governing IR.
*/
OPT_IR ir;
/**
* Default constructor.
* @param ir the governing IR
*/
public OPT_DominatorSystem(OPT_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 (OPT_BasicBlockEnumeration e = ir.getBasicBlocks(); e.hasMoreElements();) {
OPT_BasicBlock bb = e.next();
// add a data-flow equation for this basic block
// DOM(n) = {n} MEET {pred(n)}
OPT_DF_LatticeCell dom = findOrCreateCell(bb);
OPT_DF_LatticeCell[] pred = getCellsForPredecessors(bb);
newEquation(dom, OPT_DominatorOperator.MEET, pred);
}
}
/**
* Initialize the lattice variables (Dominator sets) for
* each basic block.
*/
protected void initializeLatticeCells() {
if (OPT_Dominators.COMPUTE_POST_DOMINATORS) {
OPT_BasicBlock exit = ir.cfg.exit();
OPT_DominatorCell last = (OPT_DominatorCell) getCell(exit);
for (final OPT_DF_LatticeCell latticeCell : cells.values()) {
OPT_DominatorCell cell = (OPT_DominatorCell) latticeCell;
if (cell == last) {
cell.addSingleBlock(cell.block);
} else {
cell.setTOP(ir);
}
}
} else {
OPT_BasicBlock start = ir.cfg.entry();
OPT_DominatorCell first = (OPT_DominatorCell) getCell(start);
for (final OPT_DF_LatticeCell latticeCell : cells.values()) {
OPT_DominatorCell cell = (OPT_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.
*/
protected void initializeWorkList() {
if (OPT_Dominators.COMPUTE_POST_DOMINATORS) {
// Add every equation to work list (to be safe)
// WARNING: an "end node" may be part of a cycle
for (OPT_BasicBlockEnumeration e = ir.getBasicBlocks(); e.hasMoreElements();) {
OPT_BasicBlock bb = e.next();
addCellAppearancesToWorkList(getCell(bb));
}
} else {
OPT_DominatorCell first = (OPT_DominatorCell) getCell(ir.cfg.entry());
addCellAppearancesToWorkList(first);
}
}
/**
* Get the OPT_DF_LatticeCell key corresponding to a basic block
* @param bb the basic block
* @return the key (just the block itself)
*/
Object getKey(OPT_BasicBlock bb) {
return bb;
}
/**
* Make a new OPT_DF_LatticeCell key corresponding to a basic block
* @param key the basic block
* @return the new cell
*/
protected OPT_DF_LatticeCell makeCell(Object key) {
return new OPT_DominatorCell((OPT_BasicBlock) key, ir);
}
/**
* Return a list of lattice cells corresponding to the
* predecessors of a basic block.
* @param bb the basic block
*/
OPT_DF_LatticeCell[] getCellsForPredecessors(OPT_BasicBlock bb) {
if (OPT_Dominators.COMPUTE_POST_DOMINATORS) {
/****
if ( bb.mayThrowUncaughtException() ) {
if (OPT_Dominators.DEBUG) VM.sysWrite("LOCATION #1 ...\n");
// Include exit node as an output node
OPT_DF_LatticeCell s[] = new OPT_DF_LatticeCell[bb.getNumberOfOut()+1];
OPT_BasicBlockEnumeration e = bb.getOut();
for (int i=0; i<s.length-1; i++ ) {
OPT_BasicBlock p = e.next();
s[i] = findOrCreateCell(getKey(p));
}
s[s.length-1] = findOrCreateCell(getKey(ir.cfg.exit()));
return s;
}
else
****/
{
if (OPT_Dominators.DEBUG) {
VM.sysWrite("LOCATION #2 ...\n");
}
OPT_DF_LatticeCell[] s = new OPT_DF_LatticeCell[bb.getNumberOfOut()];
OPT_BasicBlockEnumeration e = bb.getOut();
for (int i = 0; i < s.length; i++) {
OPT_BasicBlock p = e.next();
s[i] = findOrCreateCell(getKey(p));
}
return s;
}
} else {
if (OPT_Dominators.DEBUG) {
System.out.println("LOCATION #3 ...");
}
OPT_DF_LatticeCell[] s = new OPT_DF_LatticeCell[bb.getNumberOfIn()];
OPT_BasicBlockEnumeration e = bb.getIn();
for (int i = 0; i < s.length; i++) {
OPT_BasicBlock p = e.next();
s[i] = findOrCreateCell(getKey(p));
}
return s;
}
}
}