/*
* 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.compilers.opt.ir.OPT_BasicBlock;
import org.jikesrvm.compilers.opt.ir.OPT_BasicBlockEnumeration;
import org.jikesrvm.compilers.opt.ir.OPT_IR;
/**
* Calculate dominators for basic blocks.
* <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>
* <p> TODO: we do not support IRs with exception handlers!!
*/
class OPT_Dominators {
/**
* Control for debug output
*/
static final boolean DEBUG = false;
/**
* Should we compute post-dominators instead of dominators? This is
* false by default.
*/
static boolean COMPUTE_POST_DOMINATORS = false;
/**
* Calculate the dominators for an IR.
* <p> After this pass, each basic block's scrach field points to
* an <code> OPT_DominatorInfo </code> object, which holds the dominators
* of the basic block.
*
* @param ir the IR in question
*/
public static void perform(OPT_IR ir) {
if (ir.hasReachableExceptionHandlers()) {
throw new OPT_OperationNotImplementedException("IR with exception handlers");
}
OPT_DominatorSystem system = new OPT_DominatorSystem(ir);
if (DEBUG) {
System.out.print("Solving...");
}
if (DEBUG) {
System.out.println(system);
}
system.solve();
if (DEBUG) {
System.out.println("done");
}
OPT_DF_Solution solution = system.getSolution();
if (DEBUG) {
System.out.println("Dominator Solution :" + solution);
}
if (DEBUG) {
System.out.print("Updating blocks ...");
}
updateBlocks(solution);
if (DEBUG) {
System.out.println("done.");
}
if (ir.options.PRINT_DOMINATORS) {
printDominators(ir);
}
}
/**
* Calculate the "approximate" dominators for an IR i.e., the
* dominators in the factored CFG rather than the normal CFG.
* <p> (No exception is thrown if the input IR has handler blocks.)
*
* <p> After this pass, each basic block's scratch field points to
* an OPT_DominatorInfo object, which holds the dominators
* of the basic block.
*
* @param ir the IR in question
*/
public static void computeApproxDominators(OPT_IR ir) {
OPT_DominatorSystem system = new OPT_DominatorSystem(ir);
if (DEBUG) {
System.out.print("Solving...");
}
if (DEBUG) {
System.out.println(system);
}
system.solve();
if (DEBUG) {
System.out.println("done");
}
OPT_DF_Solution solution = system.getSolution();
if (DEBUG) {
System.out.println("Dominator Solution :" + solution);
}
if (DEBUG) {
System.out.print("Updating blocks ...");
}
updateBlocks(solution);
if (DEBUG) {
System.out.println("done.");
}
if (ir.options.PRINT_DOMINATORS) {
printDominators(ir);
}
}
/**
* Calculate the postdominators for an IR.
* <p> After this pass, each basic block's scrach field points to
* an OPT_DominatorInfo object, which holds the postdominators
* of the basic block.
*
* @param ir the IR in question
*/
public static void computeApproxPostdominators(OPT_IR ir) {
OPT_Dominators.COMPUTE_POST_DOMINATORS = true;
OPT_DominatorSystem system = new OPT_DominatorSystem(ir);
if (DEBUG) {
System.out.print("Solving...");
}
if (DEBUG) {
System.out.println(system);
}
system.solve();
if (DEBUG) {
System.out.println("done");
}
OPT_DF_Solution solution = system.getSolution();
if (DEBUG) {
System.out.println("Postdominator Solution :" + solution);
}
if (DEBUG) {
System.out.print("Updating blocks ...");
}
updateBlocks(solution);
if (DEBUG) {
System.out.println("done.");
}
if (ir.options.PRINT_DOMINATORS) {
printDominators(ir);
}
OPT_Dominators.COMPUTE_POST_DOMINATORS = false;
}
/**
* For each basic block in the data flow system solution,
* create an <code> OPT_DominatorInfo </code> and store it in the basic
* blocks scratchObject
*
* @param solution the solution to the Dominators equations
*/
public static void updateBlocks(OPT_DF_Solution solution) {
for (final OPT_DF_LatticeCell latticeCell : solution.values()) {
OPT_DominatorCell cell = (OPT_DominatorCell) latticeCell;
OPT_BasicBlock b = cell.block;
b.scratchObject = new OPT_DominatorInfo(cell.dominators);
if (DEBUG) {
System.out.println("Dominators of " + b + ":" + cell.dominators);
}
}
}
/**
* Print the (already calculated) dominators.
* @param ir the IR
*/
public static void printDominators(OPT_IR ir) {
for (OPT_BasicBlockEnumeration e = ir.getBasicBlocks(); e.hasMoreElements();) {
OPT_BasicBlock b = e.next();
OPT_DominatorInfo i = (OPT_DominatorInfo) b.scratchObject;
System.out.println("Dominators of " + b + ":" + i.dominators);
}
}
}