/* * 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 java.util.Enumeration; 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 dominance frontier for a set of basic blocks. * * <p> Uses the algorithm of Cytron et al., TOPLAS Oct. 91: * * <pre> * for each X in a bottom-up traversal of the dominator tree do * * DF(X) < - null * for each Y in Succ(X) do * if (idom(Y)!=X) then DF(X) <- DF(X) U Y * end * for each Z in {idom(z) = X} do * for each Y in DF(Z) do * if (idom(Y)!=X) then DF(X) <- DF(X) U Y * end * end * </pre> * * <p> TODO: we do not support IRs with exception handlers!! */ class OPT_DominanceFrontier extends OPT_CompilerPhase { static final boolean DEBUG = false; /** * Should this phase be performed? This is a member of a composite * phase, so always return true. The parent composite phase will * dictate. * @param options controlling compiler options */ public final boolean shouldPerform(OPT_Options options) { return true; } /** * Return this instance of this phase. This phase contains no * per-compilation instance fields. * @param ir not used * @return this */ public OPT_CompilerPhase newExecution(OPT_IR ir) { return this; } /** * Return a String representation for this phase * @return a String representation for this phase */ public final String getName() { return "Dominance Frontier"; } /** * Should the IR be printed either before or after performing this phase? * * @param options controlling compiler options * @param before true iff querying before the phase * @return true or false */ public final boolean printingEnabled(OPT_Options options, boolean before) { return false; } /** * Calculate the dominance frontier for each basic block in the * CFG. Stores the result in the DominatorTree for the governing * IR. * * <p> NOTE: The dominator tree MUST be calculated BEFORE calling this * routine. * * @param ir the governing IR */ public void perform(OPT_IR ir) { // make sure the dominator computation completed successfully if (!ir.HIRInfo.dominatorsAreComputed) { return; } // make sure dominator tree is computed if (ir.HIRInfo.dominatorTree == null) { return; } // for each X in a bottom-up traversal of the dominator tree do OPT_DominatorTree tree = ir.HIRInfo.dominatorTree; for (Enumeration<OPT_TreeNode> x = tree.getBottomUpEnumerator(); x.hasMoreElements();) { OPT_DominatorTreeNode v = (OPT_DominatorTreeNode) x.nextElement(); OPT_BasicBlock X = v.getBlock(); if (DEBUG) { System.out.println("Computing frontier for node " + X); } OPT_BitVector DF = new OPT_BitVector(ir.getMaxBasicBlockNumber() + 1); v.setDominanceFrontier(DF); // for each Y in Succ(X) do for (OPT_BasicBlockEnumeration y = X.getOut(); y.hasMoreElements();) { OPT_BasicBlock Y = y.next(); // skip EXIT node if (Y.isExit()) { continue; } // if (idom(Y)!=X) then DF(X) <- DF(X) U Y if (OPT_LTDominatorInfo.getIdom(Y) != X) { DF.set(Y.getNumber()); } } if (DEBUG) { System.out.println("After local " + DF); } // for each Z in {idom(z) = X} do for (Enumeration<OPT_TreeNode> z = tree.getChildren(X); z.hasMoreElements();) { OPT_DominatorTreeNode zVertex = (OPT_DominatorTreeNode) z.nextElement(); OPT_BasicBlock Z = zVertex.getBlock(); if (DEBUG) { System.out.println("Processing Z = " + Z); } // for each Y in DF(Z) do for (OPT_BasicBlockEnumeration y = zVertex.domFrontierEnumerator(ir); y.hasMoreElements();) { OPT_BasicBlock Y = y.next(); // if (idom(Y)!=X) then DF(X) <- DF(X) U Y if (OPT_LTDominatorInfo.getIdom(Y) != X) { DF.set(Y.getNumber()); } } } if (DEBUG) { System.out.println("After up " + DF); } } if (DEBUG) { for (Enumeration<OPT_BasicBlock> bbEnum = ir.cfg.basicBlocks(); bbEnum.hasMoreElements();) { OPT_BasicBlock block = bbEnum.nextElement(); if (block.isExit()) { continue; } System.out.println(block + " DF: " + tree.getDominanceFrontier(block)); } } } /** * Calculate the dominance frontier for the set of basic blocks * represented by a BitVector. * * <p> NOTE: The dominance frontiers for the IR MUST be calculated * BEFORE calling this routine. * * @param ir the governing IR * @param bits the BitVector representing the set of basic blocks * @return a BitVector representing the dominance frontier for the set */ public static OPT_BitVector getDominanceFrontier(OPT_IR ir, OPT_BitVector bits) { OPT_BitVector result = new OPT_BitVector(ir.getMaxBasicBlockNumber() + 1); OPT_DominatorTree dTree = ir.HIRInfo.dominatorTree; for (int i = 0; i < bits.length(); i++) { if (bits.get(i)) { result.or(dTree.getDominanceFrontier(i)); } } return result; } /** * Calculate the iterated dominance frontier for a set of basic blocks * represented by a BitVector. * * <p> NOTE: The dominance frontiers for the IR MUST be calculated * BEFORE calling this routine. * * @param ir The governing IR * @param S The {@link OPT_BitVector} representing the set of basic blocks * @return an {@link OPT_BitVector} representing the dominance frontier for * the set */ public static OPT_BitVector getIteratedDominanceFrontier(OPT_IR ir, OPT_BitVector S) { OPT_BitVector DFi = getDominanceFrontier(ir, S); while (true) { OPT_BitVector DFiplus1 = getDominanceFrontier(ir, DFi); DFiplus1.or(DFi); if (DFi.equals(DFiplus1)) { break; } DFi = DFiplus1; } return DFi; } }