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.ir.BasicBlock;
018import org.jikesrvm.compilers.opt.ir.IR;
019import org.jikesrvm.compilers.opt.util.Tree;
020import org.jikesrvm.compilers.opt.util.TreeNode;
021import org.jikesrvm.util.BitVector;
022
023/**
024 * This class provides the abstraction of a dominator tree
025 *
026 * <p>TODO: we do not support IRs with exception handlers.
027 */
028public class DominatorTree extends Tree {
029  /**
030   * {@code true} if we are computing regular dominators, {@code false} for post-dominators
031   */
032  private final boolean forward;
033
034  /**
035   * The governing IR
036   */
037  private final IR ir;
038
039  /**
040   * A structure used to quickly index into the DominatorVertex tree
041   */
042  private final DominatorTreeNode[] dominatorInfoMap;
043
044  /**
045   * Build a dominator tree from an IR. NOTE: the dominator
046   * information MUST be computed BEFORE calling this method!
047   *
048   * @param ir the governing IR
049   * @param forward are we building regular dominators or post-dominators?
050   */
051  public static void perform(IR ir, boolean forward) {
052    // control for debugging messages.
053    final boolean DEBUG = false;
054
055    if (forward) {
056      ir.HIRInfo.dominatorTree = new DominatorTree(ir, forward);
057      if (ir.options.PRINT_DOMINATORS) {
058        if (DEBUG) {
059          System.out.println("Here is the CFG for method " + ir.method.getName() + "\n" + ir.cfg);
060        }
061        System.out.println("Here is the Dominator Tree for method " +
062                           ir.method.getName() + "\n" +
063                           ir.HIRInfo.dominatorTree);
064      }
065    } else {
066      ir.HIRInfo.postDominatorTree = new DominatorTree(ir, forward);
067      if (ir.options.PRINT_POST_DOMINATORS) {
068        if (DEBUG) {
069          System.out.println("Here is the CFG for method " + ir.method.getName() + "\n" + ir.cfg);
070        }
071        System.out.println("Here is the Post-Dominator Tree for method " +
072                           ir.method.getName() + "\n" +
073                           ir.HIRInfo.postDominatorTree);
074      }
075    }
076  }
077
078  /**
079   * Build a dominator tree from an IR. NOTE: the dominator
080   * information MUST be computed BEFORE calling this
081   * constructor!
082   *
083   * @param ir the governing IR
084   * @param forward are we building regular dominators or post-dominators?
085   */
086  public DominatorTree(IR ir, boolean forward) {
087    this.ir = ir;
088    this.forward = forward;
089
090    // The query methods of dominator information, such as
091    // getDominanceFrontier, dominates, and domFrontierEnumerator
092    // all use ir.getBasicBlock(int).  This method relies on
093    // the basic block map being up to date.  Here we ensure this
094    // property, even though it is needed for computing the dominator
095    // tree.
096    ir.resetBasicBlockMap();
097
098    // allocate the dominator vertex map
099    dominatorInfoMap = new DominatorTreeNode[ir.getMaxBasicBlockNumber() + 1];
100
101    // allocate the tree and root node
102    // Step 1: add all basic blocks to the tree as nodes
103    for (Enumeration<BasicBlock> bbEnum = ir.cfg.basicBlocks(); bbEnum.hasMoreElements();) {
104      BasicBlock block = bbEnum.nextElement();
105      // We treat the exit node as not being part of the CFG
106      if (!forward || !block.isExit()) {
107        addNode(block);
108      }
109    }
110
111    // Step 2: set the root value
112    setRoot(dominatorInfoMap[getFirstNode().getNumber()]);
113
114    // Step 3: Walk the nodes, for each node create link with parent
115    //   Leaf nodes have no links to add
116    for (Enumeration<BasicBlock> bbEnum = ir.cfg.basicBlocks(); bbEnum.hasMoreElements();) {
117      BasicBlock block = bbEnum.nextElement();
118      // skip the exit node
119      if (forward && block.isExit()) {
120        continue;
121      }
122
123      // get the tree node corresponding to "block"
124      DominatorTreeNode blockNode = dominatorInfoMap[block.getNumber()];
125
126      // if parent = null, this is the root of the tree, nothing to do
127      if (LTDominatorInfo.getInfo(block, ir) == null) {
128        System.out.println("info field is null for block: " + block);
129      }
130      BasicBlock parent = LTDominatorInfo.getInfo(block, ir).getDominator();
131      if (parent != null) {
132        DominatorTreeNode parentNode = dominatorInfoMap[parent.getNumber()];
133
134        // tell the parent they have a child
135        parentNode.addChild(blockNode);
136      }
137    }           // for loop
138  }             // method
139
140  /**
141   * Get the first node, either entry or exit
142   * depending on which way we are viewing the graph
143   * @return the entry node or exit node
144   */
145  private BasicBlock getFirstNode() {
146    if (forward) {
147      return ir.cfg.entry();
148    } else {
149      return ir.cfg.exit();
150    }
151  }
152
153  /**
154   * Enumerate the children of the vertex corresponding to a basic
155   * block
156   *
157   * @param bb the basic block
158   * @return an Enumeration of bb's children
159   */
160  public Enumeration<TreeNode> getChildren(BasicBlock bb) {
161    DominatorTreeNode node = dominatorInfoMap[bb.getNumber()];
162    return node.getChildren();
163  }
164
165  /**
166   * Return the parent of the vertex corresponding to a basic
167   * block
168   *
169   * @param bb the basic block
170   * @return bb's parent
171   */
172  public BasicBlock getParent(BasicBlock bb) {
173    DominatorTreeNode node = dominatorInfoMap[bb.getNumber()];
174    return ((DominatorTreeNode) node.getParent()).getBlock();
175  }
176
177  /**
178   * Return the (already calculated) dominance frontier for
179   * a basic block
180   *
181   * @param bb the basic block
182   * @return a BitVector representing the dominance frontier
183   */
184  public BitVector getDominanceFrontier(BasicBlock bb) {
185    DominatorTreeNode info = dominatorInfoMap[bb.getNumber()];
186    return info.getDominanceFrontier();
187  }
188
189  /**
190   * Return the (already calculated) dominance frontier for
191   * a basic block
192   *
193   * @param number the number of the basic block
194   * @return a BitVector representing the dominance frontier
195   */
196  public BitVector getDominanceFrontier(int number) {
197    return getDominanceFrontier(ir.getBasicBlock(number));
198  }
199
200  /**
201   * Does basic block number b dominate all basic blocks in a set?
202   *
203   * @param b the number of the basic block to test
204   * @param bits BitVector representation of the set of basic blocks to test
205   * @return true or false
206   */
207  public boolean dominates(int b, BitVector bits) {
208    for (int i = 0; i < bits.length(); i++) {
209      if (!bits.get(i)) {
210        continue;
211      }
212      if (!dominates(b, i)) {
213        return false;
214      }
215    }
216    return true;
217  }
218
219  /**
220   * Does basic block number "master" dominate basic block number "slave"?
221   *
222   * @param master the number of the proposed "master" basic block
223   * @param slave  the number of the proposed "slave block
224   * @return "master dominates slave"
225   */
226  public boolean dominates(int master, int slave) {
227    BasicBlock masterBlock = ir.getBasicBlock(master);
228    BasicBlock slaveBlock = ir.getBasicBlock(slave);
229    DominatorTreeNode masterNode = dominatorInfoMap[masterBlock.getNumber()];
230    DominatorTreeNode slaveNode = dominatorInfoMap[slaveBlock.getNumber()];
231    return slaveNode.isDominatedBy(masterNode);
232  }
233
234  /**
235   * Does basic block number "master" dominate basic block number "slave"?
236   *
237   * @param master the number of the proposed "master" basic block
238   * @param slave  the number of the proposed "slave block
239   * @return "master dominates slave"
240   */
241  public boolean dominates(BasicBlock master, BasicBlock slave) {
242    DominatorTreeNode masterNode = dominatorInfoMap[master.getNumber()];
243    DominatorTreeNode slaveNode = dominatorInfoMap[slave.getNumber()];
244    return slaveNode.isDominatedBy(masterNode);
245  }
246
247  /**
248   * Creates dominator tree nodes for the passed block and adds them to the
249   * map.
250   * @param b the basic block
251   */
252  private void addNode(BasicBlock b) {
253    DominatorTreeNode node = new DominatorTreeNode(b);
254    dominatorInfoMap[b.getNumber()] = node;
255  }
256
257  /**
258   * Return the distance from the root of the dominator tree to a given
259   * basic block
260   *
261   * @param b the basic block in question
262   * @return <code>b</code>'s depth
263   */
264  public int depth(BasicBlock b) {
265    return dominatorInfoMap[b.getNumber()].getDepth();
266  }
267
268  /**
269   * Return the deepest common dominance ancestor of blocks <code>a</code> and <code>b</code>
270   *
271   * @param a The first basic block
272   * @param b The second basic block
273   * @return the deepest common dominance ancestor of blocks <code>a</code>
274   *        and <code>b</code>
275   */
276  public BasicBlock deepestCommonAncestor(BasicBlock a, BasicBlock b) {
277    DominatorTreeNode n_a = dominatorInfoMap[a.getNumber()];
278    DominatorTreeNode n_b = dominatorInfoMap[b.getNumber()];
279    while (n_a != n_b) {
280      if (n_a.getDepth() > n_b.getDepth()) {
281        n_a = (DominatorTreeNode) n_a.getParent();
282      } else {
283        n_b = (DominatorTreeNode) n_b.getParent();
284      }
285    }
286    return n_a.getBlock();
287  }
288
289}