001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm.compilers.opt.controlflow;
014
015import java.util.Enumeration;
016
017import org.jikesrvm.compilers.opt.OptOptions;
018import org.jikesrvm.compilers.opt.driver.CompilerPhase;
019import org.jikesrvm.compilers.opt.ir.BasicBlock;
020import org.jikesrvm.compilers.opt.ir.IR;
021import org.jikesrvm.compilers.opt.util.TreeNode;
022import org.jikesrvm.util.BitVector;
023
024/**
025 * Calculate dominance frontier for a set of basic blocks.
026 *
027 * <p> Uses the algorithm of Cytron et al., TOPLAS Oct. 91:
028 *
029 * <pre>
030 * for each X in a bottom-up traversal of the dominator tree do
031 *
032 *      DF(X) &lt; - null
033 *      for each Y in Succ(X) do
034 *        if (idom(Y)!=X) then DF(X) &lt;- DF(X) U Y
035 *      end
036 *      for each Z in {idom(z) = X} do
037 *        for each Y in DF(Z) do
038 *              if (idom(Y)!=X) then DF(X) &lt;- DF(X) U Y
039 *        end
040 *      end
041 * </pre>
042 *
043 * <p> TODO: we do not support IRs with exception handlers!!
044 */
045public class DominanceFrontier extends CompilerPhase {
046  /**
047   * Should this phase be performed?  This is a member of a composite
048   * phase, so always return {@code true}.  The parent composite phase will
049   * dictate.
050   * @param options controlling compiler options
051   * @return {@code true}
052   */
053  @Override
054  public final boolean shouldPerform(OptOptions options) {
055    return true;
056  }
057
058  /**
059   * Return this instance of this phase. This phase contains no
060   * per-compilation instance fields.
061   * @param ir not used
062   * @return this
063   */
064  @Override
065  public CompilerPhase newExecution(IR ir) {
066    return this;
067  }
068
069  /**
070   * Return a String representation for this phase
071   * @return a String representation for this phase
072   */
073  @Override
074  public final String getName() {
075    return "Dominance Frontier";
076  }
077
078  /**
079   * Should the IR be printed either before or after performing this phase?
080   *
081   * @param options controlling compiler options
082   * @param before {@code true} iff querying before the phase
083   * @return {@code false}
084   */
085  @Override
086  public final boolean printingEnabled(OptOptions options, boolean before) {
087    return false;
088  }
089
090  /**
091   * Calculate the dominance frontier for each basic block in the
092   * CFG. Stores the result in the DominatorTree for the governing
093   * IR.
094   *
095   * <p> NOTE: The dominator tree MUST be calculated BEFORE calling this
096   *      routine.
097   *
098   * @param ir the governing IR
099   */
100  @Override
101  public void perform(IR ir) {
102    final boolean DEBUG = false;
103    // make sure the dominator computation completed successfully
104    if (!ir.HIRInfo.dominatorsAreComputed) {
105      return;
106    }
107    // make sure dominator tree is computed
108    if (ir.HIRInfo.dominatorTree == null) {
109      return;
110    }
111    // for each X in a bottom-up traversal of the dominator tree do
112    DominatorTree tree = ir.HIRInfo.dominatorTree;
113    for (Enumeration<TreeNode> x = tree.getBottomUpEnumerator(); x.hasMoreElements();) {
114      DominatorTreeNode v = (DominatorTreeNode) x.nextElement();
115      BasicBlock X = v.getBlock();
116      if (DEBUG) {
117        System.out.println("Computing frontier for node " + X);
118      }
119      BitVector DF = new BitVector(ir.getMaxBasicBlockNumber() + 1);
120      v.setDominanceFrontier(DF);
121      // for each Y in Succ(X) do
122      for (Enumeration<BasicBlock> y = X.getOut(); y.hasMoreElements();) {
123        BasicBlock Y = y.nextElement();
124        // skip EXIT node
125        if (Y.isExit()) {
126          continue;
127        }
128        // if (idom(Y)!=X) then DF(X) <- DF(X) U Y
129        if (LTDominatorInfo.getIdom(Y, ir) != X) {
130          DF.set(Y.getNumber());
131        }
132      }
133      if (DEBUG) {
134        System.out.println("After local " + DF);
135      }
136      //        for each Z in {idom(z) = X} do
137      for (Enumeration<TreeNode> z = tree.getChildren(X); z.hasMoreElements();) {
138        DominatorTreeNode zVertex = (DominatorTreeNode) z.nextElement();
139        BasicBlock Z = zVertex.getBlock();
140        if (DEBUG) {
141          System.out.println("Processing Z = " + Z);
142        }
143        // for each Y in DF(Z) do
144        for (Enumeration<BasicBlock> y = zVertex.domFrontierEnumerator(ir); y.hasMoreElements();) {
145          BasicBlock Y = y.nextElement();
146          // if (idom(Y)!=X) then DF(X) <- DF(X) U Y
147          if (LTDominatorInfo.getIdom(Y, ir) != X) {
148            DF.set(Y.getNumber());
149          }
150        }
151      }
152      if (DEBUG) {
153        System.out.println("After up " + DF);
154      }
155    }
156    if (DEBUG) {
157      for (Enumeration<BasicBlock> bbEnum = ir.cfg.basicBlocks(); bbEnum.hasMoreElements();) {
158        BasicBlock block = bbEnum.nextElement();
159        if (block.isExit()) {
160          continue;
161        }
162        System.out.println(block + " DF: " + tree.getDominanceFrontier(block));
163      }
164    }
165  }
166
167  /**
168   * Calculate the dominance frontier for the set of basic blocks
169   * represented by a BitVector.
170   *
171   * <p> NOTE: The dominance frontiers for the IR MUST be calculated
172   *    BEFORE calling this routine.
173   *
174   * @param ir the governing IR
175   * @param bits the BitVector representing the set of basic blocks
176   * @return a BitVector representing the dominance frontier for the set
177   */
178  public static BitVector getDominanceFrontier(IR ir, BitVector bits) {
179    BitVector result = new BitVector(ir.getMaxBasicBlockNumber() + 1);
180    DominatorTree dTree = ir.HIRInfo.dominatorTree;
181    for (int i = 0; i < bits.length(); i++) {
182      if (bits.get(i)) {
183        result.or(dTree.getDominanceFrontier(i));
184      }
185    }
186    return result;
187  }
188
189  /**
190   * Calculate the iterated dominance frontier for a set of basic blocks
191   * represented by a BitVector.
192   *
193   * <p> NOTE: The dominance frontiers for the IR MUST be calculated
194   *    BEFORE calling this routine.
195   *
196   * @param ir The governing IR
197   * @param S  The {@link BitVector} representing the set of basic blocks
198   * @return an {@link BitVector} representing the dominance frontier for
199   *    the set
200   */
201  public static BitVector getIteratedDominanceFrontier(IR ir, BitVector S) {
202    BitVector DFi = getDominanceFrontier(ir, S);
203    while (true) {
204      BitVector DFiplus1 = getDominanceFrontier(ir, DFi);
205      DFiplus1.or(DFi);
206      if (DFi.equals(DFiplus1)) {
207        break;
208      }
209      DFi = DFiplus1;
210    }
211    return DFi;
212  }
213}
214
215
216